Работа с файлами и организация печати.

При проектировании приложения достаточно часто возникает необходимость работать непосредственно с файлами. Это требуется, например, для добавления, удаления файлов или каталогов (папок), записи данных в файлы или чтения из них как программно, так и в интерактивном режиме. Необходимость работы с файлами возникает также при создании программы инсталляции разработанного приложения на пользовательские компьютеры, чтения данных из файлов при инициализации приложения с использованием файлов настройки, организации вывода файлов на печать. Для этих целей Visual Basic 6 предоставляет полный набор функций, работающих с файлами, папками и устройствами, дающий возможность производить с ними все необходимые действия.
В Visual Basic 6 существует понятие типа файла, который определяется организационной структурой хранения информации в файле и способом доступа к этой информации. Принято выделять следующие типы файлов.
Файлы последовательного доступа. Как правило, это текстовые файлы или аналогичные им. Такие файлы представляют собой последовательность символов. При этом данные могут быть с разделителями или без разделителей, то есть содержание файла может иметь некую структуру. Структурной единицей содержимого в подобных файлах, как правило, является строка. Примерами этих файлов могут служить текстовые файлы и файлы инициализации программ.
Файлы произвольного доступа. Это структурированные файлы, которые содержат информацию в виде записей. Примером могут служить файлы баз данных.
Двоичные (бинарные) файлы. Файлы с побайтным доступом. В принципе, это те же файлы с последовательным доступом, но информация в них не организована в строки. Особенность данных файлов — работа с байтами или блоками байтов. К таким файлам можно отнести выполняемые программы, файлы динамических библиотек, файлы документов Word.
Подобное деление файлов на типы достаточно условно и определяется особенностями организации файлов и доступа к данным в них. Например, файл с последовательным доступом можно открыть и в режиме двоичного доступа. Если этот файл имеет разделители, то для работы с ним придется написать специальную процедуру обработки разделителей и разбора данных, так как двоичный доступ обеспечивает побайтную запись/чтение из файла. Очевидно, что это неудобно. Именно поэтому и введено условное деление файлов на типы в зависимости от формата файла и доступа к данным. Соответственно сгруппированы и функции Visual Basic для записи/чтения данных. Мы рассмотрим работу с каждым из типов файлов, понимая, что такое разделение на типы достаточно условно, но позволяет обеспечить наиболее эффективную обработку данных для каждого типа.
Замечание
Вероятно, более корректным было бы сказать не файл последовательного доступа, а файл, открытый для последовательного доступа, не двоичный файл, а файл, открытый для двоичного доступа. Однако далее будем придерживаться именно такой терминологии, которая указывает тип файла.
Тип файла задает оптимальный набор функций записи и чтения данных из файла. Поэтому при работе с файлами для написания эффективной программы всегда необходимо иметь представление о типах файлов, с которыми будет работать программа, и об организации хранения данных в этих файлах. Это дает возможность обеспечить оптимальный доступ и использовать соответствующие этому доступу функции.
Традиционный подход при работе с файлами
Традиционный подход при работе с файлами остается неизменным практически с самых первых версий Visual Basic и заключается в использовании функций и операторов, обеспечивающих прямой доступ к информации в файлах. Функции и операторы, используемые при работе с файлами, приведены в табл. 9.1. В столбце Тип файла этой таблицы приняты следующие сокращения типов файлов:

  • П — файл последовательного доступа;
  • Пр — файл произвольного доступа;
  • Б — бинарный файл.

В данной главе мы рассмотрим только основные функции и операторы, необходимые для получения навыков работы с файлами.
Таблица 9.1. Функции и операторы для работы с файлами



 
Для удобства сгруппируем функции и операторы по выполняемому действию, как это принято в Visual Basic. Такое объединение удобно при выборе функции или оператора для выполнения необходимых действий с файлами (табл. 9.2).
Таблица 9.2. Функции и операторы для работы с файлами по группам



Открытие файлов
Как было указано выше, работа с каждым из типов файлов имеет свои особенности. Однако есть два действия, общие для всех типов файлов — их открытие и закрытие.
Понятно, что перед тем как записать данные в файл или прочитать данные из файла, необходимо сначала открыть этот файл. Открытие файла выполняется оператором open:
Open pathName For mode [access] [lock] As [#]fileNumber [Len=recLength]
где:

  • pathName — полное имя файла;
  • mode — режим доступа к файлу. Может принимать следующие значения: Append, Binary, Input, Output или Random;
  • access — тип доступа к файлу. Определяет характер действий с файлом — чтение или запись данных. Может принимать значения: Read (Чтение), Write (Запись) или Read/Write (Чтение/Запись);
  • lock — тип разрешения доступа к файлу другим процессам. Определяет возможность одновременной работы с файлом нескольких приложений или нескольких пользователей. Может принимать значения: Shared (Общий), Lock Read (Блокировка чтения), Lock Write (Блокировка записи) или Lock Read Write (Блокировка чтения и записи);
  • fileNumber — целочисленное выражение, задающее идентификатор файла (дескриптор). Может иметь значение от 1 до 511 включительно;
  • recLength — число, определяющее размер буфера данных для записи/чтения в файлах прямого доступа. Для файлов произвольного доступа это число задает длину одной записи файла. Может иметь значение до 32,767 (байтов).

При работе оператора Open создается специальный счетчик номеров (идентификаторов) открытых файлов (в операторе это параметр fileNumber) для однозначного определения файла, с которым программа работает в текущий момент.
Если указанный в операторе open файл не найден по заданному пути или не существует, он будет создан этим оператором для режимов доступа Append, Binary, output или Random. Для режима доступа input новый файл не создается.
Важной особенностью режимов доступа является возможность многократного открытия файла для режимов Binary, input и Random, то есть файл можно открыть несколько раз с разными номерами. Но для режимов доступа Output и Append, используемых для записи данных, это недопустимо.
Если номер открываемого файла специально не контролируется и не задается программой, его можно узнать с помощью функции FreeFile, возвращающей последний свободный номер открываемого файла.
Замечание
При использовании оператора Open необходимо, чтобы режим доступа соответствовал типу открываемого файла.
Закрытие файлов
Закрытие файлов выполняется очень просто. Для этого необходимо использовать оператор close, имеющий следующий синтаксис:
Close [fileNumberLlist]
где fileNumberLlist — список закрываемых файлов, представленных номерами файлов и перечисляемых через запятую: [#fileNumber] [,#fileNumber] . . . [,# fileNumber]. При этом номер файла аналогичен номеру файла в функции open.
Предупреждение
Необходимо иметь в виду, что если список файлов не указан, оператор close закрывает все открытые файлы.
 
Работа с файлами последовательного доступа
Файлы последовательного доступа — это, как правило, текстовые файлы, то есть последовательности ASCII-символов, организованные в строки. Примером может служить файл инициализации Windows NT ( 1).
При открытии файлов последовательного доступа возможны три режима доступа:

  • Input — открыт для последовательного чтения данных;
  • Output — открыт для последовательной записи данных, при этом информация записывается всегда с начала файла (предыдущая затирается, если в файле уже что-то записано);
  • Append — открыт для добавления данных к уже имеющимся в файле. 

Чтение данных
Чтение данных из файла последовательного доступа выполняется с помощью функции Input и операторов Input # и Line Input #. Рассмотрим эти функции и операторы.
Функция Input имеет следующий синтаксис:
Input(number, #fileNumber)
где:

  • number — целое число, которое задает количество считываемых из файла символов;
  • fileNumber — номер файла, аналогичный номеру файла в операторе open.

Функция Input считывает из файла заданное количество символов и обычно используется для чтения данных, записанных в файл оператором print #.
Замечание
Следует иметь в виду, что функция input требует знания количества считываемых символов. Поэтому для чтения данных из файла необходимо предварительно вычислить его длину с помощью функции FileLen.
Если в программе требуется прочитать данные из файла, в котором информация в строках имеет структуру с разделителями (в качестве разделителей используются запятые), необходимо применить оператор Input #:
Input #fileNumber, varlist
где:

  • fileNurnber — номер файла, аналогичный номеру файла в операторе open;
  • varlist — список переменных.

При работе этого оператора сначала считывается целая строка, а затем подстроки, отделенные разделителями (запятыми), помещаются в соответствующие переменные списка. Для корректной работы оператора строки файла должны иметь заданную структуру с разделителями. Обычно этот оператор используется в паре с оператором записи write #.
Для чтения всего содержимого файла при помощи оператора Input # необходимо организовать циклическое считывание данных из файла, поскольку данные считываются этим оператором по строкам.
Для построчного чтения данных из последовательного файла применяется оператор Line Input #. Синтаксис этого оператора следующий:
Line Input # fileNurnber, varName
где:

  • fileNurnber — номер файла, аналогичный номеру файла в операторе open;
  • varName — имя переменной.

Оператор Line Input # посимвольно считывает всю строку данных из файла и помещает ее в строковую переменную. При этом разделителем строк в файле служит стандартный разделитель строк символ возврата каретки CHR(13) или последовательность символов возврата каретки и перевода строки CHR(13) + CHR(10), причем в переменную varName эти разделители не вставляются.
Замечание
Обычно оператор Line Input # используется в паре с оператором Print #.
Для того чтобы прочитать все данные из файла при помощи оператора Line Input #, необходимо организовать цикл чтения данных.
Для изучения функций и операторов, предназначенных для работы с файлами, создадим небольшое приложение. Выполните следующие действия:
1. Создайте новый стандартный проект. Для этого в меню File (Файл) выберите команду New Project (Создать новый) и в окне выбора типа проекта дважды щелкните мышью на значке Standard EXE.
2. Присвойте проекту имя MyFileProject. Используйте для этого окно свойств проекта, которое можно вызвать командой Project1 Properties (Свойства Project1) меню Project (Проект). После переименования проекта эта команда именуется MyFileProject Properties (Свойства MyFileProject).
3. Для выбора файлов потребуются диалоговые окна открытия и сохранения файлов. С помощью диалогового окна Components (Компоненты), вызываемого командой Components меню Project (Проект), подключите к проекту библиотеку Microsoft Common Dialog Control 6.0 и нажмите кнопку ОК.
4. Переименуйте форму проекта, присвоив ей название FormForFile.
5. В свойство caption формы введите заголовок Работаем с файлами.
6. Добавьте в форму элемент управления типа TextBox для ввода/вывода данных и присвойте ему имя txtFile. Придайте текстовому полю достаточно большие размеры, чтобы оно занимало практически все пространство формы. Установите свойство поля Multi-Line в значение True.
7. Добавьте в форму элемент управления CommonDialog, дважды щелкнув мышью кнопку CommonDialog на панели элементов управления.
Совет
Если панель элементов управления отсутствует на экране, для ее отображения в меню View (Вид) выберите команду ToolBox (Панель инструментов).
8. Присвойте созданному объекту типа CommonDialog имя cdCommonDialog.
9. Для фильтрации файлов в свойство Filter объекта cdCommonDialog введите следующий текст: Все файлы (*. *) |*. * | Текстовые файлы (*. txt) \ *. txt \.
10. Добавьте В форму FormForFile кнопку управления типа CommandButton,
дважды щелкнув мышью кнопку CommandButton на панели элементов управления.
11. После появления объекта в форме назовите эту кнопку cbstart и присвойте свойству Caption значение Выполнить. Созданная в форме кнопка cbstart будет служить для выполнения действий по событию кнопки Click.
Созданное тестовое приложение показано на  2.
Полученное приложение можно теперь использовать для изучения работы с файлами. Запрограммируем приложение на чтение данных из файла последовательного доступа. Для этого откроем окно редактора кода и введем следующий код:
Dim strFileName As String
Dim strFileContent As String
Dim nFreeFile As Integer
Dim nFileLenght As Integer
Private Sub cbStart_Click()
cdCommonDialog.ShowOpen
strFileName = cdCommonDialog.FileName
nFreeFile = FreeFile
If strFileName <> "" Then
Open strFileName For Input As nFreeFile
nFileLenght = FileLen(strFileName)
strFileContent = Input(nFileLenght, #nFreeFile)
txtFile.Text = strFileContent
Close
End If
End Sub
Работающее приложение показано на  3. В данном случае при нажатии кнопки Выполнить открывается диалоговое окно поиска файла. Путь и имя файла, возвращаемое диалоговым окном, хранятся в переменной strFileName. Найденный файл (он должен быть текстовым) открывается при помощи оператора open для чтения данных. Функция input считывает сразу весь файл в переменную strFileContent, содержимое которой затем помещается в текстовое поле txtFile. После выполнения всех действий файл закрывается оператором close.
Чтобы прочитать данные при помощи оператора Line Input #, необходимо заменить текст кода, расположенный сразу после оператора open, на следующий:
Do While Not EOF(nFreeFile)
Line Input #nFreeFile, strFileContent
txtFile.Text = txtFile.Text + strFileContent +Chr$(13) + Chr$(10) Loop Close
В этом цикле данные из файла построчно считываются в переменную strFileContent и помещаются в текстовое поле txtFile. Цикл работает до достижения конца файла, который контролируется функцией EOF. Применение цикла не требует знания длины файла, что иногда предпочтительнее.
Для изучения работы оператора input # добавьте в форму еще одно текстовое поле. Назовите его txtNumber И установите свойство поля DataFormat
в значение Number. Текст в приложении после оператора open необходимо заменить на следующий:
Dim nFileContent As Integer
Input #nFreeFile, strFileContent, nFileContent
txtFile.Text = strFileContent
txtNumber.Text = nFileContent
Close
Работающее приложение показано на  4. При этом строки открываемого файла имеют структуру, аналогичную следующей строке:
Это файл для проверки функций, 100
то есть текст и число расположены через запятую.
Переход на заданную позицию в файле
Переход на заданную позицию в файле можно организовать с помощью оператора seek, имеющего следующий синтаксис:
Seek #fileNumber, position
где:

  • fileNumber — номер файла, аналогичный номеру файла в операторе open;
  • position — целочисленное выражение, задающее позицию указателя в файле. Позиционирование при этом выполняется посимвольно.

Оператор seek устанавливает указатель на требуемую позицию. Если после этого использовать функции чтения или записи, то действие этих функций будет выполняться начиная с позиции указателя, найденного оператором Seek.
Можно в код приложения MyFileProject непосредственно перед функцией input вставить выражение, задающее позиционирование:
Seek #nFreeFile, 77
nFileLenght = nFileLenght — 76
В этом случае данные из файла будут считаны начиная с 77 по счету символа от начала и до конца файла. При этом необходимо уменьшить число считываемых символов, поскольку считывается весь файл.
Запись данных
Данные в файл последовательного доступа записываются с помощью операторов print # и write #. Оператор write # дополнительно автоматически вставляет в файл разделители, но не дает гибкости при управлении форматированием данных. Как можно было заметить при изучении функций чтения данных, каждая из функций записи работает в паре с определенной функцией чтения. Для оператора print # это функции Input или Line Input #, а для оператора write #t — это Input #.
Совет
Рекомендуется при применении операций записи/чтения данных из файлов использовать именно такие пары функций и операторов записи/чтения.
Рассмотрим оператор print #. Он имеет следующий синтаксис:
Print #fileNumber, [outputlist]
где:

  • fileNumber — номер файла, аналогичный номеру файла в операторе open;
  • outputlist — список выражений или переменных для записи.

Оператор write ft имеет следующий синтаксис:
Write #fileNumber, [outputlist]
где:

  • fileNumber — номер файла, аналогичный номеру в операторе open;
  • outputlist — список выражений или переменных для записи.

При выполнении записи данных в файл оператор write # после каждой строки автоматически вставляет символ перевода каретки CHR(13) и символ новой строки CHR(10).
Заменим код в нашем приложении MyFileProject на следующий:
Dim strFileName As String
Dim strFileContent As String
Dim nFreeFile As Integer
Private Sub cbStart_Click()
nFreeFile = FreeFile
cdCommonDialog.ShowSave
strFileName = cdCommonDialog.FileName
If strFileName <> "" Then
Open strFileName For Output As nFreeFile
strFileContent = txtFile.Text
Print #nFreeFile, strFileContent
Close
End If
End Sub
В полученном приложении данные, введенные в текстовое поле, будут записываться оператором print # в файл, найденный при помощи диалогового окна сохранения файлов.
Работа с файлами произвольного доступа
Файл с произвольным доступом обладает заранее заданной структурой и состоит из записей. Каждая запись в файле — это некоторая порция данных, которая имеет строго определенный размер и свой конкретный номер в файле. Доступ к данным в файле произвольного доступа осуществляется именно по номеру записи. Данные из файла такого типа читаются и записываются записями. Примерами файла произвольного доступа являются базы данных, всегда имеющие строго определенную структуру.
При открытии файлов произвольного доступа возможен только один режим доступа — Random. Кстати, этот режим является режимом по умолчанию для функции Open.
Используя возможности Visual Basic, можно создать файл произвольного доступа пользовательской, то есть своей собственной структуры. Продемонстрируем это на небольшом примере. С помощью оператора туре объявим тип переменной, имеющей заданную .структуру записи:
Type PhisFace
PhisFaseID As Integer
FIO As String * 50
End Type
В данном примере объявлена структура в виде записи из двух полей. Первым полем является идентификатор, а вторым — фамилия, имя и отчество.
Замечание
Объявление пользовательского типа данных необходимо осуществлять в программном модуле. Для добавления программного модуля в проект следует выполнить команду Add Module (Добавить модуль) из меню Project (Проект) и на вкладке New (Новый) появившегося диалогового окна Add Module выбрать значок с названием Module (Модуль).

Открытие файла произвольного доступа
Файл произвольного доступа открывается несколько иначе, чем файл последовательного доступа. Синтаксис оператора open при этом выглядит следующим образом:
Open pathName [For Random] As fileNumber Len = recLength
где:

  • pathName — полное имя файла;
  • fileNumber — номер файла;
  • recLength — длина записи в байтах.

При использовании оператора Open для открытия файла произвольного доступа атрибут For не обязателен, так как в Visual Basic 6 этот параметр устанавливается по умолчанию. Как видно из синтаксиса, в отличие от файла с последовательным доступом, при открытии файла с произвольным доступом необходимо обязательно указывать длину записи. При этом, если длина записи не известна, ее можно вычислить с использованием функции Len.
Чтение данных из файла произвольного доступа
Данные из файла произвольного доступа, как правило, считываются записями. Для этого используется оператор Get #, который имеет следующий синтаксис:
Get #fileNumber, [recNumber], varName
где:

  • fileNumber — номер файла;
  • recNumberномер записи в файле;
  • varName — переменная.

Если параметр recNumber в функции Get не указан, считывается текущая запись, на которой позиционирован указатель.
Для позиционирования указателя можно использовать функцию seek. Синтаксис этого оператора такой же, как для файлов последовательного доступа, но имеет другой смысл. Если для последовательных файлов позиционирование выполняется по символам, то для файлов произвольного доступа — по номеру записи:
Seek #fileNumber, position
где:

  • fileNumber — номер файла;
  • position — целочисленное выражение, которое задает номер записи в файле. Запись в файл произвольного доступа

Для записи данных в файл произвольного доступа используется оператор Put #, имеющий следующий синтаксис:
Put #fileNumber, [recNumber], varName
где:

  • fileNumber — номер файла, аналогичный номеру в операторе open;
  • recNumber — целочисленное выражение, которое задает номер записи в файле;
  • varName — переменная, указывающая источник записываемых данных.

Этот оператор используется только для файлов произвольного доступа и бинарных. Если номер записи не указан, то по умолчанию принимается текущая позиция указателя записи.
Замечание
При использовании оператора Put необходимо иметь в виду, что данные в записи с указанным в операторе номером будут заменены на те, которые мы записываем в файл. Добавление записей выполняется при помощи этого же оператора, но с некоторыми особенностями. Об этом речь пойдет в следующем разделе.
Рассмотрим небольшой пример. Воспользуемся приложением MyFileApp, изменив его следующим образом:
1. Измените наименование кнопки Выполнить на Запись.
2. Добавьте в форму еще одну кнопку управления.
3. Присвойте созданной кнопке наименование cbRead, используя свойство Name.
4. В свойство Caption введите значение Чтение.
5. Добавьте в приложение программный модуль, воспользовавшись командой Add Module (Добавить модуль) из меню Project (Проект).
6. В код модуля введите текст описания пользовательского типа данных:
Type Phis Face
PhisFaseID As Integer
FIO As String * 50
End Type
7. Откройте окно редактора кода и замените находящийся там код на следующий:
Dim ForFileRecords As PhisFace
Dim nRecNo As Integer
Private Sub SaveRecord ()
Open "C:\FilePF.dat" For Random As #1 Len = Len(ForFileRecords)
ForFileRecords.PhisFaseID = txtNumber.Text
ForFileRecords.FIO = txtFile.Text
Put #1, nRecNo, ForFileRecords
nRecNo = nRecNo + 1
Close #1
End Sub
Private Sub ReadRecord ()
Open "C:\FilePF.dat" For Random As #1 Len = Len(ForFileRecords)
Get #1, nRecNo, ForFileRecords
txtNumber.Text = ForFileRecords.PhisFaseID
txtFile.Text = ForFileRecords.FIO
nRecNo = nRecNo + 1
Close #1
End Sub
Private Sub Form Load()
nRecNo = 1
End Sub
Private Sub cbStart_Click()
Call SaveRecord
End Sub
Private Sub cbRead_Click()
Call ReadRecord
End Sub
В тексте этого кода мы объявили переменные ForFileRecords пользовательского типа для описания структуры файла и nRecNo в качестве счетчика записей. Открывая файл с доступом Random и указанием длины записи в соответствии с длиной переменной ForFileRecords, мы создаем файл требуемой структуры.
8. Запустите приложение. При нажатии кнопки Запись выполняется запись содержимого текстовых полей в файл созданной структуры. При нажатии кнопки Чтение эти данные можно прочитать в текстовом поле последовательно по записям, начиная с первой. При этом каждая кнопка вызывает собственную процедуру выполнения действия.
Изменение данных в файле произвольного доступа
Для изменения данных в записях файла (редактирование, добавление, удаление записей) применяется оператор put ft. При его использовании необходимо иметь в виду, что данные в записи будут заменены на те, которые мы передаем в файл. Подчеркнем, что новая запись с данными не создается.
Для добавления записей в файл необходимо указывать номер записи на единицу больший номера последней записи. В этом случае запись будет добавлена в файл, а не изменена. Например:
Put #FileNum, LastRecord + 1, ForFileRecords
Для вычисления текущего номера последней записи LastRecord можно использовать длину записи и размер файла, возвращаемый функцией LOF.
Перейдем к описанию процесса удаления данных из файла произвольного доступа. Существуют два способа. Можно просто очистить соответствующие поля указанных записей, то есть записать в них пустые значения. Однако в этом случае в файле остаются пустые записи. Понятно, что при таком подходе ресурсы (дисковое пространство) используются нерационально.
Для окончательного удаления записей рекомендуется перезаписывать данные в новый файл, пропуская пустые записи. Алгоритм этих действий таков:
1. Создайте новый файл с помощью оператора Open.
2. Перепишите все непустые записи в новый файл, используя оператор Put #.
3. Закройте исходный файл и удалите его при помощи оператора Kill.
4. Переименуйте новый файл в исходный оператором Name.
Получаем тот же самый файл, но уже без пустых записей. При этом экономится пространство диска и время поиска данных в таком файле.
Работа с двоичными файлами
Двоичный файл в корне отличается от файлов последовательного и произвольного доступа. Посмотрите на  5. Здесь в качестве примера двоичного файла с помощью редактора Notepad системы Windows открыт выполняемый файл Visual Basic 6.
Из рисунка видно, что нет смысла просматривать файл в чистом виде, его понимает только специальная программа. Двоичный файл не организован в строки, как файл последовательного доступа, представленный ранее на  1. Здесь нельзя выделить строки, записи или иную информационную структуру кроме байтов или блоков байтов.
Двоичный файл открывается только в двух режимах:

  • Binary — двоичный доступ по номеру байта;
  • Random — произвольный доступ.

Для режима доступа Random к двоичным файлам, в отличие от файлов произвольного доступа, запись не имеет строго заданного размера и обычно вычисляется по соответствующему алгоритму или хранится в записях файла.
Работа с двоичными файлами отличается большей свободой выполнения различных действий, чем с файлами последовательного доступа. В отличие от файлов последовательного доступа, двоичный файл открывается сразу и для чтения, и для записи.
Открытие двоичного файла
Двоичный файл открывается по-другому, чем файл последовательного доступа. Синтаксис оператора Open для двоичного файла выглядит следующим образом:
Open pathName For Binary As fileNumber
где:

  • pathNameполное имя файла;
  • fileNumber — номер файла.

 
Чтение данных из двоичных файлов
Чтение данных из двоичных файлов выполняется с помощью оператора Get #, имеющего следующий синтаксис:
Get #fileNumber, [recNumber], varName
где:

  • fileNumber — номер файла;
  • recNuinber — размер записи в байтах;
  • varName — переменная, в которую читаются данные из файла.

Запись данных в двоичные файлы
Для записи данных в двоичные файлы используется оператор put #, имеющий следующий синтаксис:
Put [#]fileNumber, [recNumber], varName
где:

  • fileNumber — номер файла;
  • recNumber — размер записи в байтах;
  • varName — переменная, в которой хранятся данные, записываемые в файл.

Позиционирование в двоичном файле выполняется так же, как в файле последовательного доступа.
Замечание
Оператор Put ft работает в паре с оператором Get #.
Работа с атрибутами файлов
Для работы с атрибутами файлов используются функции GetAttr и SetAttr. Синтаксис функции GetAttr, возвращающей атрибуты файлов, следующий:
GetAttr (pathName)
где pathName — путь, включающий имя файла, папку, устройство. По умолчанию применяется текущая папка и устройство.
Функция GetAttr возвращает число, которое определяет атрибуты файла. Интерпретировать это число можно при помощи параметров, описанных в табл. 9.3.
Таблица 9.3. Константы атрибутов файлов
Аналогично работает функция setAttr, выполняющая установку атрибутов файлов. Синтаксис этой функции следующий:
SetAttr pathName, attributes
где:

  • pathName — путь, включающий имя файла, папку, устройство. По умолчанию используется текущая папка и устройство;
  • attributes — число или выражение, задающее сумму атрибутов.

Замечание
В функции SetAttr используются все константы, описанные в табл. 9.3, кроме константы vbDirectory.
Для того чтобы задать несколько атрибутов, можно просто просуммировать указанные константы. Например, для установки атрибутов файла Hidden и Read-only необходимо использовать функцию setAttr следующего вида:
SetAttr "MyFile", vbHidden + vbReadOnly
При этом для файла MyFile будут установлены атрибуты Hidden и Read-only.
Работа с папками и устройствами
Файл находится на самом нижнем уровне хранения информации в файловой системе компьютера. Выше в иерархии файловой системы расположены папки и устройства. Под устройством понимается не только жесткий диск, но и, например, устройство для чтения CD-ROM.
Для операций с папками и устройствами в Visual Basic существует набор функций и операторов (табл. 9.4), которые позволяют создавать и удалять папки, переименовывать их, раскрывать их содержимое.
Таблица 9.4. Функции и операторы для работы с папками и устройствами
Из всего списка функций для работы с папками одной из самых полезных является функция Dir. Действие этой функции напоминает аналогичную команду DOS. С помощью этой функции можно получить список файлов указанной папки. При этом можно применять шаблон имени файла, используя типовые обозначения "*" — множественная подмена, "?" — подмена одного символа.
Функция Dir имеет следующий синтаксис:
Dir(pathName[, attributes])
где:

  • pathName — путь, включающий имя файла, папку, устройство. По умолчанию применяется текущая папка и устройство. Для обозначения имени можно применить шаблон по аналогии с DOS. Если файл не найден, то возвращается пустая строка;
  • attributes — атрибуты файлов. Имеют значения, указанные в табл. 9.5. Если атрибуты не назначены, то по умолчанию возвращаются файлы без атрибутов.

Указывая атрибуты для функции Dir, мы назначаем фильтр для списка выводимых файлов. Для того чтобы назначить одновременно несколько атрибутов, их можно просто арифметически сложить.
Указывая конкретное значение файла, функцию Dir можно использовать для подтверждения существования указанного файла на диске. Если указанный файл не существует, то возвращается пустая строка.
Таблица 9.5. Константы атрибутов файлов функции oir
Кратко опишем синтаксис еще нескольких полезных функций, используемых при работе с папками.
Для создания папки применяется оператор MkDir, синтаксис которого выглядит следующим образом:
MkDir path
где path — путь, включающий имя файла, папку, устройство. По умолчанию используется текущая папка и устройство.
Если параметр path не содержит имя устройства, папка будет создана на текущем устройстве.
Для удаления папок используется оператор RmDir, имеющий следующий синтаксис:
RmDir path
где path — путь, включающий имя файла, папку, устройство. По умолчанию используется текущая папка и устройство.
Совет
При использовании оператора RmDir необходимо иметь в виду, что если удаляемая папка содержит файлы, будет выдаваться системное сообщение об ошибке. Чтобы избежать этого, рекомендуется сначала удалить все файлы из папки с помощью оператора Kill и лишь затем удалить указанную папку
Для выбора другого устройства используется оператор chDrive, имеющий следующий синтаксис:
ChDrive drive где drive — строковое выражение, назначающее новое устройство.
Параметром этой функции является буквенное обозначение устройства вашей системы. При использовании этой функции необходимо иметь в виду, что устройство должно существовать и быть доступным.
 
Организация печати
Печать текста, то есть вывод данных на принтер, можно организовать при помощи файлового оператора print #. Действительно, с точки зрения вывода данных, в принципе все равно, куда пересылать информацию. Необходимо только правильно указать ее получателя.
Для пересылки данных на принтер используется прямое назначение порта принтера (LPT1, LPT2) в качестве получателя данных. Это можно сделать при помощи оператора открытия файла open:
Open "LPT 1" For Output As #nPrinterHandle
После выполнения этого оператора для адресации данных на принтер необходимо использовать дескриптор (идентификатор файла) #nprinterHandle. Если в приложении не поддерживается вычисление идентификатора файлов, то следует использовать функцию FreeFile для его вычисления. Аналогично можно направить данные в любой другой порт компьютера или сети.
После того как порт открыт для приема данных, можно использовать оператор print #. Следующее выражение посылает на принтер данные для печати:
Print #nPrinterHandle, strExpression
В этом выражении strExpression задает печатаемый текст.
Используя функции и операторы чтения данных из файла, можно организовать циклический построчный вывод файла на печать.
Однако этот метод организации вывода данных на печать имеет свои тонкости. Все операции работы принтера (позиционирование печатающей головки, перевод строки, перевод страницы и др.) теперь потребуется программировать с помощью специальных операторов, которые понимает принтер. Такие операторы называются Esc-кодами (Esc-последовательностями). Их описание прилагается к каждому принтеру и здесь мы не будем их рассматривать.
После завершения печати данных порт закрывается оператором close, который также используется для закрытия файла:
Close #nPrinterHandle
или
Close
При использовании оператора close без дескриптора одновременно с портом закрываются и файлы, из которых выводилась информация.
Система файловых объектов (FSO)
В Visual Basic 6 кроме традиционного применяется принципиально новый метод работы с файлами, который заключается в использовании объектно-ориентированного подхода. В систему файловых объектов FSO (File System Objects) входит набор классов объектов с большим количеством методов.
В этом разделе мы перечислим основные классы системы и обсудим методику их использования. Основные классы объектов, которые входят в состав FSO, указаны в табл. 9.6.
Таблица 9.6. Список основных классбв объектов системы файловых объектов
Для того чтобы можно было пользоваться объектами FSO, необходимо подключить к проекту библиотеку Microsoft Scripting Runtime в окне подключения ссылок References (Ссылки), открываемом при выполнении команды References меню Project (Проект). В этой библиотеке находятся все классы системы FSO. Просмотреть методы и свойства классов можно с помощью окна Object Browser (Браузер объектов), которое вызывается командой Object Browser меню View (Вид). В этом окне все классы FSO находятся в библиотеке Scripting, которую можно найти по этому имени в верхнем раскрывающемся списке.

Рассмотрим методы и свойства, входящие в эти классы.
Класс Drive
В классе Drive собраны свойства для работы с устройствами файловой системы ( 6).
Объекты данного класса содержат свойства, описанные в табл. 9.7.
Таблица 9.7. Список свойств класса Drive



 
Класс File
В классе File предоставлены свойства и методы для работы с файлами ( 7).
Класс характеризуется свойствами, описанными в табл. 9.8.
Таблица 9.8. Список свойств класса File





В отличие от класса Drive, класс File содержит методы, список которых приведен в табл. 9.9.
Таблица 9.9. Список методов класса File
Класс Folder
Класс Folder позволяет работать с папками ( 8). В этот класс входят такие же методы и свойства, как и в класс File. Они выполняют те же действия, но только в применении к папкам.
Дополнительно этот класс характеризуется свойствами, описанными в табл. 9.10.
Таблица 9.10. Список свойств класса Folder



Класс FileSystemObject
Класс FileSystemObject является базовым для системы файловых объектов и его методы частично дублируют методы предыдущих классов ( 9). Класс характеризуется единственным свойством Drives, которое возвращает список доступных устройств.
Список методов этого класса гораздо богаче. В него входят методы, описанные в табл. 9.1).
Таблица 9.11. Список методов класса FileSystemObject
Класс TextStream
Класс TextStream предназначен для работы с текстовыми файлами ( 10).
Свойства данного класса описываются в табл. 9.12.
Таблица 9.12. Список свойств класса TextStream
Кроме свойств, в классе TextStream представлены методы, описанные в табл. 9.13.
Таблица 9.13. Список методов класса TextStream
Программирование в системе FSO
Новые методы системы FSO расширяют и дополняют традиционные возможности Visual Basic при работе с файлами. Использование системы FSO состоит из трех этапов:
1. Создание объекта системы FSO.
2. Настройка требуемых методов объекта FSO.
3. Настройка доступных свойств объекта FSO.
Создать объект системы FSO можно объявлением переменной типа FSO:
Dim NewFSO As New FileSystemOb]ect
Для создания объекта можно также использовать следующий оператор:
Set NewFSO = CreateObject("Scripting.FileSystemObject")
В данном случае Scripting. FileSystemOb:ect — это требуемый объект с указанием библиотеки.
После этого можно работать со свойствами и методами объекта NewFSO как со всеми другими объектами приложения.

Работа с устройствами и папками
С помощью FSO можно получить полную информацию об устройствах, используя свойства объектов класса Drive системы FSO. Для изучения свойств класса Drive создадим небольшое приложение, собирающее информацию об устройствах. Выполните следующие действия:
1. Создайте новый стандартный проект. Для этого в меню File (Файл) выберите команду New Project (Создать новый проект) и в окне выбора типа проекта дважды щелкните мышью на значке Standard EXE.
2. Присвойте проекту имя MyFSO. Для этого откройте окно свойств проекта, выбрав команду Project1 Properties (Свойства Project 1) меню Project (Проект).
3. Присвойте форме проекта имя frmFormAboutDrive. В свойство Caption формы введите заголовок Сведения об устройстве.
4. Разместите в форме объект типа DriveListBox, дважды нажав кнопку DriveListBox на панели элементов управления. Используя свойство Name, присвойте объекту имя drvSelectDrive.
5. Добавьте в форму элемент управления типа commandButton. Назовите созданную кнопку cbStart.
Созданное приложение показано  11.
6. Откройте окно редактора и введите приведенный ниже код:
Private Sub GetInfoAboutDrive()
Dim NewFSO As New FileSystemObject, Driver As Drive
Dim sInfoDrv(l To 4) As String, sSayAboutInfo As String
Set Driver = New
FSO.GetDrive(NewFSO.GetDriveName(drvSelectDrive.Drive))
If Driver.IsReady = True Then
sInfoDrv(l) = Driver.SerialNumber
sInfoDrv(2) = Driver.TotalSize / 1048576
sInfoDrv(3) = Driver.FreeSpace / 1048576
sInfoDrv(4) = Driver.FileSystem
sSayAboutInfo = "№ " + sInfoDrv(1) + Chr(10)
sSayAboutInfo = sSayAboutInfo + "Всего: " + s!nfoDrv(2) + _
" МБайт" + Chr(10)
sSayAboutInfo = sSayAboutInfo + "Свободно: " + slnfo0rv(3) + _
" МБайт " + Chr(10)
sSayAboutInfo = sSayAboutInfo + "Файловая система: " + _
sInfoDrv(4) + Chr(10)
Else
sSayAboutInfo = "Устройство не готово" + Chr(10)
End If
'Вывод в окно Immediate
Debug.Print sSayAboutInfo
'Вывод в окно сообщения
MsgBox sSayAboutInfo,, "Сведения об устройстве"
End Sub
Private Sub cbStart_Click ()
GetInfoAboutDrive
End Sub
7. Запустите приложение на выполнение. При нажатии кнопки, расположенной в форме, в окно сообщения выдаются сведения о выбранном устройстве. Одновременно информация выдается в окно Immediate (Непосредственное выполнение).
Замечание
Необходимо напомнить, что для работы с FSO следует подключить к проекту библиотеку Microsoft Scripting Runtime, используя окно подключения ссылок References (Ссылки).
При работе с папками можно выполнять следующие действия:

  • создать папку;
  • удалить папку;
  • переместить папку;
  • скопировать папку;
  • переименовать папку;
  • подтвердить существование папки;
  • найти родительскую папку.

Для работы с папками используются объекты двух классов: Folder или FileSystemObject.
Рассмотрим работу с папками на примере небольшого приложения. Выполните следующие действия:
1. Создайте новый стандартный проект. Для этого в меню File (Файл) выберите команду New Project (Создать новый проект) и в окне выбора типа проекта дважды щелкните мышью на значке Standard EXE.
2. Присвойте проекту имя MyFSOAndFolder. Для этого откройте окно свойств проекта, выбрав команду Projecti Properties (Свойства Project!) меню Project (Проект).
3. Присвойте форме проекта имя frmFormFolder. В свойство caption формы введите заголовок Работа с папками.
4. Разместите в форме объект типа DriveListBox, дважды щелкнув мышью кнопку DriveListBox на панели элементов управления. Используя свойство Name, Присвойте объекту ИМЯ drvSelectDrive.
5. Добавьте в форму объект типа DirListBox для поиска папок. Для этого дважды щелкните мышью кнопку DirListBox на панели элементов управления. Используя свойство Name, присвойте объекту имя dirFolders.
6. Добавьте в форму поле типа TextBox и назовите его txtNameFolder. Для пояснения расположите над этим полем метку Label. Размер (длина) метки должен быть равен размеру поля txtNameFolder. Значение свойства Alignment (Выравнивание) метки установите равным 2-Center.
7. Добавьте в форму три кнопки типа CommandButton. Назовите эти кнопки cbCreate, cbDelete, cbRename и, используя свойство Caption, разместите на них, соответственно, надписи Создать, Удалить, Переименовать.
Созданное приложение показано на  12.
8. Откройте окно редактора и введите приведенный ниже код:
Dim NewFSO As New FileSystemObject, Folder As Folder
Dim sNameFolder As String
Private Sub cbCreate_Click()
' Создание папки
If txtNameFolder <> "" Then
sNameFolder = dirFolders.Path
Set Folder = NewFSO.GetFolder(sNameFolder)
If Folder.IsRootFolder = True Then
MsgBox sSayAboutInfo,, "Корневая папка"
sNameFolder = dirFolders.Path + txtNameFolder.Text
Else
sNameFolder = dirFolders.Path + "\" + txtNameFolder.Text
End If
NewFSO.CreateFolder (sNameFolder)
End If
End Sub
Private Sub cbDelete_Click ()
' Удаление папки
sNameFolder = dirFolders.Path
Set Folder = NewFSO.GetFolder(sNameFolder)
NewFSO.DeleteFolder (sNameFolder)
End Sub
Private Sub cbRename_Click()
' Переименование папки
sNameFolder = dirFolders.Path
Set Folder = NewFSO.GetFolder(sNameFolder)
Folder.Name = txtNameFolder.Text
End Sub
Private Sub drvSelectDrive Change()
dirFolders.Path = drvSelectDrive.Drive
End Sub
9. Запустите приложение на выполнение. Обратите внимание на синхронизацию Объектов drvSelectDrive (Список устройств) И dirFolders (Список папок), которая выполняется по событию change списка устройств. При работе с примером необходимо помнить, что выбор значения в списке выполняется двойным щелчком мыши, то есть свойство path списка папок обновляется по двойному щелчку мыши.
Работа с файлами
При работе с файлами в FSO принято делить выполняемые действия на две большие группы.

  • Работа на уровне файлов. К этой группе относится создание, удаление, перемещение, копирование файлов.
  • Работа на уровне данных в файлах. Это ввод, добавление или удаление данных, чтение данных из файлов.

 
Работа на уровне файлов
Для создания файла можно использовать метод createTextFile класса FileSystemObject:
Dim NewFSO As New FileSystemObject, NewFile As TextStream
Set NewFile = NewFSO.CreateTextFile ("C:\NewFile.txt")
Для удаления файла используется метод Delete класса File. Необходимо заметить, что перед удалением файл должен быть закрыт с помощью метода close. Программный код, выполняющий удаление файла в приложении, выглядит следующим образом:
Dim NewFile As TextStream, File
Set NewFile = NewFSO.CreateTextFile("c:\NewFile.txt")
NewFile.Close
Set File = NewFSO.GetFile("c:\NewFile.txt")
File.Delete
В этом примере файл сначала создается, а затем удаляется.
Перемещение файлов выполняется с помощью метода Move класса File. Если воспользоваться предыдущим текстом, то код, выполняющий перемещение файла, выглядит следующим образом:
Dim NewFile As TextStream, File
Set NewFile = NewFSO.CreateTextFile("c:\NewFile.txt")
NewFile.Close
Set File = NewFSO.GetFile("c:\NewFile.txt")
File.Move ("c:\NewFile.txt")
При этом, как и при удалении, необходимо закрывать файл.
Копирование файла выполняется аналогично перемещению с использованием метода copy.
Разработаем приложение для изучения работы с файлами. Для этого воспользуемся приложением, созданным в предыдущем примере при рассмотрении работы с папками. Откройте приложение и модифицируйте его следующим образом:
1. Увеличьте размер формы, переставьте кнопки и текстовое поле с меткой, как показано на  13. Текст метки измените на Имя файла.
2. Добавьте в форму объект типа FileListBox (Список файлов), дважды щелкнув мышью кнопку FileListBox на панели элементов управления. Используя свойство Name, назовите его filFiles.
3. Измените текст кода в приложении на указанный ниже:
Dim NewFSO As New FileSystemObject, Folder As Folder
Dim sNameFolder As String
Dim sNameFile As String
Dim File
Private Sub cbCreate_Click()
' Создание файла
Dim NewFile As TextStream
sNameFile = dirFolders.Path + "\" + txtNameFile.Text
Set NewFile = NewFSO.CreateTextFile(sNameFile)
filFiles.Refresh
End Sub
Private Sub cbDelete_Click()
' Удаление файла
sNameFolder = dirFolders.Path
Set Folder = NewFSO.GetFolder(sNameFolder)
If Folder.IsRootFolder = True Then
sNameFile = filFiles.Path + filFiles.FileName
Else
sNameFile = filFiles.Path + "\" + filFiles.FileName
End If
Set File = NewFSO.GetFile(sNameFile)
File.Delete
filFiles.Refresh
End Sub
Private Sub cbRename_Click ()
' Переименование файла
sNameFolder = dirFolders.Path
Set Folder = NewFSO.GetFolder(sNameFolder)
If Folder.IsRootFolder = True Then
sNameFile = filFiles.Path + filFiles.FileName
Else
sNameFile = filFiles.Path + "\" + filFiles.FileName
End If
Set File = NewFSO.GetFile(sNameFile)
File.Name = txtNameFile.Text fil
Files.Refresh
End Sub
Private Sub dirFolders Change()
filFiles.Path = dirFolders.Path
End Sub
Private Sub drvSelectDrive_Change()
dirFolders.Path = drvSelectDrive.Drive
End Sub
Private Sub filFiles_Click()
txtNameFile.Text = filFiles.FileName
End Sub
В этом приложении создаются, удаляются и переименовываются файлы. Работа списков синхронизирована по событию change списков устройств и папок.
Работа на уровне данных
Запись данных в файл выполняется с помощью методов write и WriteLine класса TextStream. Если необходимо добавить в файл пустую строку, можно использовать метод WriteBlankLines.
Метод WriteLine отличается от write тем, что первый добавляет в записываемую строку метку конца строки.
Корректная запись данных в файл предполагает выполнение этой операции в три этапа:
1. Открытие файла.
2. Запись данных одним из методов.
3. Закрытие файла.
В программном коде показано применение этих методов для записи данных в файл:
Dim NewFSO, txtNewFile
Set NewFSO = CreateObject("Scripting.FileSystemObject")
Set txtNewFile = NewFSO.CreateTextFile("c:\IniFile.ini". True)
' Запись строки
txtNewFile.Write ("Файл инициализации приложения")
' Запись
txtNewFile.WriteBlankLines (2)
' Запись строки с меткой конца строки
txtNewFile.WriteLine ("Parameter = 70")
txtNewFile.Close
Чтение данных из файла выполняется по блокам, построчно или целиком.
для этого используются соответственно методы Read, ReadLine и ReadAll.
Работу этих методов можно изучить, дополнив предыдущий текст следующим кодом:
' Чтение из файла
Dim File As File
Dim sFileCont As String
Set File = NewFSO.GetFile("c:\IniFile.ini")
Set txtNewFile = File.OpenAsTextStream(ForReading)
sFileCont = txtNewFile.Read(40) I
MsgBox sFileCont
sFileCont = txtNewFile.ReadLine
MsgBox sFileCont
txtNewFile.Close
Замечание
При использовании метода ReadAll необходимо помнить, что для чтения больших файлов требуются соответствующие ресурсы памяти.

 

 
На главную | Содержание | < Назад....Вперёд >
С вопросами и предложениями можно обращаться по nicivas@bk.ru. 2013 г. Яндекс.Метрика