Форум » [x]Harbour » Разделить файл » Ответить

Разделить файл

rvu: Есть большой текстовый файл, нужно его поделить по числу строк. Например, кусками по 10 000 строк. Или по 100 000. Есть способ? Понятно, что можно искать CHR(13)+CHR(10) и отрезать по кусочку, но как-то очень это долго. Причем, длительность еще не самая большая проблема.

Ответов - 28, стр: 1 2 All

Dima: rvu [pre2] if hb_fuse(TMMP+sysname+".doc")#0 do while !hb_feof() // считаем строки и пишем во временную строку , как набралось нужное кол-во строк , пишем эту строку в файл , Hb_memowrite Cstr:=hb_freadln()) hb_fskip() enddo [/pre2]

fil: А fread не шустрее ? Читаем в цикле блок по 64К, парсим этот блок по строкам, а затем к остатку клеим новые 64К.

Dima: fil пишет: А fread не шустрее ? Тестить надо

rvu: Спасибо! Покопался на форуме поиском, нашел примеры интересные. А есть руководство по Харбору, где бы эти и другие полезные функции были описаны? У меня есть какой-то файл, но в нем этих функций нет.

Andrey: Вот это будет шустрее. [pre2] cTxt := HB_Memoread("имя и путь к файлу") aDim := HB_ATokens( cTxt, CHR( 13 ) + CHR( 10 ), .T., .T. ) cTxt := "" FOR nI := 1 TO LEN(aDim) // здесь обработка строк и запись по кускам // HB_MemoWrit("имя файла для записи", cTxt) NEXT[/pre2]

Dima: Andrey пишет: Вот это будет шустрее. Вполне возможно.

rvu: hb_freadln() разбивает строчку на две, если ее длина больше, чем 4096 знаков. Что для меня не подходит. Или отслеживать длину всех строк и потом ошибочные склеивать, или все-таки искать CHR(13)+CHR(10).

Петр: rvu пишет: Или отслеживать длину всех строк и потом ошибочные склеивать, или все-таки искать CHR(13)+CHR(10) или переопределить размер буфера #define _B_SIZE 4096 => #define _B_SIZE 32768 и перекомпилировать библиотеку

rvu: Библиотека hbmisc.lib? А где взять исходник? Я пользуюсь MiniGUI, .lib файл там такой есть, но что в него компилировать? В установленный у меня харбор полез искать, там явно версия другая, чем в MiniGUI. Вообще, если не сложно, расскажите подробнее. Какой-то харбор скачал, тему про компилирование библиотеки нашел, чуть позже попробую. Но если есть какие-то специфические особенности, подскажите, пожалуйста.

Dima: rvu пишет: hb_freadln() разбивает строчку на две, если ее длина больше, чем 4096 знаков После первой автоматом не дописывается CRLF ? Андрей выше предлагал еще вариант.

rvu: Dima пишет: После первой автоматом не дописывается CRLF ? Она дописывает его и после первой части и после второй. И вместо одной строки получается две. Dima пишет: Андрей выше предлагал еще вариант. Я помню про него, но сначала хотел с тем вариантом разобраться.

rvu: А в HB_Memoread() тоже, наверное, ограничения по размеру есть? У меня файл большой, около 10 гигов.

Dima: rvu пишет: У меня файл большой, около 10 гигов Что в нем живет , все собрания сочинений В.И. Ленина ? ЗЫ HB_Memoread виснет или что ? Может надо просто подождать , размер то не слабый....

Haz: rvu пишет: У меня файл большой, около 10 гигов. Скорее всего будет ошибка при попытке выделить память. Нужно читать блоками и парсить блоки как предложил Андрей, возвращаясь при чтении назад на размер последнего элемена массива. При этом игнорировать этот последний элемент. Это на тот случай если в нем только часть строки. Для файлов вменяемого размер предложение Адрея оптимально. Задача на 10 минут

Andrey: Haz пишет: Задача на 10 минут +1

rvu: Dima пишет: HB_Memoread виснет или что ? Нет, в нем ограничение, просто не читает весь файл.

rvu: Haz пишет: Нужно читать блоками и парсить блоки как предложил Андрей, возвращаясь при чтении назад на размер последнего элемена массива. При этом игнорировать этот последний элемент. Это на тот случай если в нем только часть строки. Казалось, что перекомпилировать библиотеку проще, но пока это не удалось.

Петр: rvu пишет: Казалось, что перекомпилировать библиотеку проще, но пока это не удалось. Это дело 5-ти минут. Попробую пошагово описать (как смогу, если что - извините ) Исходные данные : MiniGUI у меня находится на диске C:, BCC на диске F: Значит в \BATCH\minigui.cfg должны быть прописаны такие строки MG_BCC=f:\borland\bcc55 MG_ROOT=c:\minigui В BATCH\hbmk2.bat меняю эту строку if not defined MG_BCC set MG_BCC=f:\borland\bcc55 Затем иду сюда (мы ведь помним, что MiniGUI для BCC построен на hb 3.2) и с помощью зеленой кнопки загружаю архив с исходниками (Download Zip) Извлекаю из указаного архива папку с библиотекой hbmisk и помещаю ее в c:\minigui\source, т.е. в папке Source у нас появилась еще одна папка hbmisk, а в ней нужные нам файлы. Дальше, не сильно мудрствуя, набираю в командной строке команду C:\MiniGUI\BATCH\hbmk2.bat C:\MiniGUI\SOURCE\hbmisc\hbmisc.hbp и запускаю ее на выполнение клавишей Enter (я работаю в Far и использую для таких случаев Ctrl + F, но это дело вкуса) После завершения работы находим в папке с исходниками и нужную нам библиотеку. Если все работает, правим нужные файлы и опять перекомпилируем. Вручную перемещаем (заменяем) библиотеку в папку C:\MiniGUI\Harbour\Lib\, но можем и файл проекта поправить - это как кому нравится, в общем несущественно для разовой работы. Писал эту "инструкцию" дольше чем делал. Куда вы сбросите файлы с исходниками - это тоже не важно: все имена папок являются вымышленными и любое совпадение с реально существующими или когда-либо существовавшими папками случайно

SergKis: rvu Очень давно (с S87) использую [pre2] FUNCTION fRLine( h, b, s, l ) LOCAL r := .T., c, i, j, k, n, p b := '' l := iif( Empty( l ), 1024, l ) s := iif( Empty( s ), chr(13)+chr(10), s ) c := space( l ) n := len( s ) - 1 DO WHILE .T. i := fRead(h, @c, l) j := left( c, l ) IF ( p := at( s, j ) ) > 0 b += left( j, p - 1) fSeek( h, -( i - ( p + n ) ), 1 ) EXIT ELSE b += j IF i < l r := .F. EXIT ENDIF ENDIF ENDDO RETURN r использование ... IF( hFile := fOpen( cFile ) ) <= 0; RETURN .F. ENDIF cBuf := '' DO WHILE ! fRLine( hFile, @cBuf, chr(13)+chr(10), 4096 ) IF Len(cBuf) > 0 ... ENDIF ENDDO fClose( hFile ) RETURN .T. [/pre2]

rvu: Петр пишет: Попробую пошагово описать (как смогу Огромное спасибо, все работает! И написано очень доступно. Всем спасибо за дельные советы! Может быть, позднее попробую способ Андрея, тоже интересно.

Andrey: rvu пишет: Может быть, позднее попробую способ Андрея, тоже интересно. Я не знаю, можно ли в переменную загнать 10 Гб ( я так понял это размер файла) ? [pre2]cTxt := HB_Memoread("имя и путь к файлу")[/pre2] До 1 Гб делал. Нужно пробовать.

rvu: Andrey пишет: Я не знаю, можно ли в переменную загнать 10 Гб ( я так понял это размер файла) ? У меня не получилось. Я выше писал об этом.

Andrey: Всем привет ! Просто интересно: 1) Какая максимальная текстовая строка может быть в Харборе ? 2) Какой максимальный размер одномерного массива может быть в Харборе ?

Pasha: Ограничение длины строки для Harbour 32-bit - 4Г, размер массива соответственно 4 млрд элементов. С хвостиком, естественно. Для Harbour 64-bit - это 2^64 байт, или элементов. Это какие-то там сумасшедшие эксибайты, где-то 10 в 20й степени. Но даже выделять гигабайты в программе крайне не рекомендуется. Если и хватит виртуальной памяти, это не будет способствовать стабильной работе OS. Выделять такой объем памяти под массив строк еще хуже, чем для одной строки, так как памяти понадобится больше. Для работы с таким огромным массивом строк (если строка в среднем 50 байт, это будет 200 млн.строк) лучше сделать таблицу, можно и dbf, с полем скажем типа Variant (это разновидность memo). Сформировать эту таблицу, и ползать по ней, не перенапрягая несчастную операционную систему гигантскими запросами.

rvu: Pasha пишет: Но даже выделять гигабайты в программе крайне не рекомендуется. Если и хватит виртуальной памяти, это не будет способствовать стабильной работе OS. У меня есть еще одна задача, где я файл размером немного больше гига делю по строчкам. Компьютер с 4 гигами оперативки нормально к такому относится.

PSP: rvu пишет: У меня есть еще одна задача, где я файл размером немного больше гига делю по строчкам. Компьютер с 4 гигами оперативки нормально к такому относится. Может незаметно настать момент, когда файл будет гораздо больше и ОС им подавится. Присоединюсь к Павлу, лучше использовать dbf.

Pasha: Вот именно. У меня как раз комп с 4Г Для harbour 32-bit выдаю space(1000000000) секунда задержки, и запрос выполняется а для space(2000000000) программа сначала задумывается на несколько секунд, а затем вываливается с ошибкой 9006, хоть предел размера строки на 4Г не превышен. ОС не смогла выполнить запрос. А может выполнить, но другая задача захлебнется от нехватки памяти. Дополню: все это касается 64-битной ОС. Для 32-битной дело обстоит еще печальнее.

Pasha: Берем Harbour-64, ОС и комп тот же: win7-64 и 4G RAM запрашиваем space(1000000000) Без проблем, одна секунда - и все в порядке. Поднимаем ставки space(2000000000) space(3000000000) 10-15 секунд задержки, но система справляется. Идем на рекорд: space(4000000000) Программа "виснет" на несколько минут, ОС тоже, индикатор диска бешено мигает, но в конце концов запрос выполняется. Затем пару минут ОС ведет себя несколько задумчиво и глючно, видимо, освобождает выделенную память. В конце концов работоспособность восстанавливается. Дальше пробовать не стал. Повторюсь: огромные объемы памяти запросить можно, но делать это не стоит. Это как участвовать в соревновании: кто больше скушает водки пельменей. Победить можно, но можно и помереть.



полная версия страницы