Неблокирующее чтение текстового файла
версия для печатиНа работе возникла практическая задача: в логе прокси-сервера найди записи по фильтру. Лог - это обычный текстовый файл, так что наиболее простое программное решение - читать его построчно через pascal-функции Reset() и Readln(). Накидал программку, обкатал ее на копии файла, все прекрасно. Но такую прогу нельзя применить к текущему логу, т.к. функция Reset() блокирует файл на запись. Решением стало применение функций WinAPI для чтения файла. В итоге у меня получился аналог функций Паскаля для построчного чтения файла через WinAPI.
Лирическое отступление: для чтения лога пришлось писать программу, т.к. в худшее время своей жизни лог весит 1.5 Гб! MSWord его очень долго ворочает, про "Блокнот"-подобные софтины я вообще молчу.
Ничего революционного я не придумал, просто упростил себе жизнь. Исходник модуля с нужными функциями и примером использования в этом архиве. Все сделано на Delphi 7, упрощено почти до предела. В коде полно комментариев, здесь я разъясню в свободной форме, что да как.
Для поддержания аналогии с Pascal-функциями свои я назвал почти так же. Для открытия файла в мою AssignFile_WAPI() завернута функция CreateFile() с соответствующими флагами, которые разрешают доступ к файлу на измение/чтение. Так же реализованы аналоги функций CloseFile(), EOF(), Reset() и конечно Readln(). Программа работает с Windows-окончаниями строк (CRLF). Переделать под Линукс/Mac несложно.
Функция Readln_WAPI() работает так: читает блок байт из файла в буфер чтения. Размер блока - 128 байт. В зависимости от практического применения его можно изменить. К слову, Readln() Паскаля вообще по байту читает из файла и сравнивает с символами окончания строки. Начало искомой строки совпадает с началом буфера чтения. Ищем в нем конец строки, вырезаем строку из буфера и передаем как результат. Потом указатель файла перемещаем на начало следущей строки. Если в буфере чтения не найдено окончания строки, значит она длинее 128 байт, читаем следующий блок файла, ищем там, дописывая результат, и т.д. Другой вариант - был прочитан конец файла. Тогда в результат выдать все, что получили. Собссно вся затея в двух словах :)
Еще одно отступление: первой и весьма безумной идеей было переписать функцию Reset %). После четвертого перехода в связанную с ней функцию, минуя пару мест на ассемблере я так и не нашел, где именно ставится блокировка на запись. В итоге отказался от идеи, но ее все равно можно реализовать. Это я к тому, что приведенный код скорее всего нельзя портировать в Линукс и при необходимости придется искать иные пути.
[1oo%, EoF]Понравилась статья? Расскажите о ней друзьям: