Чтение и запись двоичных файлов делается обычно с помощью класса
FileStream
.
Класс FileStream
Экземпляр
FileStream
используется для чтения или записи данных файла. Чтобы создать
FileStream
, необходимо иметь данные четырех видов:
□ Файл для доступа.
□ Режим, который указывает, как необходимо открыть файл. Например, собираетесь ли вы создать новый файл или открыть существующий файл, и, если открывается существующий файл, должна ли какая-либо операция записи интерпретироваться
как перезапись содержимого файла или как добавление к файлу.
□ Доступ, указывающий, как будет осуществляться доступ к файлу, будет ли выполняться чтение или запись в файл или и то и другое.
□ Общий доступ. Другими словами, будет ли осуществляться исключительный доступ к файлу, или желательно, чтобы другие потоки могли одновременно получать доступ к этому файлу. Если так, то должны ли другие потоки иметь доступ для чтения файла, записи в него или для того и другого.
Первый из этих видов данных представлен обычно строкой, которая содержит полное имя пути доступа файла, и в этой главе будут рассматриваться только те конструкторы, которые требуют строку. Помимо этих конструкторов, существуют и некоторые другие, которые получают дескриптор файла Windows в стиле старого Windows API. Остальные три вида данных представлены тремя перечислениями .NET, называемыми соответственно
FileMode
,
FileAccess
и
FileShare
. Значения этих перечислений должны быть понятны из названий.
Перечисление
Значения
FileMode
(режим файла)
Append
(добавить),
Create
(создать),
CreateNew
(создать новый),
Open
(открыть),
OpenOrCreate
(открыть или создать),
Truncate
(обрезать)
FileAccess
(доступ к файлу)
Read
(чтение),
ReadWrite
(чтение-запись),
Write
(запись)
FileShare
(общий доступ к файлу)
None
(нет),
Read
(чтение),
ReadWrite
(чтение-запись),
Write
(запись)
Отметим, что в случае
FileMode
могут порождаться исключения, если запросить режим, который несогласован с существующим статусом файла.
Append
,
Open
и
Truncate
будут порождать исключение, если файл еще не существует, a
CreateNew
будет порождать исключение, если он существует.
Create
и
OpenOrCreate
будут удовлетворять любому сценарию, но
Create
будет удалять любой существующий файл для замены его новым, вначале пустым файлом.
Существует большое число конструкторов для
FileSream
. Три простейшие из них работают следующим образом:
// создает файл с доступом read-write и предоставляет другим потокам
// доступ на чтение
FileStream fs = new FileStream(@"C:\C# Projects\Projects.doc", FileMode.Create);
// как и выше, но мы получаем доступ к файлу только на запись
FileStream fs2 = new FileStream(@"C:\C# Projects\Projects2.doc", FileMode.Create, FileAccess.Write);
// как и выше, но другие потоки не имеют никакого доступа
к файлу,
// пока fs3 открыт
FileStream fs3 = new FileStream(@"C:\C# Projects\Projects3.doc", FileMode.Create, FileAccess.Read, FileShare.None);
Из этого кода можно видеть, что эти перегружаемые версии конструкторов предоставляют значения по умолчанию
FileAcces.ReadWrite
и
FileShare.Read
для третьего и четвертого параметров. Также можно создать файловый поток из экземпляра
FileInfo
:
FileInfo MyFile4 = new FileInfo(@"C:\C# Projects\Projects4.doc");
FileStream fs4 = MyFile4.OpenRead;
FileInfo MyFile5 = new FileInfo(@"C:\C# Projects\Projects5.doc");
FileStream fs5 = MyFile5.OpenWrite;
FileInfo MyFile6 = new FileInfo(@"C:\C# Projects\Projects6.doc");
FileInfo MyNewFile = new FileInfo(@"C:\C# Projects\ProjectsNew.doc");
FileStream fs7 = MyNewFile.Create;
FileInfo.OpenRead
поставляет поток, предоставляющий доступ только для чтения к существующему файлу, в то время как FileInfo.OpenWrite предоставляет доступ для чтения-записи.
FileInfo.Open
позволяет явно определить параметры режима, доступа и общего доступа.
Не забудьте, что по окончании работы поток необходимо закрыть:
fs.Close;
Закрытие потока освобождает связанные с ним ресурсы и позволяет другим приложениям настроить потоки на тот же самый файл. Для чтения и записи данных в поток
FileStream
реализует ряд методов.
Метод
ReadByte
является простейшим способом чтения данных: он захватывает один байт из потока и преобразовывает результат в int, имеющее значение между 0 и 255. По достижении конца потока возвращается -1:
int NextByte = fs.ReadByte;
Если желательно прочитать несколько байтов за один раз, можно вызвать метод
Read
, который читает указанное число байтов в массиве.
Read
возвращает реально прочитанное число байтов, если это значение равно нулю, то это говорит о конце потока:
// считать 100 байтов int nBytes = 100;
byte [] ByteArray = new byte[nBytes];
int nBytesRead = fs.Read(ByteArray, 0, nBytes);
Второй параметр в методе
Read
— смещение, которое указывает операции
Read
начать заполнение массива с элемента, отличного от первого.
Если требуется записать данные в файл, то существует два параллельных метода
WriteByte
и
Write
.
WriteByte
записывает один байт в поток:
byte Next Byte = 100; fs.WriteByte(NextByte);
Write
, с другой стороны, записывает массив байтов:
// чтобы записать 100 байтов
int nBytes = 100;
byte [] ByteArray = new byte[nBytes];
// здесь массив заполняется значениями, которые надо записать
fs.Write(BуteArray, 0, nBytes);
Как и для метода
Read,
второй параметр позволяет начать записывать с некоторого места, отличного от начала массива. Оба метода