У меня есть коллекция Book, в которой содержаться список книг. Я создаю бинарный файл и записываю в него эти данные. С записью проблем нет, файл создается и содержит все введенные мною данные. Вопрос, а как правильно считывать эти данные из бинарного файла, что бы я потом мог их просмотреть?
// Если файла не существует, то создаем
if (!File.Exists(_path + "\\Books.bin"))
{
_books.Add(new Books
{
BookName = "Книга 1",
Author = "Автор 1",
PageCount = 200,
Year = 2000
});
_books.Add(new Books
{
BookName = "Книга 2",
Author = "Автор 2",
PageCount = 400,
Year = 2010
});
_books.Add(new Books
{
BookName = "Книга 3",
Author = "Автор 3",
PageCount = 820,
Year = 2005
});
using (var fileStream = new FileStream(_path + "\\Books.bin", FileMode.Create))
{
using (BinaryWriter writer = new BinaryWriter(fileStream))
{
foreach (var book in _books)
{
writer.Write(book.BookName);
writer.Write(book.Author);
writer.Write(book.PageCount);
writer.Write(book.Year);
}
writer.Close();
}
}
}
// Читаем файл
using (BinaryReader reader = new BinaryReader(File.Open(_path + "\\Books.bin", FileMode.Open)))
{
}
В ответе @Rekssel чтение прекращается с помощью проверки PeekChar()
. Один из двух общепринятых способов: читаем, пока не встретим маркер конца.
Другой способ: в начале записываем длину данных. При чтении, соответственно, сперва считываем эту длину.
// Запись
using (var fileStream = new FileStream(path, FileMode.Create))
using (var writer = new BinaryWriter(fileStream))
{
writer.Write(_books.Count);
foreach (var book in _books)
{
writer.Write(book.BookName);
writer.Write(book.Author);
writer.Write(book.PageCount);
writer.Write(book.Year);
}
}
// Чтение
using (var fileStream = new FileStream(path, FileMode.Open))
using (var reader = new BinaryReader(fileStream))
{
int count = reader.ReadInt32();
_books = new List<Books>(count);
for (int i = 0; i < count; i++)
{
_books.Add(new Books
{
BookName = reader.ReadString(),
Author = reader.ReadString(),
PageCount = reader.ReadInt32(),
Year = reader.ReadInt32()
});
}
}
Недостаток этого способа в том, что при записи нужно знать длину данных, а это не всегда известно, допустим, у нас источник данных IEnumerable
или IQueryable
.
Достоинство этого способа в том, что при чтении можно сразу выделить буфер нужной длины. При этом не будет лишних переаллокаций в дальнейшем.
Предположу, что так:
using (BinaryReader reader = new BinaryReader(File.Open(path, FileMode.Open)))
{
while (reader.PeekChar() > -1)
{
_books.Add(new Books
{
BookName = reader.ReadString(),
Author = reader.ReadString(),
PageCount = reader.ReadInt32(),
Year = reader.ReadInt32()
});
}
}
Или так:
using (BinaryReader reader = new BinaryReader(File.Open(path, FileMode.Open)))
{
while (reader.PeekChar() > -1)
{
Books book = new Books();
book.BookName = reader.ReadString();
book.Author = reader.ReadString();
book.PageCount = reader.ReadInt32();
book.Year = reader.ReadInt32();
_books.Add(book);
}
}
Используйте BinaryFormatter.
Например:
Для записи:
BinaryFormatter formatter = new BinaryFormatter();
using (FileStream fs = new FileStream("books.bin", FileMode.OpenOrCreate))
{
formatter.Serialize(fs, "ваш_объект");
}
Для считывания:
BinaryFormatter formatter = new BinaryFormatter();
using (FileStream fs = new FileStream("books.bin", FileMode.OpenOrCreate))
{
"тип_вашего_объекта" obj = ("тип_вашего_объекта")formatter.Deserialize(fs);
}
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Можно как-то отловить открытие папки в проводнике на c# и передать путь в мою программу? Пытаюсь создать свой клон китайского clover'a