Тверской государственный университет
Опубликован: 13.09.2006 | Доступ: свободный | Студентов: 3491 / 369 | Оценка: 4.65 / 4.29 | Длительность: 30:37:00
Специальности: Программист, Менеджер
Лекция 15:

Файловый ввод-вывод.

Закрытие файлов

Для закрытия файла служит оператор Close, вызываемый:

Close [список-номеров-файлов]

Параметр список-номеров-файлов может содержать один или несколько номеров ранее открытых файлов, которые должны быть закрыты. Как обычно, номера в списке разделяются запятыми. Если параметр опущен, то закрываются все открытые в данный момент файлы. После выполнения оператора Close номера закрытых файлов снова можно использовать при открытии в операторе Open.

Закрыть все открытые оператором Open файлы может также оператор Reset. Как и вызов Close без параметров, он освободит все номера открытых файлов и перенесет содержимое их буферов на диск.

Запись в файлы последовательного доступа

При записи и чтении данных в последовательный файл происходит автоматическое редактирование данных. В зависимости от того, на кого ориентировано это редактирование, человека или программу компьютера применяются две формы редактирования. Соответственно операторы записи и чтения существуют в двух вариантах:

  1. Для записи "человеко-ориентированных" данных применяется оператор Print#, представляющий данные в формате, подготовленном для отображения на экране дисплея. По существу, мы уже хорошо знакомы с этим оператором, поскольку ни одна наша программа не обходилась без вывода данных в окно отладки, а применяемый для этих целей метод Print объекта Debug по синтаксису и по действию подобен оператору Print#.
  2. Для записи данных, обрабатываемых после их чтения программой, используется оператор Write#. Заметим, в каком - то смысле это более универсальный оператор, чем Print, он, например, не зависит от локализации.

Оператор Print# записывает в файл форматированные данные. Его вызов имеет вид:

Print #номер-файла, [список-вывода]

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

[{Spc(n) | Tab[(n)]}] [выражение] [симв-поз]
  • Spc(n) задает количество вставляемых пробелов.
  • Альтернативный параметр Tab(n) указывает абсолютный номер n столбца, в котором будет начинаться текст, определяемый параметром выражение. Если не указывать аргумент у Tab, то позицией вставки является следующая зона печати. (Можно полагать, что при выводе экран разделен на зоны, и табуляция позволяет переходить от одной зоны к другой).
  • Параметр выражение задает выражение, значение которого после редактирования и преобразования его в текстовую строку будет записано в файл. На выражения не накладывается особых ограничений, Это могут быть как строковые, так и числовые выражения, они могут содержать данные разных типов. Даты записываются в файл в кратком формате, значения булевых переменных - как ключевые слова Ложь ( False ) или Истина ( True ), пустое значение Empty - как пустое слово, нулевое значение Null выводится как "Null". Данные об ошибке выводятся в виде кода ошибки. Числовые данные выводятся в формате, зависящем от локализации. При выводе можно вызвать для форматирования данных функцию Format.
  • Параметр симв-поз задает положение следующего выражения. Если он равен ";" или пробелу, вставка следующего выражения будет происходить сразу за последним выведенным символом, Tab(n) указывает номер n столбца, начиная с которого будет выводиться выражение. Tab без аргумента или "," - переход в следующую позицию табуляции (зону печати).

Создадим теперь открытый ранее файл read.me, записывая в него выражения, позволяющие продемонстрировать все возможности оператора Print:

Public Sub WritingWithPrint()
		Dim MyBool As Boolean, MyDate As Date
		Dim MyNull As Variant, MyFloat As Double, MyErr As Variant
 
	Print #1, "Первая строка файла"			' запись текстовой строки.
	'Первая строка файла
	Print #1, "Зона 1"; Tab; "Зона 2"	' запись в двух позициях табуляции.
	'Зона 1 Зона 2
	Print #1, "Зона 1", "Зона 2"		 ' запятая разделяет как табуляции.
	'Зона 1 Зона 2
	Print #1, "Привет,"; "старик!"	'; склеивает выражения.
	'Привет,старик!
	Print #1, "Привет,"; "старик!"	' пробел действует аналогично.
	'Привет,старик!
	Print #1, Spc(5); "5 пробелов "		' вставка 5 пробелов слева.
	'	 5 пробелов
	Print #1, Tab(20); "Старик,"; Tab(10); "привет!"	' печать в соответствующих столбцах.
	'					Старик
	'		 привет!
	Print #1, "one"; " "; "two"		'разделение пробелом
	'one two
	MyBool = False					 ' булева переменная
	Print #1, MyBool
	'False
	MyDate = #6/14/1999#				' значение даты
	Print #1, MyDate				 ' печать в кратком формате
	'14.06.99
	MyNull = Null						' нулевое значение
	Print #1, MyNull
	'Null
	MyFloat = 3.1416					'вещественное значение
	' использование функции Format:
	Print #1, MyFloat, Format(MyFloat, "#.00"), Format(MyFloat, "00.000")
	'3,1416 3,14 03,142
	On Error Resume Next
	Err.Raise 6
	MyErr = Err
	Print #1, MyErr
	MyErr = CVErr(2000)
	Print #1, MyErr
End Sub
14.2.

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

Public Sub ReadingWithLine()
	Dim MyStr As String
	
	Close #1
	Open Path & "read.me" For Input As #1
	Do While Not EOF(1)
		Line Input #1, MyStr
		Debug.Print MyStr
	Loop
End Sub

Текст в окне отладки выглядит в полном соответствии с нашими ожиданиями. Вот он:

Первая строка файла
Зона 1		Зона 2
Зона 1		Зона 2
Привет,старик!
Привет,старик!
	 5 пробелов 
					Старик,
		 привет!
one two
False
14.06.99 
Null
 3,1416		3,14			03,142
 6 
Error 2000

Обратите внимание, ошибки, возбуждаемые методом Raise и функцией CVErr, редактируются по-разному, в первом случае записывается только код ошибки, во втором ѕ код сопровождается ключевым словом Error, не переводимым в локализованных версиях.

Заметьте, точно такой же текст можно получить, если в процедуре WritingWithPrint заменить оператор Print на Debug.Print, поскольку этот метод и этот оператор порождают одинаковый результат, разница лишь в том, что один из них помещает результаты в файл, а другой ѕ в окно отладки.

При выводе данных можно управлять шириной выводимых строк. Ширину выводимых строк для открытого файла устанавливает оператор:

Width #номер-файла, ширина

Параметр ширина принимает значения от 0 до 255. Если при печати в файл оператором Print добавление значения очередного выражения в строку приведет к превышению установленной границы, это значение будет печататься с новой строки. При этом значение одного выражения не переносится, даже если его длина превышает установленную границу. Например, если для файла с номером 1 ограничить ширину строки 5 символами:

Width #1,5

а затем напечатать строку:

Str = "раму мылом"
Print #1, "мама", "мыла", Str

то в файле окажутся строки:

мама
мыла
раму мылом

Обращаем внимание и на то, что переход к новой строке может происходить и при встрече с разделителем Tab(n), если n задает позицию меньшую, чем текущая позиция. Пример такой ситуации встречался в нашей процедуре.

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

Write #номер-файла, [список-вывода ]

Параметр номер-файла - номер открытого файла с последовательным доступом, список-вывода - одно или несколько разделенных запятыми числовых или строковых выражений, значения которых записываются в файл. Разделителями выражений могут быть пробелы и точка с запятой.

Также как и оператор Print, оператор Write производит редактирование данных в момент записи. При этом приняты следующие соглашения:

  • В числах в качестве разделителя целой и дробной частей всегда используется точка.
  • В качестве булевых значений используются слова #TRUE# и #FALSE#.
  • При записи дат применяется универсальный формат.
  • Ошибки выводятся в формате #ERROR код-ошибки#.
  • Для пустого значения выражения ( Empty ) ничего не записывается
  • Значение Null записывается как #Null#.

В отличие от оператора Print, оператор Write# вставляет при записи запятые между соседними выражениями и заключает строковые значения в кавычки. После записи последнего выражения вставляется перевод на новую строку (Chr(13) + Chr(10)).

Следующая процедура создает файл с последовательным доступом "readme.txt" и записывает в него данные с помощью оператора Write#. При записи мы старались повторить содержимое предыдущего файла, чтобы можно было сравнить работу, выполняемую операторами Print и Write. Вот текст этой процедуры:

Public Sub WritingWithWrite()
	Dim MyStr As String, MyBool As Boolean, MyDate As Date
	Dim MyNull As Variant, MyFloat As Double, MyErr As Variant
	
	'Открытие файла readme.txt
	Open Path & "readme.txt" For Output As #7
	
	'Создание файла
	Write #7, "Первая строка файла"			' запись текстовой строки.
	Write #7, "Зона 1", "Зона 2"	' запись двух строк.
	Write #7, "Привет,", "старик!"	'еще две строки
	MyStr = "раму мылом. "
	Write #7, "Мама ", "мыла ", MyStr
	MyBool = False					 ' булева переменная
	Write #7, MyBool
	MyDate = #6/14/1999#				' значение даты
	Write #7, MyDate					' запись даты
	MyNull = Null						' нулевое значение
	Write #7, MyNull
	MyFloat = 3.1416					'вещественное значение
	' использование функции Format:
	Write #7, MyFloat, Format(MyFloat, "0.00"), Format(MyFloat, "00.000")
	On Error Resume Next
	Err.Raise 6
	MyErr = Err
	Write #7, MyErr
	MyErr = CVErr(2000)
	Write #7, MyErr

End Sub
14.3.

Результат выполнения этой процедуры - файл "readme.txt" - в текстовом редакторе выглядит так:

"Первая строка файла"
"Зона 1","Зона 2"
"Привет,","старик!"
"Мама ","мыла ","раму мылом. "
#FALSE#
#1999-06-14#
#NULL#
3.1416,"3,14","03,142"
6
#ERROR 2000#

Сравните эти строки с теми, что выдаются оператором Print.

полина есенкова
полина есенкова
Дмитрий Вологжин
Дмитрий Вологжин
Добрый день, прошел тесты с 1 по 9, 10 не сдал, стал читать лекцию и всё пройденные тесты с 1 по 9 сбросились, когда захотел пересдать 10 тест.