Иллюстрированный самоучитель по VB.NET

       

Запись в файл


Начнем с рассмотрения команды, часто встречающейся при работе с файловыми потоками:

Dim myFileStream As New FileStream("MyFile.txt". FileMode.OpenOrCreate, FileAccess.Write)

Как видно из приведенного фрагмента, эта версия конструктора FileStream получает имя файла (заданное по отношению к текущему каталогу, если не указано полное имя) и два параметра, значения которых относятся к перечисляемым типам FileMode и FileAccess соответственно. Таким образом, в нашем примере конструктор Fi1eStream либо создает файл с именем MyFile.txt в текущем каталоге, либо открывает его, если файл с таким именем уже существует. В любом случае программа сможет записывать данные в файл. Часто встречаются и другие конструкторы класса Fi leStream:

  • Sub New(String, FileMode): создает объект FileStream с заданным именем и в заданном режиме (см. ниже описание FileMode).

  • Sub NewCString, FileMode, FileAccess): создает объект FileStream в заданном режиме, с заданными правами чтения/записи и совместного доступа.

    Допустимыми значениями перечисляемого типа FileAccesS являются Read, Write и ReadWri te. Основные значения перечисляемого типа Fi I eMode перечислены в табл. 9.9. Учтите, что некоторые из них требуют особых привилегий для операций с файлами.

    Таблица 9.9. Значения перечисляемого типа FileMode



    Значение

    Описание

    Append Открыть существующий файл (или создать несуществующий). Указатель текущей позиции перемещается в конец файла для записи. Используется совместно с FileAccess.Write
    Create Создать новый файл. Внимание — существующий файл автоматически стирается!
    CreateNew Создать новый файл. Отличается от Create тем, что для существующего файла инициируется исключение IOException
    Open Открыть существующий файл. Если файл не существует, инициируется исключение IOException. Используется совместно с FileIOPermissionAccess.Read
    OpenOrCreate Открыть или создать файл
    Truncate Открыть существующий файл, удалить текущее содержимое
    <
    Объекты FHeStream также возвращаются следующими методами классов File и FHelnfo: File.Create, File.Open, File.OpenRead, File.OpenWrite, FHeInfo.Create, FHelnfo.Open, FHelnfo.OpenRead.

    Хотя файловые потоки поддерживают произвольный доступ методом Seek, базовый класс-FileStream ориентирован исключительно на операции с байтами, поэтому его возможности ограничиваются простой записью байта или массива байтов методами WriteByte и Write. Приведенный ниже фрагмент создает файл, показанный на рис. 9.2:

    Option Strict On Imports System.IO

    Module Modulel

    Sub Main()

    Dim i As Integer

    Dim theBytes(255) As Byte

    For i = 0 To 255

    theBytes(i) = CByte(i)

    Next

    Dim myFileStream As FileStream

    Try

    myFileStream = New FileStream("C:\foo",

    Fi1eMode.OpenOrCreate. FileAccess.Write)

    myFlleStream.Write(theBytes, 0. 256) Finally

    If Not (myFileStream Is Nothing) Then

    myFileStream.Close()

    End Try

    DisplayAFile("C:\foo")

    End Sub

    End Module



    Рис. 9.2. Запись двоичных данных в файл

    После выполнения этого фрагмента записанные данные можно прочитать методом Read, а также воспользоваться методом Seek для перехода к произвольной позиции в файле. Впрочем, как это всегда бывает при работе с неструктурированными потоками байтов, вам придется самостоятельно преобразовать двоичные данные в более полезный формат. В результате сейчас трудно найти более содержательный пример, чем простой вывод записанных чисел процедурой, приведенной ниже:

    Sub ReadDataBack()

    Dim myFileStream As Stream.i As Integer Try

    myFileStream = New FileStream("C:\foo",

    FileMode.Open. FileAccess.Read)

    For i = 0 To 255

    Console.Write(myFileStream.ReadByte) Next

    Catch e As Exception MsgBox(e.Message)

    Finally

    If Not (myFileStream Is Nothing) Then

    myFileStream.Close()

    End Try

    End Sub

    Метод Length базового класса Stream всегда позволяет прочитать нужное количество байтов в цикле независимо от структуры файла. Например, следующая процедура читает файл по одному байту.


    Обнаруженные исключения просто передаются вызывающей стороне; вероятно, в реальной программе следовало бы определить новый класс исключения:

    Sub DisplayAFile(ByVal theFileName As String)

    Dim theFile As FileStream

    Dim i As Long Try

    theFile = New FileStream(theFileName.

    Fi1eMode.Open,Fi1eAccess.Read)

    For i = 0 To (theFile.Length - 1)

    ' Вычесть 1. поскольку отсчет начинается с 0

    Consolе.Write(theFiIe.ReadByte) Next

    Catch Throw Finally

    If Not (theFile Is Nothing) Then theFile.Close()

    End Try

    End Sub

    Если файл имеет небольшие размеры и легко помещается в памяти, воспользуйтесь одним вызовом Read и прочитайте весь файл в байтовый массив нужного размера. Такая операция выполняется значительно быстрее.

    Другой распространенный вариант посимвольного чтения основан на том, что метод ReadByte в конце потока возвращает -1. Основной цикл выглядит примерно так:

    Dim i As Integer i = theFile.ReadByte

    Do Until i =-1

    Console.Write(i)

    i = theFile.ReadByte Loop

    Чтение/запись файла на уровне отдельных байтов используется не так уж часто; в основном это необходимо при выполнении низкоуровневых операций. При операциях более высокого уровня часто используется стандартный прием — неструктурированный файловый поток передается конструктору потока, обладающего более широкими возможностями. Этот принцип называется многоуровневой организацией потоков. Например, неструктурированный файловый поток можно передать потоку, автоматически распознающему текст. Разные способы многоуровневой организации потоков описаны в нескольких ближайших разделах. Но прежде, чем переходить к этим разделам, просмотрите табл. 9.10 — в ней перечислены основные методы и свойства базового класса FileStream. В дальнейшем мы будем использовать эти методы, хотя базовый файловый поток будет скрыт потоками более высоких уровней.

    Таблица 9.10. Основные члены класса RleStream



    Метод/свойство



    Описание



    Handle (свойство)



    Файловый манипулятор операционной системы для файла, инкапсулированного в объекте FileStream. Свойство доступно для чтения



    Length (свойство)



    Размер потока в байтах. Свойство доступно для чтения



    Name (свойство)



    Уточненное имя, переданное конструктору FileStream



    Position (свойство)



    Текущая позиция для операций чтения или записи в потоке (нумерация позиций начинается с нуля). Свойство доступно для чтения и записи



    Close



    Закрывает поток и освобождает все связанные с ним ресурсы



    Flush



    Пересылает все данные из буфера в устройство. Автоматически вызывается при вызове Close



    Lock(ByVal position As Long,

    ByVal length As Long)



    Блокирует доступ ко всему файлу или его части со стороны других

    процессов (нумерация позиций начинается с нуля)



    Read(ByVal array() As Byte,

    ByVal offset As Integer,

    ByVal count As Integer)



    Читает заданное количество байтов в массив из файлового

    потока начиная с заданной позиции





    ReadByte





    Читает один байт из файла и перемещает указатель текущей

    позиции на один байт вперед



    Seek(ByVal offset As Long,

    ByVal origin As SeekOrigin)



    Устанавливает указатель текущей позиции в потоке в заданное

    положение



    Unlock(ByVal position As Long,

    ByVal length As Long)



    Снимает блокировку с ранее заблокированной части файла

    (нумерация позиций начинается с нуля)



    Write(ByVal array() As Byte,

    ByVal offset As Integer,

    ByVal count As Integer)



    Записывает заданное количество байт из массива в файловый

    поток начиная с заданной позиции





    WriteByte



    Записывает байт в текущую позицию файлового потока


    Содержание раздела