Страницы: 1
RSS
Построчное чтение текстового файла, При условии, что в теле файла есть символы EOF
 
Всем привет!
Собственно, сабж. Предпосылки: есть база данных предприятия. Дважды в день я экспортирую таблицы в текст (с разделением табуляцией), а эти текстовые файлы заранее связаны с Access, как внешние источники данных. проблема в том, что некоторые юзеры вносят в текстовые поля таблиц символы Tab, копируя артикулы из чужих программ. При этом в текстовых файлах съезжают поля и Access начинает матюгаться (я его использую для отчетов). Придумал следующее: открывать текстовые файлы для чтения на VBA, подсчитывать кол-во Chr(9) в каждой строке, а при несовпадении с установленным эталоном выводить в лог на лист Excel. Работает довольно быстро, но вот проблема: в двух таблицах есть зашифрованные бинарные поля, которые изобилуют символами EOF (Ctrl+Z, #1A) и чтение файла обрывается. Пробовал читать, как бинарник, потом разделять на строки:
Код
DataArr()=Split(BigStr,VbNewLine)
, потом в цикле перебирать массив, НО чтение файла :
Код
BigStr=Input(LOF(f),f)
для больших файлов (~60-70мб) требует нереально много времени.
Пожалуйста, предложите какой-нибудь шустрый метод. Только просьба есть: если предложенный вариант будет предполагать использование ADO или API, в двух словах опишите как это работает.

PS: код в приложенном файле не будет работать в отрыве от реальных данных. Там на определенном листе в книге personal.xlsb находится перечень файлов и эталонное значение.
 
Можно так, подключив библиотеку Microsoft Scripting Runtime
Код
Public Sub Checker()
    Const FileName As String = "c:\ESRI\authorize.txt"
    Dim fso As New Scripting.FileSystemObject
    Dim pStream As Scripting.TextStream
    Dim Strs() As String, i As Long, sRow As String
    Set pStream = fso.OpenTextFile(FileName, ForReading)
    Strs = VBA.Split(pStream.ReadAll, vbNewLine)
    pStream.Close
    'Естественно, если нужен только log, то
    'перезаписывать файл не нужно, тогда убрать эту строку
    Set pStream = fso.CreateTextFile(FileName, True)
    'цикл по строкам исходного файла
    'а вы уверены, что в бинарной части
    'не будет vbNewLine?
    For i = 0 To UBound(Strs)
        sRow = Strs(i)
        'анализируем строку sRow на табуляцию и что-то с ней делаем
        '....
        'сохраняем изменённую строку, если нет перезаписи то и ниже комментируем
        pStream.WriteLine sRow
    Next i
    'как и эту
    pStream.Close
End Sub
 
Думаю в коде выше забылось
Код
Const ForReading = 1

Кроме того, ведь в условиях было "для больших файлов (~60-70мб) требует нереально много времени" - поэтому думаю
Код
Strs = VBA.Split(pStream.ReadAll, vbNewLine)

может занять тоже много времени и памяти...
Вот был бы небольшой пример этого хитрого файла - можно было бы проверить как отработает readline
 
Цитата
ребует нереально много времени
Да как сказать Игорь. Для файла в 76Мб с 5 полями чтение, разбиение на строки по vbNewLine, разбиение по VBA.Split(sRow, vbTab) и построчная запись в этот же файл, заняло 15 сек. От "железа" да зависит, но не смертельно.
 
Всем привет!
Огромное спасибо за код, хотя достаточно было только наводку дать. В сторону TextStream присмотрелся вчера вечером на просторах майкрософта, но с английским у меня очень печально.
Цитата
Для файла в 76Мб с 5 полями чтение, разбиение на строки по vbNewLine, разбиение по VBA.Split(sRow, vbTab) и построчная запись в этот же файл, заняло 15 сек
Обнадёживает. Имеется два файла по 60 и 68 мб. В каждом по 84 поля и около 200 тыс. строк. Если читать их как бинарные, то загрузка командой BigStr=Input(LOF(f),f) в строковую переменную занимала около 15 минут для каждого, на серверной станции Dell. Насчет примеров данных, сори, не представляю, куда можно такой объём выложить, даже если заменить "пулеметы" на "огурцы".
Сейчас буду пробовать, главное чтобы TextStream.ReadAll выполнялся не очень долго. И еще, надеюсь, последний вопрос: на что опирается параметр AtEndOfStream - на физический конец файла, как в бинарном подходе или же на текстовые маркеры в теле файла? А то из этого я совершенно ничего не понял. Еще раз спасибо, мне кажется это подойдёт. Проверю, отпишусь.
Вчитался:
Цитата
'а вы уверены, что в бинарной части
   'не будет vbNewLine?
Почти уверен. Иначе это вызвало бы перекос по кол-ву строк даже в Блокноте.

PS. VBA.Split=Split?
 
Нормально читает TextStream, если вы не ошиблись в коде EOF (&H1A), то заглотил бинарный файл (дал на "съедение" rar-архив) с таким кодом без проблем. Так что AtEndOfStream - конец файла.
Цитата
PS. VBA.Split=Split?
Если точно по пространству имён, то
VBA.Strings.Split ;)
Успехов.
 
Как пример вполне хватило бы 10 этих хитрых строк - это куда угодно можно в архиве положить.

И всёж я думаю что быстрее будет читать построчно
Код
retstring = a.ReadLine
и анализировать. Да и писать на выход ведь ничего не нужно?
 
Проверил, ReadAll работает довольно быстро. Символы EOF ни ему, ни AtEndOfStream не помеха. Не учел только наличия vbTab в битовых полях, но это уже тонкости.

Огромное спасибо за помощь. :D
Страницы: 1
Наверх