Что нового

[Файлы, Массивы] Медленная запись в файл

F9

Новичок
Сообщения
71
Репутация
2
Добрый день!

Столкнулся с проблемой медленной записи в файл из массива.
Задача такова:
Есть файл File1.txt по сути являющийся файлом CSV, с разделителями в виде ";".
Размер не более 500 Кб
Необходимо выделить столбцы разделенные разделителем, и только некоторые из них (допустим 1,5,4,3 - вставить в файл File2.txt через разделитель @TAB.

Вот как реализовал:
Код:
#include <File.au3>
#include <Array.au3>
#include <Zip_UDF.au3>
#include <_StringsStripChars.au3>


global $var = IniReadSection("config.ini", "file_settings")
If @error Then
    MsgBox(4096, "", "Ошибка! Не могу найти/прочитать файл настроек INI")
Else
EndIf

$FileFfrom = $var[1][1]

global $var = IniReadSection("config.ini", "mail_settings")
$ID = $var[8][1]
$DestFile = FileOpen($ID & "_" & StringTrimLeft(@YEAR,2) & @MON & @MDAY & ".txt",1+8)

For $i = 1 to _FileCountLines($FileFfrom)
	Local $line = FileReadLine($FileFfrom,$i)
	If @error = -1 Then ExitLoop

	Local $StringPart = StringSplit($line, ";") ;читаем строку по разделителям ";".
	;~ Поля для выгрузки:
;~ 1		Наименование товара
;~ 		Страна производитель товара
;~ 4		Производитель товара
;~ 3		Цена розничная с НП
;~ 2		Остаток товра
;~ 		Код товара 
;~ 		Срок годности


FileWrite($DestFile,_StringStripChars($StringPart[1],"/\min" & CHR(034) & CHR(039),3,0,1) & @TAB & $StringPart[5] & @TAB & $StringPart[4] & @TAB & $StringPart[3] &@CR)
Next
FileClose($FileFfrom)
FileClose($DestFile)

Получилось среднее время выполнения сначала было в районе 400 секунд. После этого исправил косяк в логике работы программы, дабы не повторять одни и теже операции в цикле. Получил результат 230 сек.
И все равно я считаю, что это долго! (Комп не сильно старый, i3 + 4 Гб ОЗУ)

Есть у кого идеи как ускорить работу парсера?
Или так и должно быть? Просто до этого на VBScripte был данный скрипт реализован - там процесс занимал не больше минуты-двух.


Добавлено:
Сообщение автоматически объединено:

Ах да, забыл... Функцию _StringsStripChars взял с форума.
Вот она:
Код:
;;===============================================================================
; Название функции:        _StringStripChars()
; Описание:                Очистка (удаление/опщипывание) определённых символов в строке.
;
; Параметры:               $sString       - Строка для обработки.
;                          $sSubString    - Символы (подстрока) которые следует удалять.
;                          $iFlag [Опц.]  - Определяет поведение процесса опщипывания (см. Возвращаемое значение).
;                          $iCount [Опц.] - Определяет количество удалений указанных символов в $sSubString (см. Возвращаемое значение).
;                          $iGroupChars [Опц.] - Если этот параметр равен 1 (по умолчанию 0), то все символы в $sSubString группируются и удаляются по отдельности.
;
; Требования:              AutoIt 3.2.8.1 +
;
; Возвращаемое значение:   При успешной обработке - Возвращает новую строку после удаления символов в соответствии с флагами $iFlag и $iCount:
;                               $iFlag = 0 (по умолчанию) - замена символов по всей строке - с этим флагом @extended будет содержать число произведённых замен в строке.
;                               $iFlag = 1 - замена символов с левой стороны у строки.
;                               $iFlag = 2 - замена символов с правой стороны у строки.
;                               $iFlag = 3 - замена символов с обеих сторон у строки.
;
;                               $iCount = 0 (по умолчанию) - замена всех вхождении символов указанных в $sSubString.
;                               $iCount > 0 - замена N-ое число (указанное в $iCount) вхождении символов $sSubString.
;
;                          При неудачной обработке - Если длина указанной строки равняется нулю (0), то @error устанавливается на 1 и возвращается $sString.
;
; Автор(ы):                amel27, Мод. от G.Sandler a.k.a MsCreatoR
;===============================================================================

Func _StringStripChars($sString, $sSubString, $iFlag = 0, $iCount = 0, $iGroupChars = 0)
    If StringLen($sString) = 0 Then Return SetError(1, 0, $sString)

    Local $sGroupChar_a = '(', $sGroupChar_b = ')'
    If $iCount < 0 Then Local $sGroupChar_a = '[', $sGroupChar_b = ']'

    $sSubString = StringRegExpReplace($sSubString, '([][{}()|.?+*\\^\$])', '\\\1')

    If $iGroupChars = 1 Then $sSubString = '[' & $sSubString & ']'

    Local $sPattern = '(?i)' & $sGroupChar_a & $sSubString & $sGroupChar_b
    Local $sPattern_Count = '{1,' & $iCount & '}'

    If $iCount <= 0 Then $sPattern_Count = '+'
    If $iFlag <> 0 Then $iCount = 0
    If $iFlag = 1 Then $sPattern = '(?i)^' & $sGroupChar_a & $sSubString & $sGroupChar_b & $sPattern_Count
    If $iFlag = 2 Then $sPattern = '(?i)' & $sGroupChar_a & $sSubString & $sGroupChar_b & $sPattern_Count & '$'
    If $iFlag = 3 Then $sPattern = '(?i)^' & $sGroupChar_a & $sSubString & $sGroupChar_b & $sPattern_Count & '|' & _
        $sGroupChar_a & $sSubString & $sGroupChar_b & $sPattern_Count & '$'

    $sString = StringRegExpReplace($sString, $sPattern, '', $iCount)
    Return SetExtended(@extended, $sString)
EndFunc
 

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,322
F9,
Дайте примеры файла-исходника и файла-результата.
 
Автор
F9

F9

Новичок
Сообщения
71
Репутация
2
Файл исходник:

"АТЕНОЛОЛ 0,05 №30 ТАБ;Россия;Фармстандарт-Уфимский витаминный завод;10;3;10348;20130501;
"БЕКЛАЗОН ЭКО 100МКГ 200ДОЗ АЭР (беклометазон);Ирландия;Нортон (Вотерфорд);317,4;1;17745;20130901;
"БЕТОПТИК 0,5% ГЛ КАПЛИ (бетаксолол);Бельгия;Fabrica De Balas Sao Joro S.A. Riclan;195,6;2;2924;20140201;
"БРИЛЛИАНТОВЫЙ ЗЕЛЕН 1% 25МЛ. СПИРТ Р;Россия;ОБНОВЛЕНИЕ ПФК;12,7;1;3328;20120601;
"ВЕРАПАМИЛ 80мг №50;Россия;АЛЬФАПЛАСТИК ОБЪЕДИНЕНИЕ;36,1;2;38769;20160401;
"ВЕРОШПИРОН 50 №30 КАПС (спиронолактон);Венгрия;GEDEON RICHTER;175,8;1;9426;20160101;
"ДИКЛО-Ф 0,1% 5МЛ ГЛ.КАПЛИ /диклофенак/;Индия;PROMED EXPORTS;146,4;1;12659;20121201;
"ДИКЛОФЕНАК 1% 30Г. МАЗЬ;Россия;Синтез АКО ОАО;17;1;40196;20130401;
"ДИКЛОФЕНАК 1% 40,0 гель;Россия;EGIS;46,6;3;568445;20130201;
"ДИКЛОФЕНАК 5% 30,0 гель;;;44,9;1;573540;;
"ДИКЛОФЕНАК 5% 30,0 гель;Россия;Синтез АКО ОАО;41;2;573540;20130601;
"МОНОСАН 40МГ №30 ТАБ (изосорбида мононитрат);Чехия;PRO.MED.CS Praha;140,4;1;572500;20140501;
"МОНОЧИНКВЕ РЕТАРД 50МГ №30 КАПС (изосорбида мононитрат);Россия;Menarini A.Industria;349;1;5976;20120701;
"САЛЬБУТАМОЛ 90доз АЭР /Семашко/;Россия;Мосхимфармпрепараты ФГУП им. Семашко;88,2;3;28127;20130401;
"ЭНАЛАПРИЛ 10 №20 ТАБ /отеч/;Россия;ОЗОН,ООО;7,8;17;80968;20140601;
"ЭНАЛАПРИЛ 20 №20 ТАБ /отеч/;Россия;ОЗОН,ООО;11,5;3;82080;20140601;
//"РЕАФЕРОН-ЕС ЛИПИНТ 500тысМЕ №5 ФЛ (интерферон);Россия;KRKA+Вектор Медика;694,5;1;12153;20121101;
min"ПИЛОКАРПИНА Г/ХЛ 1% 5 МЛ СТЕКЛ;Россия;ДИАФАРМ;15,7;1;43124;20120901;
min"ПИЛОКАРПИНА Г/ХЛ 1% 5 МЛ СТЕКЛ;Россия;Синтез АКО ОАО;26,6;1;43124;20130401;
ВАЛЬСАКОР 0,08 №28 ТАБЛ П/О /валсартан/;Словения;KRKA;255,6;1;572788;20130601;
ВАЛЬСАКОР 0,16 №28 ТАБЛ П/О /валсартан/;Словения;KRKA;387,6;1;573619;20130501;
ГУБКА для тела ОВАЛ;нет;нет;24;1;574023;20120601;
ЗАПУСКАЛКИ НЛО;Китай;нет;28;1;574141;20120805;
ИГРУШКА МЯГ.КРОЛИК 25СМ;Китай;МИР ДЕТСТВА;310;1;86308;20121224;

Файл на выходе должен быть примерно таким:
АТЕНОЛОЛ 0,05 №30 ТАБ 3 10 Фармстандарт-Уфимский витаминный завод
БЕКЛАЗОН ЭКО 100МКГ 200ДОЗ АЭР (беклометазон) 1 317,4 Нортон (Вотерфорд)
БЕТОПТИК 0,5% ГЛ КАПЛИ (бетаксолол) 2 195,6 Fabrica De Balas Sao Joro S.A. Riclan
БРИЛЛИАНТОВЫЙ ЗЕЛЕН 1% 25МЛ. СПИРТ Р 1 12,7 ОБНОВЛЕНИЕ ПФК
ВЕРАПАМИЛ 80мг №50 2 36,1 АЛЬФАПЛАСТИК ОБЪЕДИНЕНИЕ
ВЕРОШПИРОН 50 №30 КАПС (спиронолактон) 1 175,8 GEDEON RICHTER
ДИКЛО-Ф 0,1% 5МЛ ГЛ.КАПЛИ /диклофенак 1 146,4 PROMED EXPORTS
ДИКЛОФЕНАК 1% 30Г. МАЗЬ 1 17 Синтез АКО ОАО
ДИКЛОФЕНАК 1% 40,0 гель 3 46,6 EGIS
ДИКЛОФЕНАК 5% 30,0 гель 1 44,9
ДИКЛОФЕНАК 5% 30,0 гель 2 41 Синтез АКО ОАО
МОНОСАН 40МГ №30 ТАБ (изосорбида мононитрат) 1 140,4 PRO.MED.CS Praha
МОНОЧИНКВЕ РЕТАРД 50МГ №30 КАПС (изосорбида мононитрат) 1 349 Menarini A.Industria
САЛЬБУТАМОЛ 90доз АЭР /Семашко 3 88,2 Мосхимфармпрепараты ФГУП им. Семашко
ЭНАЛАПРИЛ 10 №20 ТАБ /отеч 17 7,8 ОЗОН,ООО
ЭНАЛАПРИЛ 20 №20 ТАБ /отеч 3 11,5 ОЗОН,ООО
РЕАФЕРОН-ЕС ЛИПИНТ 500тысМЕ №5 ФЛ (интерферон) 1 694,5 KRKA+Вектор Медика
ПИЛОКАРПИНА Г/ХЛ 1% 5 МЛ СТЕКЛ 1 15,7 ДИАФАРМ
ПИЛОКАРПИНА Г/ХЛ 1% 5 МЛ СТЕКЛ 1 26,6 Синтез АКО ОАО
ВАЛЬСАКОР 0,08 №28 ТАБЛ П/О /валсартан 1 255,6 KRKA
ВАЛЬСАКОР 0,16 №28 ТАБЛ П/О /валсартан 1 387,6 KRKA
ГУБКА для тела ОВАЛ 1 24 нет
ЗАПУСКАЛКИ НЛО 1 28 нет
ИГРУШКА МЯГ.КРОЛИК 25СМ 1 310 МИР ДЕТСТВА

То есть, без всяких служебных символов, таких как слэши, кавычки...
Порядок полей указан в певом IT-тэге
PS
Кстати не могу никак убрать кавычку внутри строки, сразу после слова(без пробела).
В регулярных - не вообще не силен :stars:
 

WSWR

AutoIT Гуру
Сообщения
941
Репутация
363
F9

Взял функцию с оф форума:

Код:
#include <Array.au3>
#include <FileConstants.au3>

Local $a2dArray = 0, $sText = ''
$sFilePath = @ScriptDir & '\TestDB.txt'

_FileReadToArray2D(@ScriptDir & '\1.txt', $a2dArray, Default)

;_ArrayDisplay($a2dArray)

For $j = 1 To $a2dArray[0][0]
	$sText &= $a2dArray[$j][0] & @TAB & $a2dArray[$j][4] & @TAB & $a2dArray[$j][3] & @TAB & $a2dArray[$j][2] & @CRLF	
Next

$hFileOpen = FileOpen($sFilePath, $FO_OVERWRITE)

FileWrite($hFileOpen, StringRegExpReplace($sText, '(")|(//)|( ")', ''))
FileClose($hFileOpen)

Func _FileReadToArray2D($sFilePath, ByRef $aArray, $sDelimiter = Default)
	$aArray = 0
	Local $aSRE = StringRegExp(FileRead($sFilePath) & @LF, '([^\r\n]*)(?:\r\n|\n|\r)(?:[\r\n]$)?', 3) ; By DXRW4E.
	If @error Then
		Return SetError(1, 0, 0)
	EndIf
	Local $iUBound = UBound($aSRE, 1)
	If $sDelimiter = Default Then
		$sDelimiter = ';'
	EndIf
	Local $aSplit = StringSplit($aSRE[0], $sDelimiter)
	If @error Then
		Return SetError(2, 0, 0)
	EndIf

	Local $aArrayTemp[$iUBound + 1][$aSplit[0]] = [[0]]
	For $i = 0 To $iUBound - 1
		$aSplit = StringSplit($aSRE[$i], $sDelimiter)
		If @error Then
			ContinueLoop
		EndIf

		$aArrayTemp[0][0] += 1
		For $j = 1 To $aSplit[0]
			$aArrayTemp[$aArrayTemp[0][0]][$j - 1] = $aSplit[$j]
		Next
	Next
	$aArray = $aArrayTemp
	$aArrayTemp = 0
EndFunc   ;==>_FileReadToArray2D


С удалением символов только не понял
 
Автор
F9

F9

Новичок
Сообщения
71
Репутация
2
ВАУ!
Круто, 2 секунды и готово.. :shok: :laugh: :laugh:
Теперь можно мне какие нибудь коментарии - что сделано и почему с двумерным массивом быстрее работает?


PS
с удалением тоже всё как надо!
_StringsStripChars - использовал только потому, что там синтаксис примитивно понятный, а не как в StringRegExp :stars:

PPS
А как к этому выражению,
Код:
StringRegExpReplace($sText, '(")|(//)|( ")', '')

добавить условие на удаление пробелов ТОЛЬКО в начале строки ?
 

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,322
F9,
Мой вариант, без доп. функций.
Код:
Local $aColumn[5] = [4, 1, 5, 4, 3], _ ;$aColumn[0] - кол-во колонок в массиве
		$iMax, $sTxt, $aTxt, $aTmp, $hFile

For $i = 1 To $aColumn[0]
	If $iMax < $aColumn[$i] Then $iMax = $aColumn[$i]
Next
$aTxt = StringSplit(StringStripCR(FileRead(@ScriptDir & '\1.txt')), @LF)
For $i = 1 To $aTxt[0]
	$aTmp = StringSplit($aTxt[$i], ';')
	If $aTmp[0] < $iMax Then ContinueLoop
	For $j = 1 To $aColumn[0]
		$sTxt &= $aTmp[$aColumn[$j]] & @TAB
	Next
	$sTxt = StringTrimRight($sTxt, 1) & @CRLF
Next
$hFile = FileOpen(@ScriptDir & '\1_new.txt', 2)
FileWrite($hFile, StringRegExpReplace($sTxt, '(?m)^[^ЁА-Я]*|"', ''))
FileClose($hFile)
 
Верх