Что нового

[Файловая система] Объединить два больших txt файла

vasykas

Новичок
Сообщения
24
Репутация
0
Здравствуйте.
Пытаюсь объединить 2 больших текстовых файла:

Код:
Func _too()
$iStart = TimerInit()
$hFile = FileOpen(@scriptdir&"\result.txt", 2)
$text = GUICtrlRead($fileList) 
$read = StringSplit(StringStripCR($text), @LF)
$Array = _ArrayUnique($read, 1, 1)
    _ArrayDelete($Array, 0)
For $i = 0 to UBound($Array) - 1
$iFileSize = FileGetSize($Array[$i])
If $iFileSize > 200000000 Then
 While 1
FileWrite($hFile, FileRead($Array[$i], 150*1024*1024))
If @error = -1 Then ExitLoop
If FileRead($Array[$i], 150*1024*1024) = $iFileSize Then ExitLoop ; вот здесь не могу сообразить
WEnd
EndIf
 FileWrite($hFile, FileRead($Array[$i]))
	
Next
FileClose($hFile)
EndFunc


если файл больше 200 мб то соединяем блоками по 150мб
не могу выйти с цикла по достижении конца файла
копирует 2-3..гига и т.д бесконечно кто что подскажет
спасибо.
 

AZJIO

Меценат
Меценат
Сообщения
2,892
Репутация
1,196
vasykas
Прокомментировал твой код. Избався от создания кучи лейблов. Сделай их заранее (3 штуки) и просто обновляй данные.
Код:
Func _too()
	$iStart = TimerInit()
	$hFile = FileOpen(@scriptdir&"\result.txt", 2)
	$text = GUICtrlRead($fileList)
	$read = StringSplit(StringStripCR($text), @LF)
	$Array = _ArrayUnique($read, 1, 1)
		_ArrayDelete($Array, 0) ; Можно удалить 0-индекс ещё в StringSplit
	For $i = 0 to UBound($Array) - 1
	  If GUIGetMsg() = $stop Then ExitLoop ; вылет если стоп
		$iFileSize = FileGetSize($Array[$i]) ; размер файла
		GUICtrlCreateLabel($Array[$i], 100, 260, 280) ; создаём лейбл и суём в него путь, а может лучше вставить в существующий лейбл, обновляя данные?  Смотри GUICtrlSetData
		GUICtrlSetFont(-1, 8, 180, 4, $font) ; И не придётся ему вцикле назначать размер
		If $iFileSize > 200000000 Then ; Если размер больше 200 Мб, то... (а если меньше, то игнор что-ли? где "иначе" - else)
		   $a1 = $Array[$i] ; не вижу использование $a1 в дальнейшем
			 While 1
				GUICtrlCreateLabel(StringFormat('%.2f sec', TimerDiff($iStart) / 1000), 175, 40, 60) ; Опять чтоли создаём тучу лейблов? Смотри GUICtrlSetData
				GUICtrlSetFont(-1, 11, 180, 4, $font) ; И каждый раз размер?
				If GUIGetMsg() = $stop Then ExitLoop ; вылет если стоп
				FileWrite($hFile, FileRead($Array[$i], 150*1024*1024)) ; Читаем 150 Мб? Читает каждый раз с начала, а надо открыть в дескриптор, чтобы запоминать позицию.
				If @error = -1 Then ExitLoop
				If FileRead($Array[$i], 150*1024*1024) = $iFileSize Then ExitLoop ; вот здесь не могу сообразить... прочитанное из файла очень длинный текст и он ни как не будет равен числу "200000000", потому что 200000000 чостоит из 9 символов, а прочитанное из 150 тысяч символов.
			WEnd
		EndIf
		 FileWrite($hFile, FileRead($Array[$i])) ; Зачем мы выполняли цикл выше если тут мы снова читаем файл и пишем, наверно это для случая "иначе" - else
		 If GUIGetMsg() = $stop Then ExitLoop ; вылет если стоп
		GUICtrlCreateLabel(StringFormat('%.2f sec', TimerDiff($iStart) / 1000), 175, 40, 60) ; Ещё что-ли туча лейблов? Смотри GUICtrlSetData
		GUICtrlSetFont(-1, 11, 180, 4, $font)  
	Next
	FileClose($hFile)
EndFunc
 
Автор
V

vasykas

Новичок
Сообщения
24
Репутация
0
с дескриптором вроде разобрался (наверно :smile: )
Код:
$hFile = FileOpen(@scriptdir&"\result.txt", 16 + 2)

но как выйти с цикла не могу всеровно сообразить (здесь понятно намудрил)
Код:
If FileRead($Array[$i], 150*1024*1024) = $iFileSize Then ExitLoop ; вот здесь не могу сообразить... прочитанное из файла очень длинный текст и он ни как не будет равен числу "200000000", потому что 200000000 чостоит из 9 символов, а прочитанное из 150 тысяч символов.

поидее он должен сам выйти... по достижении конца файла?
 

inververs

AutoIT Гуру
Сообщения
2,135
Репутация
465
Код:
_too()

Func _too()
	Local Const $buffer = 150 * 1024 * 1024

	Local $hOut = FileOpen('result.txt', 2) ;файл куда пишем
	Local $hIn = FileOpen('file.txt') ;большой файл
	Local $data

	While 1
		$data = FileRead($hIn, $buffer)
		If @error Or Not @extended Then
			ExitLoop
		EndIf
		FileWrite($hOut, $data)
	WEnd

	FileClose($hIn)
	FileClose($hOut)

EndFunc
 

AZJIO

Меценат
Меценат
Сообщения
2,892
Репутация
1,196
vasykas
Корректировка скрипта (2 раза). Проверить не начем, тестируй, разбирайся.
Код:
$iLb_path = GUICtrlCreateLabel('', 100, 260, 280)
GUICtrlSetFont(-1, 8, 180, 4, $font)
$iLb_timer = GUICtrlCreateLabel('', 175, 40, 60)
GUICtrlSetFont(-1, 11, 180, 4, $font)
 
Func _too()
	Local $iReadSize, $iStart, $hFile, $text, $asArray, $iFileSize, $hFileDst
	$iReadSize = 150*1024*1024 ; 150 Мб многовато. Столько памяти будет являтся требовательснотью к парограмме. Достаточно по 10 Мб буфер памяти.
	$iStart = TimerInit() ; Засекаем время
	$hFile = FileOpen(@scriptdir & "\result.txt", 2) ; Открываем файл к которому присоединение данных, удаляя его содержимое.
	If $hFile = -1 Then Return ; Вылет если файл не открылся
	$text = GUICtrlRead($fileList) ; Читаем файл путей
	$asArray = StringSplit($text, @CRLF, 2+1) ; Разделяя переносом строки @CRLF, не возвращая число элементов массива.
	$asArray = _ArrayUnique($asArray)
	For $i = 0 to UBound($asArray) - 1
		If GUIGetMsg() = $stop Then ExitLoop ; вылет если стоп. Кстати, опрос события тормозит выполнения цикла, лучше зарегистрировать горячую клавишу.
		$iFileSize = FileGetSize($asArray[$i]) ; размер файла
		GUICtrlSetData($iLb_path, $asArray[$i]) ; суём путь
		If $iFileSize > 200000000 Then ; Если размер больше 200 Мб, то...
		   $hFileDst = FileOpen($asArray[$i]); Открываем файл для чтения
			 While 1
				GUICtrlSetData($iLb_timer, StringFormat('%.2f sec', TimerDiff($iStart) / 1000)) ; время
				If GUIGetMsg() = $stop Then
					FileClose($hFileDst) ; Закрываем файл
					ExitLoop 2 ; вылет из двух циклов если стоп (в теории надо не просто выпрыгнуть из цикла, но и закрыть дескрипторы файлов)
				EndIf
				$tmp = FileRead($hFileDst, $iReadSize) ; Читаем по 150 Мб пока файл не закончится
				If @error = -1 Then ExitLoop ; Выпрыгиваем если достигнут конец файла
				FileWrite($hFile, $tmp)
			WEnd
			FileClose($hFileDst)
		Else
			FileWrite($hFile, FileRead($asArray[$i]))
		EndIf
		GUICtrlSetData($iLb_timer, StringFormat('%.2f sec', TimerDiff($iStart) / 1000)) ; время
	Next
	FileClose($hFile)
EndFunc


поидее он должен сам выйти... по достижении конца файла?
Читай в справке -1 означает прочитанно до конца, то есть правильно у тебя. Хотя нет, -1 у тебя относится к FileWrite, а надо к FileRead. Вынеси чтение наружу в отдельную строку и проверяй его ошибку.
 
Автор
V

vasykas

Новичок
Сообщения
24
Репутация
0
если я разделяю: FileWrite и FileRead то выскакивает Ошибка выделения памяти
а когда в одну строку то ошибки нет (не знаю почему)

Код:
FileWrite($hFile, FileRead($Array[$i]))

может попробовать FileWriteLine и FileReadLine
там можно For и Ubount задействовать они точно цикл закончят
по достижении конца файла
 

AZJIO

Меценат
Меценат
Сообщения
2,892
Репутация
1,196
vasykas
если я разделяю: FileWrite и FileRead то выскакивает Ошибка выделения памяти
Уменьши размер 150 Мб до 10 Мб. Зачем такими огромными пачками писать. Программа повышает свою требовательность к памяти. Она требует 150 Мб для своей работы, а это много. Лучше читать и писать в бинарном режиме, так как в 2 раза меньше использует память, не переводит ANSI в UTF16.

может попробовать FileWriteLine и FileReadLine
Лучше найти ошибку чем ухудшать.

И посмотри, я сделал поправки в скрипте, обновил.
 
Автор
V

vasykas

Новичок
Сообщения
24
Репутация
0
Ураааа!!!
Уменьшил до 50мб
Все отлично, буду разбираться в коде.
век живи век учись.
Всем огромное спасибо.
 
Верх