Newbie questions (text files processing)

Программирование на Visual Basic, главный форум. Обсуждение тем программирования на VB 1—6.
Даже если вы плохо разбираетесь в VB и программировании вообще — тут вам помогут. В разумных пределах, конечно.
Правила форума
Темы, в которых будет сначала написано «что нужно сделать», а затем просьба «помогите», будут закрыты.
Читайте требования к создаваемым темам.
ProgrammingFan
Начинающий
Начинающий
 
Сообщения: 9
Зарегистрирован: 20.08.2015 (Чт) 10:26

Newbie questions (text files processing)

Сообщение ProgrammingFan » 30.08.2017 (Ср) 11:21

Вводные данные - VB5.0, и желание обойтись встроенными средствами именно этой версии, без подключения внешних модулей.
Пишу программу по обработке текстовых файла, достаточно больших по размерам, порядка 40-50 тысяч строк.
Предполагается, что программа воспринимает аргумент (имя файла) с командной строки,
показывает форму с именем файла и прогресс-баром, обрабатывает его и закрывается.
Но на пути к этой идилии возникло пару затруднений...

1) Открываю файл для построчного чтения OPEN Filename$ FOR INPUT, затем обрабатываю его
через цикл WHILE NOT EOF().... WEND. Предполагалась, что внутри этого цикла оператор LOC
вернет мне текущую байтовую позицию, и конструкция LOC()/LOF() *100 позволит мне получить
процент выполнения, для передачи в прогресс-бар. Оказалось напрасно - help говорит ай-я-яй :)

Sequential : Current byte position in the file divided by 128. However, information returned by Loc
for sequential files is neither used nor required

Пока вышел из положения предварительным подсчетом количества строк в цикле WHILE...WEND,
а затем открытием уже рабочего цикла FOR...NEXT. Но если в последнем случае передать процент
в прогресс-бар получается без проблем, то в первом - совсем никак, а операция достаточно длительная.
В идеале хотелось бы обойтись одним проходом, но вот как?

2) Первоначально предполагалось, что программа не потребует взаимодействия с пользователем. Но возникла проблема - форма не прорисовывается полностью - белый прямоугольник и квадратики прогресс бара.
Стоит поставить breakpoint в середине цикла FOR...NEXT - все на месте.

Код: Выделить всё
Private Sub Form_Activate()

   'open file for input
    Open FileInput$ For Input As #1
    While Not EOF(1)
        Line Input #1, FileString$
       'calculate lines for progressbar
        LineCount = LineCount + 1
    Wend
   Close #1   

    Open Fileinput$ For Output As #1
    For i = 1 To LineCount

       'draw progress bar
        prgProgress.Value = i / LineCount * 100
      ' ******************************************
       'read and processing....
        Line Input #1, FileString$
      ' ******************************************
Next i
close #1
   
End Sub


Интуитивно понимаю, что форма не получает фокус, но почему??? Пока вышел из положения через кнопку OK на форме. Вынес всю обработку в процедуру MAIN. Теперь форма вроде как прорисовывается, и после нажатия на кнопку выполняется код:

Код: Выделить всё
Private Sub cmdOK_Click()

    Call Main

End Sub


Но возникает другая проблема - на форме во время работы не меняются cвойства .CAPTION у меток. Предполагается, что в первом, вспомогательном цикле будет метка "Loading..." , перед работой второго она заменятся на имя обрабатываемого файла

Код: Выделить всё
Private Sub Main()

    LblFilename.Caption = "Loading..."
    Open FileInput$ For Input As #1

    While Not EOF(1)
    ....
    Wend
    Close #1

    LblFilename.Caption = Fileinput$   
    Open FileInput$ For Input As #1
       
    For i = 1 To LineCount
        DoEvents
       ....
    Next i
   Close #1
End Sub
[code]
Во время работы метка получает свойство "Loading..." и больше не меняется несмотря на явное присваивание перед выполнением цикла. Опять же - стоит остановить программу в середине цикла - все показывается как должно. Грешил на DOEVENTS, но что с ним, что без него - не выходит :(

3. Поскольку теперь на форме появилась кнопка "OK", а цикл достаточно протяженый по времени, хотелось бы хотя бы заблокировать повторное нажатие кнопки, и изменить ее на неактивную, но вот как это сделать?


alibek
Большой Человек
Большой Человек
 
Сообщения: 14205
Зарегистрирован: 19.04.2002 (Пт) 11:40
Откуда: Russia

Re: Newbie questions (text files processing)

Сообщение alibek » 30.08.2017 (Ср) 15:10

1. Почему бы открывать файл в режиме binary?
Читать в буфер, из буфера извлекать строки, обрабатывать строки и писать в выходной файл.
А возможно и разбивать на строки не потребуется.

2. Если на скорую руку, то то перед началом цикла выполнить Me.Refresh, а в цикле вставить DoEvents или Refresh каждые 50-100 мс.

3. cmdOK.Enabled = False
Lasciate ogni speranza, voi ch'entrate.

ProgrammingFan
Начинающий
Начинающий
 
Сообщения: 9
Зарегистрирован: 20.08.2015 (Чт) 10:26

Re: Newbie questions (text files processing)

Сообщение ProgrammingFan » 30.08.2017 (Ср) 17:24

alibek писал(а):1. Почему бы открывать файл в режиме binary?
Читать в буфер, из буфера извлекать строки, обрабатывать строки и писать в выходной файл.
А возможно и разбивать на строки не потребуется.

Интересно... Правильно ли я понимаю - открываем файл, резервируем строковую переменную равную длине файла, и считываем его весь в эту строку, затем крутим цикл по поиску CHR$(10)+CRH$(13) и записываем построчно? Мне кажется это будет медленнее, чем просто посчитать строки в файле. Да и хватит ли памяти, скажем для разбора полугигабайтного файла?
Или же предполагается проводить обработку не построчно, а с той самой большой считанной из файла переменной?

alibek писал(а):2. Если на скорую руку, то то перед началом цикла выполнить Me.Refresh,

Да, это именно то, что и требовалось, спасибки :) Получается что каждый раз, когда меняется свойство у какого-нибудь элемента формы нужно вызывать эту команду, принудительно обновляя содержимое формы?
Код: Выделить всё
LblFilename.Caption = "Stage I": Me.Refresh
   for
      ....
   next
LblFilename.Caption = "Stage II": Me.Refresh

alibek писал(а):а в цикле вставить DoEvents или Refresh каждые 50-100 мс.

Объясни, пожалуйста, немного подробнее - ведь DoEvents передает управление операционке, не позволяя программе монополизировать использование процессора, так? Разве она может помочь в обновлении формы?
alibek писал(а):3. cmdOK.Enabled = False

Вот! Именно то, что надо :) Правда теперь, с Me.Refresh, необходимость в кнопках OK и Cancel отпала, программа выполняется без участия пользователя, как я и планировал изначально. Но это пригодится обязательно где-то еще...

alibek
Большой Человек
Большой Человек
 
Сообщения: 14205
Зарегистрирован: 19.04.2002 (Пт) 11:40
Откуда: Russia

Re: Newbie questions (text files processing)

Сообщение alibek » 30.08.2017 (Ср) 19:14

ProgrammingFan писал(а):Правильно ли я понимаю - открываем файл, резервируем строковую переменную равную длине файла, и считываем его весь в эту строку, затем крутим цикл по поиску CHR$(10)+CRH$(13) и записываем построчно? Мне кажется это будет медленнее, чем просто посчитать строки в файле. Да и хватит ли памяти, скажем для разбора полугигабайтного файла?

Если делать правильно, это будет быстро и без расхода памяти.
Читать большими блоками, например по 0,5-2 МБ (системное кеширование будет достаточно эффективным) в байтовый массив, искать переводы строк INSTR и никаких посторонних манипуляций со строкой (конкатенация или прочее). Важное условие — в буфер гарантировано должна умещаться самая длинная строка файла, иначе алгоритм придется существенно усложнять. Если есть возможность (файлы гарантированно не будут слишком большими), то оптимальнее всего сразу считать весь файл в буфер. Или отобразить файл в память, где-то на форуме был пример.
Нужную строку получить с помощью Mid$, сделать с ней необходимые манипуляции и сохранить в выходной файл.

ProgrammingFan писал(а):Да, это именно то, что и требовалось, спасибки :) Получается что каждый раз, когда меняется свойство у какого-нибудь элемента формы нужно вызывать эту команду, принудительно обновляя содержимое формы?

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

ProgrammingFan писал(а):LblFilename.Caption = "Stage I": Me.Refresh

Лучше LblFilename.Refresh.

ProgrammingFan писал(а):Объясни, пожалуйста, немного подробнее - ведь DoEvents передает управление операционке, не позволяя программе монополизировать использование процессора, так? Разве она может помочь в обновлении формы?

Поищи на форуме, тут Хакер уже описывал подробно, что происходит.
При вызове DoEvents сработает все, что накопилось в буфере сообщений оконного цикла. События и перерисовка окна.
Lasciate ogni speranza, voi ch'entrate.

Mikle
Изобретатель велосипедов
Изобретатель велосипедов
Аватара пользователя
 
Сообщения: 4148
Зарегистрирован: 25.03.2003 (Вт) 14:02
Откуда: Туапсе

Re: Newbie questions (text files processing)

Сообщение Mikle » 30.08.2017 (Ср) 22:13

ProgrammingFan писал(а):DoEvents передает управление операционке, не позволяя программе монополизировать использование процессора, так?

Это ты описываешь Sleep, а DoEventsпозволяет обработать очередь событий, то есть, например, как раз прорисует форму, не дожидаясь окончания выполнения какого-нибудь тяжёлого куска кода. DoEvents среди прочего вызовет и Sleep.

ProgrammingFan
Начинающий
Начинающий
 
Сообщения: 9
Зарегистрирован: 20.08.2015 (Чт) 10:26

Re: Newbie questions (text files processing)

Сообщение ProgrammingFan » 31.08.2017 (Чт) 9:35

Mikle писал(а):
ProgrammingFan писал(а):DoEvents передает управление операционке, не позволяя программе монополизировать использование процессора, так?

Это ты описываешь Sleep, а DoEventsпозволяет обработать очередь событий, то есть, например, как раз прорисует форму, не дожидаясь окончания выполнения какого-нибудь тяжелого куска кода. DoEvents среди прочего вызовет и Sleep.

Понятно... Вставил вызов DoEvents в самый загруженный участок кода. Насколько я могу судить по help'у
Код: Выделить всё
Caution   Any time you temporarily yield the processor within an event procedure, make sure the procedure  is not executed again from a different part of your code before the first call returns; this could cause unpredictable results. In addition, do not use DoEvents if other applications could possibly interact with your procedure in unforeseen ways during the time you have yielded control.

главное не вызывать эту процедуру где-нибудь еще. То бишь если есть рекурсия - то не в коем случае...

ProgrammingFan
Начинающий
Начинающий
 
Сообщения: 9
Зарегистрирован: 20.08.2015 (Чт) 10:26

Re: Newbie questions (text files processing)

Сообщение ProgrammingFan » 31.08.2017 (Чт) 9:45

alibek писал(а):Если делать правильно, это будет быстро и без расхода памяти.
Читать большими блоками, например по 0,5-2 МБ (системное кеширование будет достаточно эффективным) в байтовый массив, искать переводы строк INSTR и никаких посторонних манипуляций со строкой (конкатенация или прочее). Важное условие — в буфер гарантировано должна умещаться самая длинная строка файла, иначе алгоритм придется существенно усложнять. Если есть возможность (файлы гарантированно не будут слишком большими), то оптимальнее всего сразу считать весь файл в буфер. Или отобразить файл в память, где-то на форуме был пример.
Нужную строку получить с помощью Mid$, сделать с ней необходимые манипуляции и сохранить в выходной файл.

файлы достаточно большие (бывает, что около гигабайта), и, что еще интереснее, встречаются как обычные переводы строки (CHR$(10)+CHR(13), так и unix-way (CHR$(10). В последнем случае вообще весело: считываю первую строку как LINE INPUT, ожидая получить небольшую строчку (там прописана кодировка, по которой идет дальнейшая обоработка), а в результате получаю весь файл, и заметные тормоза (еще бы, экая глыба в памяти :)

alibek
Большой Человек
Большой Человек
 
Сообщения: 14205
Зарегистрирован: 19.04.2002 (Пт) 11:40
Откуда: Russia

Re: Newbie questions (text files processing)

Сообщение alibek » 31.08.2017 (Чт) 10:28

Значит ищешь строки по 0x0A, и дополнительно пропускаешь 0x0D на концах, если есть.
1ГБ целиком читать в буфер пожалуй не нужно, тем более на VB5.
Подбери буфер и обрабатывай блоками.
Lasciate ogni speranza, voi ch'entrate.

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: Newbie questions (text files processing)

Сообщение Хакер » 31.08.2017 (Чт) 18:49

Советую файл не читать блоками, а маппить в АП процесса. Это намного эффективнее чтения, потому что при чтении данные с диска будут попадать в память, и под эту память будут выделяться страницы из файла подкачки. Страничные фреймы в файле подкачки ресурс дефицитный (делятся между всеми процессами системы).

И по сути во время работы программы у нас одни и те же данные будут и в исходном файле, и в файле подкачки продублированы.

С маппингом такого не будет, более того -- с маппингом исключены лишние page-out операции (если маппинг сделан с правильными параметрами доступа). С маппингом можно было бы потягаться в скорости, делая чтение в overlapped-режиме и читая блоки размерами и смещениями, кратными размеру кластера по адресам, кратным размеру страницы. Но родными средстыами такого не сделать, родной доступ использует самый медленный из возсожных режим чтения.

А если не огрничиваться только родными средствами, то маппинг значительно лучше.

-----

Что касается подхода, обеспечивающего неподвисание окон во время длинных операций, то наилучший подход -- это в цикле подсчитывать кще и время, которое прошло с момента последней обработки событий/сообщений. Если оно превысило некий порог (например 50 мс), то делать обработку и сбрасывать счетчик времени.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

ProgrammingFan
Начинающий
Начинающий
 
Сообщения: 9
Зарегистрирован: 20.08.2015 (Чт) 10:26

Re: Newbie questions (text files processing)

Сообщение ProgrammingFan » 01.09.2017 (Пт) 16:20

alibek писал(а):Значит ищешь строки по 0x0A, и дополнительно пропускаешь 0x0D на концах, если есть.
1ГБ целиком читать в буфер пожалуй не нужно, тем более на VB5.
Подбери буфер и обрабатывай блоками.

А какой смысле в буфере, если файл изначально текстовый? Не проще будет его открыть AS BINARY и затем обрабатывать посимволно, прерываясь на CHR$(10) (или СHR$(10)+CHR$(13)) и записывая получившийся кусок в выходной файл?

ProgrammingFan
Начинающий
Начинающий
 
Сообщения: 9
Зарегистрирован: 20.08.2015 (Чт) 10:26

Re: Newbie questions (text files processing)

Сообщение ProgrammingFan » 01.09.2017 (Пт) 16:35

Хакер писал(а):Советую файл не читать блоками, а маппить в АП процесса. Это намного эффективнее чтения, потому что при чтении данные с диска будут попадать в память, и под эту память будут выделяться страницы из файла подкачки. Страничные фреймы в файле подкачки ресурс дефицитный (делятся между всеми процессами системы).

Чуть подробнее, если можно. Начиная с того, что такое вообще "АП процесса"? Сокращения на кириллице даже не гуглятся толком :) Англоязычные термины в этом смысле гораздо удобнее...

Хакер писал(а): Но родными средстыами такого не сделать, родной доступ использует самый медленный из возсожных режим чтения.

В принципе вполне устраивает быстродействие встроенных средств для дисковых операций. 600k текстовый файл считывается в память секунд за пять (на SSD), но вот расход оперативной памяти и подтормаживание IDE VB вынуждают искать альтернативу

Хакер писал(а):Что касается подхода, обеспечивающего неподвисание окон во время длинных операций, то наилучший подход -- это в цикле подсчитывать кще и время, которое прошло с момента последней обработки событий/сообщений. Если оно превысило некий порог (например 50 мс), то делать обработку и сбрасывать счетчик времени.

Для этого нужно кинуть на форму Timer или просто считать время в цикле?

alibek
Большой Человек
Большой Человек
 
Сообщения: 14205
Зарегистрирован: 19.04.2002 (Пт) 11:40
Откуда: Russia

Re: Newbie questions (text files processing)

Сообщение alibek » 01.09.2017 (Пт) 19:02

ProgrammingFan писал(а):Не проще будет его открыть AS BINARY и затем обрабатывать посимволно, прерываясь на CHR$(10) (или СHR$(10)+CHR$(13)) и записывая получившийся кусок в выходной файл?

Проще. Сделай оба варианта и сравни.
Lasciate ogni speranza, voi ch'entrate.

Teranas
Бывалый
Бывалый
Аватара пользователя
 
Сообщения: 224
Зарегистрирован: 13.12.2008 (Сб) 4:26
Откуда: Новосибирск

Re: Newbie questions (text files processing)

Сообщение Teranas » 04.09.2017 (Пн) 13:40

Я обычно делаю так, может, конечно, и не правильно...

Код: Выделить всё

Public Enum CFileAttributes
  FILE_ATTRIBUTE_READONLY = &H1&
  FILE_ATTRIBUTE_HIDDEN = &H2&
  FILE_ATTRIBUTE_SYSTEM = &H4&
  FILE_OLD_DOS_VOLID = &H8&
  FILE_ATTRIBUTE_DIRECTORY = &H10&
  FILE_ATTRIBUTE_ARCHIVE = &H20&
  FILE_ATTRIBUTE_DEVICE = &H40&
  FILE_ATTRIBUTE_NORMAL = &H80&
  FILE_ATTRIBUTE_TEMPORARY = &H100&
  FILE_ATTRIBUTE_SPARSE_FILE = &H200&
  FILE_ATTRIBUTE_REPARSE_POINT = &H400&
  FILE_ATTRIBUTE_COMPRESSED = &H800&
  FILE_ATTRIBUTE_OFFLINE = &H1000&
  FILE_ATTRIBUTE_NOT_CONTENT_INDEXED = &H2000&
  FILE_ATTRIBUTE_ENCRYPTED = &H4000&
  FILE_ATTRIBUTE_VALID_FLAGS = &H7FB7&
  FILE_ATTRIBUTE_VALID_SET_FLAGS = &H31A7&
End Enum

Public Enum eGenFile
  GENERIC_ALL = &H10000000
  GENERIC_EXECUTE = &H20000000
  GENERIC_WRITE = &H40000000
  GENERIC_READ = &H80000000
End Enum

Public Const CREATE_NEW            As Long = 1
Public Const CREATE_ALWAYS         As Long = 2
Public Const OPEN_EXISTING         As Long = 3
Public Const OPEN_ALWAYS           As Long = 4
Public Const TRUNCATE_EXISTING     As Long = 5
Public Const FILE_SHARE_READ       As Long = 1
Public Const FILE_SHARE_WRITE      As Long = 2
Public Const FILE_SHARE_DELETE     As Long = 4
Public Const FILE_READ_ATTRIBUTES  As Long = &H80
Public Const FILE_BEGIN            As Long = 0
Public Const FILE_CURRENT          As Long = 1

Private Type OVERLAPPED3
  Internal As Long
  InternalHigh As Long
  Offset As Long
  OffsetHigh As Long
  hEvent As Long
End Type

Private Declare Function GetFileSize Lib "kernel32" (ByVal hFile As Long, lpFileSizeHigh As Long) As Long
Private Declare Function CreateFileA Lib "kernel32" (ByVal lpFileName As String, ByVal dwDesiredAccess As Long, ByVal dwShareMode As Long, ByVal lpSecurityAttributes As Long, ByVal dwCreationDisposition As Long, ByVal dwFlagsAndAttributes As Long, ByVal hTemplateFile As Long) As Long
Private Declare Function WriteFile Lib "kernel32" (ByVal hFile As Long, ByVal lpBuffer As Long, ByVal nNumberOfBytesToWrite As Long, lpNumberOfBytesWritten As Long, ByVal lpOverlapped As Long) As Long
Private Declare Function ReadFile Lib "kernel32" (ByVal hFile As Long, ByVal lpBuffer As Long, ByVal nNumberOfBytesToRead As Long, lpNumberOfBytesRead As Long, ByVal lpOverlapped As Long) As Long
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long

Private buf() as byte, ret as long, retbytes as long
Private hFile1 as long, hFile2 as long

' Открываем исходный файл на чтение
hFile1 = CreateFileA("C:\Имя файла1.txt", GENERIC_READ, FILE_SHARE_READ Or FILE_SHARE_WRITE, ByVal 0&, OPEN_EXISTING, 0&, ByVal 0&)
' Открываем конечный файл на запись в него
hFile2 = CreateFileA("C:\Имя файла2_result.txt", GENERIC_WRITE, FILE_SHARE_READ Or FILE_SHARE_WRITE Or FILE_SHARE_DELETE, ByVal 0&, OPEN_ALWAYS, 0&, ByVal 0&)

Do
  ' Размер буфера
  redim buf(4095)
  ' Читаем блок
  ret = ReadFile(hFile1, ByVal VarPtr(buf(0)), nBuf, retbytes, byval 0&)
  if retbytes <= 0 then exit do
  if retbytes <> 4096 then redim preserve buf(retbytes - 1)

  ' Если читаемый блок - первый, то
  ' Определяем идентификатор конца строки, так как в разных системах он разный
  ' (Функция определения идентификатора конца строки)...
 
  ' Обрабатываем полученный блок, не забывая о том, что конец строки не
  ' не в конце блока и данные в конце блока надо сохранить для обработки
  ' в следующем блоке

  ' Обрезаем блок до последнего идентификатора конца строки
  ' разбиваем блок на строки и обрабатываем их
  ' (Функция обработки блока)...

  ' обновляем прогресс-бар
  DoEvents ' Обязательно
   
  ' Записываем обработанный блок
  ret = WriteFile(hFile2, ByVal VarPtr(buf(0)), nBuf, retbytes, byval 0&)
  if retbytes <= 0 then exit do
Loop

' Закрываем файлы
CloseHandle hFile1
CloseHandle hFile2
Последний раз редактировалось Teranas 10.09.2017 (Вс) 2:14, всего редактировалось 1 раз.
С уважением, Андрей.

ProgrammingFan
Начинающий
Начинающий
 
Сообщения: 9
Зарегистрирован: 20.08.2015 (Чт) 10:26

Re: Newbie questions (text files processing)

Сообщение ProgrammingFan » 06.09.2017 (Ср) 0:33

Teranas писал(а):Я обычно делаю так, может, конечно, и не правильно...

Код: Выделить всё
Private Type OVERLAPPED3
  Internal As Long
  InternalHigh As Long
  Offset As Long
  OffsetHigh As Long
  hEvent As Long
End Type

Private Declare Function GetFileSize Lib "kernel32" (ByVal hFile As Long, lpFileSizeHigh As Long) As Long
Private Declare Function CreateFileA Lib "kernel32" (ByVal lpFileName As String, ByVal dwDesiredAccess As Long, ByVal dwShareMode As Long, ByVal lpSecurityAttributes As Long, ByVal dwCreationDisposition As Long, ByVal dwFlagsAndAttributes As Long, ByVal hTemplateFile As Long) As Long
Private Declare Function WriteFile Lib "kernel32" (ByVal hFile As Long, ByVal lpBuffer As Long, ByVal nNumberOfBytesToWrite As Long, lpNumberOfBytesWritten As Long, ByVal lpOverlapped As Long) As Long
Private Declare Function ReadFile Lib "kernel32" (ByVal hFile As Long, ByVal lpBuffer As Long, ByVal nNumberOfBytesToRead As Long, lpNumberOfBytesRead As Long, ByVal lpOverlapped As Long) As Long
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long

Private buf() as byte, ret as long, retbytes as long
Private hFile1 as long, hFile2 as long

' Открываем исходный файл на чтение
hFile1 = CreateFileA("C:\Имя файла1.txt", GENERIC_READ, FILE_SHARE_READ Or FILE_SHARE_WRITE, ByVal 0&, OPEN_EXISTING, 0&, ByVal 0&)
' Открываем конечный файл на запись в него
hFile2 = CreateFileA("C:\Имя файла2_result.txt", GENERIC_WRITE, FILE_SHARE_READ Or FILE_SHARE_WRITE Or FILE_SHARE_DELETE, ByVal 0&, OPEN_ALWAYS, 0&, ByVal 0&)

Do
  ' Размер буфера
  redim buf(4095)
  ' Читаем блок
  ret = ReadFile(hFile1, ByVal VarPtr(buf(0)), nBuf, retbytes, byval 0&)
  if retbytes <= 0 then exit do
  if retbytes <> 4096 then redim preserve buf(retbytes - 1)

  ' Если читаемый блок - первый, то
  ' Определяем идентификатор конца строки, так как в разных системах он разный
  ' (Функция определения идентификатора конца строки)...
 
  ' Обрабатываем полученный блок, не забывая о том, что конец строки не
  ' не в конце блока и данные в конце блока надо сохранить для обработки
  ' в следующем блоке

  ' Обрезаем блок до последнего идентификатора конца строки
  ' разбиваем блок на строки и обрабатываем их
  ' (Функция обработки блока)...

  ' обновляем прогресс-бар
  DoEvents ' Обязательно
   
  ' Записываем обработанный блок
  ret = WriteFile(hFile2, ByVal VarPtr(buf(0)), nBuf, retbytes, byval 0&)
  if retbytes <= 0 then exit do
Loop

' Закрываем файлы
CloseHandle hFile1
CloseHandle hFile2


Экая глыба :) Пытаясь разобраться, сразу возник вопрос - GENERIC_READ откуда брать? Потому как среда ругается на то, что "Variable not defined". Подозреваю, что и со всеми остальными контантами в CreateFileA будет также...

С другой стороны, мне кажется для простой задачи построчной обработки текстового файла такая "тяжелая артиллерия" несколько избыточна. Пока я просто пытаюсь считать строку в текстовом файле, где строки отделены только CHR$(10)... Неужели все равно придется открывать файл так или иначе как BINARY и обрабатывать соответственно? Но ведь он же т-е-к-с-т-о-в-ы-й :-)

pronto
Постоялец
Постоялец
 
Сообщения: 597
Зарегистрирован: 04.12.2005 (Вс) 6:20
Откуда: Владивосток

Re: Newbie questions (text files processing)

Сообщение pronto » 06.09.2017 (Ср) 13:12

ProgrammingFan писал(а):GENERIC_READ откуда брать?

Из MSDN, конечно! CreateFile и Access Mask Format
O, sancta simplicitas!


Вернуться в Visual Basic 1–6

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 49

    TopList