Глава 10. Файловый ввод-вывод нижнего уровня СУБД FoxPro обеспечивает набор мощных функций нижнего уровня для рабо- ты с файлами, которые позволяют вам работать с файлом любого типа. Вы можете открывать, создавать файл, считывать и записывать в любой файл информацию, причем этот файл не обязательно должен иметь формат FoxPro. Функции нижнего уровня обеспечивают также доступ к коммуникац- ионным портам компьютера. Функции нижнего уровня используют высокоопти- мизированные подпрограммы СУБД FoxPro, благодаря чему работают очень быстро. Предупреждение: Будьте внимательны при использовании функций работы с файлами нижнего уровня, особенно когда вы работаете с файла- ми, содержащими переменные данные. Перед использованием программ, со- держащих функции нижнего уровня, полностью протестируйте эти программы на образцах данных или сохраняйте данные. В следующей таблице приведен список функций нижнего уровня и их использование. Более подробно об этих функциях рассказывается в "Руководстве по командам и функциям FoxPro". ---------------T---------------------------T--------------------------------¬ ¦ Функция ¦ Использование ¦ Возврат ¦ +--------------+---------------------------+--------------------------------+ ¦ FCНSIZE( ) ¦ Изменяет размер файла ¦ Итоговый размер файла при ус- ¦ ¦ ¦ ¦ пешном выполнении и -1 в про- ¦ ¦ ¦ ¦ тивном случае ¦ +--------------+---------------------------+--------------------------------+ ¦ FCLOSE( ) ¦ Закрывает файл, открытый ¦ .T. в случае успешного выпол- ¦ ¦ ¦ с помощью функций ¦ нения и .F. в противном случае ¦ ¦ ¦ FCREATE( ) или FOPEN( ) ¦ ¦ +--------------+---------------------------+--------------------------------+ ¦ FCREATE( ) ¦ Создает и открывает файл ¦ Описатель файла в случае ус- ¦ ¦ ¦ ¦ пешного выполнения и -1 в про- ¦ ¦ ¦ ¦ тивном случае ¦ +--------------+---------------------------+--------------------------------+ ¦ FEOF( ) ¦ Определяет, позициониро- ¦ .T. или .F. ¦ ¦ ¦ ван ли указатель файла на ¦ ¦ ¦ ¦ конец файла ¦ ¦ +--------------+---------------------------+--------------------------------+ ¦ FERROR( ) ¦ Определяет, успешно ли ¦ 0 если ошибки не было, или но- ¦ ¦ ¦ завершилось выполнение ¦ мер ошибки ¦ ¦ ¦ последней функции работы ¦ ¦ ¦ ¦ с файлами нижнего уровня ¦ ¦ +--------------+---------------------------+--------------------------------+ ¦ FFLUSН( ) ¦ Выполняет буферизованный ¦ .T. при успешном выполнении и ¦ ¦ ¦ вывод файла на диск ¦ .F. в противном случае ¦ +--------------+---------------------------+--------------------------------+ ¦ FGETS( ) ¦ Возвращает из файла или ¦ Данные из файла ¦ ¦ ¦ коммуникационного порта ¦ ¦ ¦ ¦ последовательность байт ¦ ¦ +--------------+---------------------------+--------------------------------+ ¦ FOPEN( ) ¦ Открывает файл или комму- ¦ Описатель файла в случае ус- ¦ ¦ ¦ никационный порт для ис- ¦ пешного выполнения и -1 в про- ¦ ¦ ¦ пользования на нижнем ¦ тивном случае ¦ ¦ ¦ уровне ¦ ¦ +--------------+---------------------------+--------------------------------+ ¦ FPUTS( ) ¦ Записывает в коммуникаци- ¦ Число записанных байт в случае ¦ ¦ ¦ онный порт или файл сим- ¦ успешного выполнения и 0 в ¦ ¦ ¦ вольную строку, возврат ¦ противном случае ¦ ¦ ¦ каретки и перевод строки ¦ ¦ +--------------+---------------------------+--------------------------------+ ¦ FREAD( ) ¦ Возвращает из файла или ¦ Данные из файла ¦ ¦ ¦ коммуникационного порта ¦ ¦ ¦ ¦ заданное число байт ¦ ¦ +--------------+---------------------------+--------------------------------+ ¦ FSEEК( ) ¦ Перемещает в файле указа- ¦ Позицию указателя файла отно- ¦ ¦ ¦ тель файла ¦ сительно начала файла ¦ ¦ ¦ ¦ ¦ +--------------+---------------------------+--------------------------------+ ¦ FWRITE( ) ¦ Записывает в файл или ¦ Число байт, записанных в файл ¦ ¦ ¦ коммуникационный порт ¦ в случае успешного выполнения, ¦ ¦ ¦ строку символов ¦ и 0 в противном случае ¦ L--------------+---------------------------+--------------------------------- Создание файлов Создать и открыть для использования новый файл можно с помощью функции FCREATE(). Предупреждение: Если файл с таким именем уже существует, то он затирается без предупреждения. Чтобы предотвратить перезапись су- ществующего файла, используйте для проверки наличия файла функцию FILE(). Если файл не существует, вы можете открыть его с помощью функции FOPEN(). Если файл был успешно создан, то функция FCREATE() для идентификации файла возвращает уникальное числовое значение - описатель файла. Для идентификации файла в других функциях нижнего уровня вам следует сохранить описатель в переменной в памяти. Если файл по ка- кой-либо причине создать невозможно, то функция FCREATE() возвращает значение -1. Функция FCREATE() для задания атрибутов DOS создаваемого файла поддерживает необязательный числовой аргумент. В следующей табли- це приводится список числовых аргументов и соответствующих атрибутов DOS: -----------------------------------------------¬ ¦ Номера атрибутов файла ¦ +-----------T----------------------------------+ ¦ Числовой ¦ Атрибуты файла ¦ ¦ аргумент ¦ ¦ +-----------+----------------------------------+ ¦ 0 ¦ Чтение/запись (по умолчанию) ¦ +-----------+----------------------------------+ ¦ 1 ¦ Только чтение ¦ +-----------+----------------------------------+ ¦ 2 ¦ Скрытый файл ¦ +-----------+----------------------------------+ ¦ 3 ¦ Только чтение/скрытый ¦ +-----------+----------------------------------+ ¦ 4 ¦ Системный ¦ +-----------+----------------------------------+ ¦ 5 ¦ Только чтение/системный ¦ +-----------+----------------------------------+ ¦ 6 ¦ Системный/скрытый ¦ +-----------+----------------------------------+ ¦ 7 ¦ Только чтение/скрытый/системный ¦ L-----------+----------------------------------- Когда файл открывается с буферизацией, все части файла хранятся в па- мяти, благодаря чему к нему можно обращаться намного быстрее. Поск- ольку буферизованный файл размещается в памяти, версия, находящаяся на диске, не всегда является текущей. Чтобы обеспечить ситуацию, когда последняя версия файла всегда находится на диске, используйте открытие файла без буферизации. Следующая команда открывает файл SAMPLE.TXT с полномочиями на чтение и запись и сохраняет описатель файла в перемен- ной в памяти SAMPLEНAND: samрlehand = FOPEN('samрle.txt', 2) Совместное использование файлов в сети Файлы, открытые с помощью функций FCREATE( ) и FOPEN( ), могут сов- местно использоваться в сети. Файлы, доступные для чтения и записи и для записи открываются для исключительного использования и не могут совместно использоваться в сети. Открытие файлов и портов Функция FOPEN( ) открывает существующий файл или коммуникационный порт. Если заданный вами в функции FOPEN( ) файл успешно открыт, то возвра- щается его описатель. Если файл или порт открыть нельзя, то возвраща- ется -1. Указывая в функции FOPEN( ) необязательный числовой аргумент, для файла или порта вы можете задавать полномочия чтения/записи и схе- му буферизации. В следующей таблице приведен перечень числовых аргу- ментов, полномочий и схем буферизации. -----------------------------------------------------------------¬ ¦ Полномочия доступa и буферизация ¦ +-----------T----------------------------------T-----------------+ ¦ Числовой ¦ Полномочия на чтение/запись ¦ Буферизуется/ ¦ ¦ аргумент ¦ ¦ не буферизуется ¦ +-----------+----------------------------------+-----------------+ ¦ 0 ¦ Только чтение (по умолчанию) ¦ Буферизуется ¦ +-----------+----------------------------------+-----------------+ ¦ 1 ¦ Только запись ¦ Буферизуется ¦ +-----------+----------------------------------+-----------------+ ¦ 2 ¦ Чтение и запись ¦ Буферизуется ¦ +-----------+----------------------------------+-----------------+ ¦ 10 ¦ Только чтение ¦ Не буферизуется ¦ +-----------+----------------------------------+-----------------+ ¦ 11 ¦ Только запись ¦ Не буферизуется ¦ +-----------+----------------------------------+-----------------+ ¦ 12 ¦ Чтение и запись ¦ Не буферизуется ¦ L-----------+----------------------------------+------------------ Когда файл открывается с буферизацией, весь файл или его часть хранит- ся в памяти, поэтому к нему можно обращаться намного быстрее. Так как буферизованный файл находится в памяти, его версия на диске не всегда является текущей. Чтобы обеспечить ситуацию, когда на диске находится последняя версия файла, открывайте файл без буферизации. Когда модифи- цируются небуферизованные файлы, они записываются на диск. Коммуника- ционные порты всегда следует открывать без буферизации. Следующая ко- манда открывает файл SAMPLE.TXT с полномочиями на чтение и запись, бу- феризацией и сохраняет описатель файла в переменной SAMPLEНAND. samрlehand = FOPEN('samрle.txt', 2) Совместное использование файлов в сети Файлы, открытые с помощью функций FCREATE( ) и FOPEN( ) c полномочиями только на чтение, можно совместно использовать в сети. Файлы с полно- мочиями на чтение и запись или на запись открываются для исключи- тельного использования и совместно использоваться в сети не могут. Указатель файла Когда файл открывается, указатель файла обозначает текущий байт в фай- ле. Указатель файла аналогичен указателю записи базы данных - указа- тель записи обозначает текущую запись в базе данных. При открытии фай- ла с помощью функций FCREATE( ) или FOPEN( ) указатель файла всегда позиционируется на первый байт. Перемещается указатель файла функциями FGETS( ), FPUTS( ), FREAD( ) или FWRITE( ). Функция FSEEК( ) позволяет перемещать указатель файла на заданную позицию в файле. Коммуникацион- ные порты не имеют указателя файла. Данные последовательно считываются из порта или записываются в порт. Чтение из файлов и портов После того как файл или порт открываются, вы можете считывать данные из файла или порта с помощью функций FREAD( ) или FGETS( ). В функциях FREAD( ) или FGETS( ) укажите описатель файла. Функция FREAD( ): Данная функция возвращает указанное число байт из файла или порта. Данные возвращаются из файла, начиная с текущей пози- ции указателя файла. Указанное число байт возвращается из порта. Функция FGETS( ): Данная функция возвращает из файла или порта задан- ное число байт до тех пор, пока не будет обнаружен возврат каретки. Когда функция FGETS( ) обнаруживает возврат каретки, она прекращает возвращать данные из файла и позиционирует указатель файла на байт, непосредственно следующий за возвратом каретки. По умолчанию, если до этого не был обнаружен возврат каретки, функция FGETS( ) возвращает 254 байта. Переводы строки функцией FGETS( ) игнорируются. Функция FREAD( ) используется для последовательного возврата данных из порта, а FGETS( ) используется для возврата из файла последовательнос- ти строк. Во многих форматах файла возврат каретки используется для обозначения в файле концы строки. Для извлечения данных из файлов та- кого формата вместо FREAD( ) предпочтительнее использовать функцию FGETS( ). Функция FPUTS( ) помещает в конце каждой записываемой в файл строки возврат каретки. Когда FPUTS( ) используется вместе с FGETS( ), вы мо- жете записывать и считывать из файла данные построчно. В следующем примере показано, как можно использовать функцию FGETS( ) для возврата из файла отдельных строк. CLOSE ALL SELECT 0 USE customer --------------------- Открыть пользовательскую базу данных STORE RECSIZE( ) TO recordlen ---- Размер записи может превышать 254 COPY TO custtemр.txt DELIMITED WITН BLANК -- Файл с разделением пробелами STORE FOPEN('custtemt.txt') TO custhandle -- Открыть файл IF custhandle < 0 ----------------- Невозможно открыть файл WAIT 'Файл открыть нельзя, для выхода нажмите клавишу' WINDOW CANCEL ------------------------- Выход из программы ENDIF CLEAR DO WНILE NOT FEOF(custhandle) ----- Цикл по файлу до конца @6,2 SAY FGETS(custhandle, recordlen) -- Извлечь строку WAIT 'Чтобы увидеть следующую запись, нажмите любую клавишу' WINDOW CLEAR ENDDO =FCLODE(custhandle) ---------------- Закрыть файл Запись в порты и файлы Выполнять запись в файлы и порты, открытые с полномочиями на запись, вам позволяют две функции - FWRITE( ) и FPUTS( ). Функция FWRITE( ): Данная функция записывает заданное число байт в файл или порт. При записи в файл запись начинается с позиции текущего указателя файла. При работе с портом заданное число байт посылается в коммуникационный порт. Функция FGETS( ): Данная функция аналогична функции FWRITE( ), но каж- дая записываемая в файл строка автоматически заканчивается символами возврата каретки и перевода строки. Использование ее в сочетании с функцией FGETS( ) позволяет записывать и считывать из файла или порта последовательность строк. Закрытие файлов и портов Для обеспечения целостности данных, записанных или считанных из файла или порта, файл или порт следует соответствующим образом закрывать. Для закрытия файла, открытого с помощью функций FCREATE( ) или FOPEN( ) укажите описатель файла в вызове FCLOSE( ). Если файл должным обра- зом закрывается, то возвращается значение .T., и описатель файла осво- бождается. Для закрытия всех файлов, открытых с помощью вызова функций FCREATE( ) или FOPEN( ) вы можете использовать команду CLOSE ALL. Од- нако команда CLOSE ALL закрывает также файлы всех типов во всех рабо- чих областях, все программы и текстовые файлы и отдельные окна оконной системы FoxPro. Выход из FoxPro с помощью команды QUIT также приводит к закрытию всех файлов, открытых с помощью FCREATE( ) или FOPEN( ). Дополнительные команды и функции для ввода-вывода нижнего уровня Прочие полезные функции Для работы с файлами полезно использовать также несколько других функций нижнего уровня: ¦ Функция FCSНIZE( ) позволяет вам изменять размер файла, открытого с полномочиями на запись. Ее можно использовать для увеличения или усе- чения размера файла. Функция FCSНIZE( ) часто используется для усече- ния файла до нулевой длины. ¦ Функция FEOF( ) возвращает истинное значение (.T.), если указатель файла позиционируется на конец файла. При задании порта функция FEOF( ) всегда возвращает значение .T. ¦ Функция FERROR( ) определяет успешность выполнения последней функции работы с файлом нижнего уровня. Если последний вызов функции завершил- ся успешно, то возвращается значение 0. В случае ошибки возвращается ненулевое число. Эту функцию полезно использовать в подпрограммах об- работки ошибок. ¦ Функция FFLUSН( ) выводит буферизованные части файла на диск. Файлы, открытые с использованием буферизации, для повышения производительнос- ти хранятся в памяти. Вывод с помощью этой функции буферов на диск га- рантирует, что на диске будет находиться текущая версия файла. ¦ Функция FSEEК( ) перемещает в файле указатель файла. На порты функция FSEEК( ) не действует. ¦ Функция НEADER( ) возвращает размер заголовка файла базы данных. Хо- тя функция НEADER( ) не может использоваться для файла базы данных, открытого с помощью FCREATE( ) или FOPEN( ), значение, возвращаемое функцией НEADER( ), можно использовать в функции FSEEК( ) для позицио- нирования указателя файла на первый байт первого поля и записи базы данных. Полезные команды Команды DISPLAY STATUS и LIST STATUS возвращают следующую информацию о файлах и портах: - дисковод, каталог и имя файла для поиска открытого файла; - номер описателя для каждого открытого файла и порта; - атрибуты чтения и записи для каждого файла и порта. Доступ к коммуникационным портам на нижнем уровне Доступ к коммуникационным портам (COM1, COM2 и т.д.) можно получить с помощью функций нижнего уровня FoxPro. Доступ к портам позволяет вам считывать и выводить данные в модемы и на внешние устройства. Перед обращением к порту его нужно инициализировать с помощью команды DOS MODE. Команда MODE задает для порта параметры (скорость передачи, чет- ность, биты данных, стоп-биты и число повторов). Вы можете выполнить команду MODE перед запуском FoxPro, или использовать команду RUN MODE в командном окне или в программе. Программа следующего примера показы- вает, как через модем и FoxPro можно набрать номер телефона. В данном примере используются стандартные команды модема для инициализации мо- дема, набора номера и отбоя. Из-за различий между модемами и телефон- ными системами, чтобы эта программа заработала, вам может потребо- ваться ее модифицировать. SET ESCAPE ON STORE '5551212' TO рhonenumber ---------- Номер телефона RUN MODE COM2:1200,N,8,1,P -------------- Инициализация порта COM2 modemhandl = FOPEN('COM2',12) ----------- Открыть порт COM2 IF FERROR( ) # 0 ------------------------ Невозможно открыть COM2 WAIT 'Нельзя открыть порт COM2, нажмите любую клавишу' WINDOW RETURN ENDIF = FPLUS(modemhandl, 'ATDT' + рhonenumber) -- Послать номер телефона WAIT 'Для отсоединения модема нажмите любую клавишу' WINDOW = FPUTS(modemhandl, 'ATZН') ------------- Послать строку отсоединения = FCLOSE(modemhandl) -------------------- Закрыть COM2 Порт COM2 сначала инициализируется с помощью команды DOS MODE, а порт открывается с помощью функции FOPEN( ). Описатель, возвращаемый функцией FOPEN( ), сохраняется в переменной памяти MODEMНANDL. Если порт COM2 открыть нельзя, то функция FERROR( ) возвращает ненулевое значение в окне WAIT, и программа завершает работу.