Автор Тема: Поиск не заполненны строк в файлах, с выводом подробного отчета  (Прочитано 6995 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Оффлайн Tyr [?]

  • Новичок
  • *
  • Сообщений: 29
  • Репутация: 3
  • Пол: Мужской
    • Награды
Версия AutoIt:3.3.8.1
Описание:
Необходимо производить поиск строк в которых заполнен вид данных, но, отсутствуют сами данные (т.е. заполненная строка выглядит так: "ДатаДок: 11.01.12", а не заполненная: "ИННПП:"), и в случае обнаружения такой строки создавать файл с таким же именем как и проверяемый файл, но с разрешением .log.
Файл *log (в идеале) должен содержать:
№ строки начала блока в котором найдены пропущенные данные(блоки в текстовых файлах разделены "#"), Наименование пропущеного блока, ДатаОпер, НомДок, Дебет, Кредит
Данные пропуск которых необходимо проверять: 'НаимБП:', 'БИКБП:', 'НаимПП:', 'ИННПП:', 'НомСчПП:', 'НазнПл:'

Примечания:
madmasles, изменил и оптимизировал мой первоначальный код самой проверки на наличие пустых строк и сделал вывод в _ArrayDisplay :
Код: AutoIt [Выделить]
#include <Encoding.au3>
#include <Array.au3>

Local $s_File = @ScriptDir & '\BV201_ZNO3434343.txt'

Local $a_Search[15] = [14, 'ДатаОпер:', 'ВидДок:', 'НомДок:', 'ДатаДок:', 'НомКорСч:', 'НаимБП:', 'БИКБП:', 'НаимПП:', 'ИННПП:', 'КПППП:', 'НомСчПП:', _
        'Дебет:', 'Кредит:', 'НазнПл:'], $v_Tmp, $a_Str, $a_Ret[1], $a_Tmp[$a_Search[0] + 1], $i_Len

Local $i_Timer = TimerInit()
$i_Len = StringLen($a_Search[1])
$v_Tmp = StringStripCR(_Encoding_OEM2ANSI(FileRead($s_File)))
For $i = 1 To $a_Search[0]
    If StringInStr($v_Tmp, $a_Search[$i] & @LF, 1) Then
;~  If StringRegExp($v_Tmp, '(?m)^' & $a_Search[$i] & '$') Then
        $a_Tmp[0] += 1
        $a_Tmp[$a_Tmp[0]] = $i
    EndIf
Next
If Not $a_Tmp[0] Then Exit MsgBox(64, '', 'All OK!')
$a_Str = StringSplit($v_Tmp, @LF)
$v_Tmp = 0
ReDim $a_Ret[$a_Str[0] + 1][$a_Tmp[0]]
For $i = 1 To $a_Str[0]
    For $j = 0 To $a_Tmp[0] - 1
        If $a_Str[$i] == $a_Search[$a_Tmp[$j + 1]] Then
            $a_Ret[0][$j] += 1
;~          $a_Ret[$a_Ret[0][$j]][$j] = $i
;~          $a_Ret[$a_Ret[0][$j]][$j] = $i & ' (' & $a_Str[$i - $a_Tmp[$j + 1] + 1] & ')'
            $a_Ret[$a_Ret[0][$j]][$j] = $i & ' (' & StringTrimLeft($a_Str[$i - $a_Tmp[$j + 1] + 1], $i_Len) & ')'
;~          ConsoleWrite($a_Str[$i - $a_Tmp[$j + 1] + 1] & @LF)
        EndIf
    Next
Next
For $i = 0 To $a_Tmp[0] - 1
    If $v_Tmp < $a_Ret[0][$i] Then $v_Tmp = $a_Ret[0][$i]
    $a_Ret[0][$i] = $a_Search[$a_Tmp[$i + 1]] & ' (' & $a_Ret[0][$i] & ')'
Next
ReDim $a_Ret[$v_Tmp + 1][$a_Tmp[0]]
ConsoleWrite(TimerDiff($i_Timer) & @LF)
_ArrayDisplay($a_Ret)
 


Так же вот мой изначальный код, который выбирал файлы по маске и последовательно выполнял их обработку:
(нажмите для показа/скрытия)
Выкладываю несколько файлов для обработки
« Последнее редактирование: Сентябрь 10, 2013, 20:25:40 от Tyr »

Русское сообщество AutoIt


Оффлайн madmasles [?]

  • Глобальный модератор
  • *
  • Сообщений: 7790
  • Репутация: 2314
  • Пол: Мужской
  • Награды За модерирование форума
    • Награды
  • Версия AutoIt: 3.3.x.x
ПредупреждениеЗа нарушение правил форума (пункт В.11):
Цитировать
Любые отрывки AutoIt кода необходимо заключать в тег [autoit] (подробнее), а обычный код соответственно в тег [code] (подробнее). Также большие выдержки текста помещайте под тег [spoiler] (подробнее), там где это поддерживается естественно. Как в случае с названием темы, также короткое и эргономичное сообщение привлекает больше внимания, и шансы на получение конкретного ответа увеличиваются.


С уважением, ваш Глобальный модератор.


Добавлено: Сентябрь 09, 2013, 17:28:52
Tyr,
Используйте из Encoding UDF - Библиотека для работы с кодировками строк функции _Encoding_OEM2ANSI() или _Encoding_866To1251(), чтобы было удобно читать.
Код: AutoIt [Выделить]
#include <Encoding.au3>

ConsoleWrite(_Encoding_866To1251('Ќ®¬‘зЏЏ:') & @LF)

« Последнее редактирование: Сентябрь 09, 2013, 17:28:52 от madmasles, Причина: Объединение сообщений »

Оффлайн Yashied [?]

  • AutoIt MVP
  • Глобальный модератор
  • *
  • Сообщений: 5379
  • Репутация: 2694
  • Пол: Мужской
    • Награды
  • Версия AutoIt: 3.3.x.x
Спасибо. Тему можно закрыть.

На форуме принято помечать тему решенной после получения ответа на свой вопрос!
Вверху или внизу темы нажмите на ссылку такого вида:
Тема не решена


Думай, прежде чем говорить.

Оффлайн madmasles [?]

  • Глобальный модератор
  • *
  • Сообщений: 7790
  • Репутация: 2314
  • Пол: Мужской
  • Награды За модерирование форума
    • Награды
  • Версия AutoIt: 3.3.x.x
Tyr  [?]
Цитировать
Может кто подскажет как сделать так, что бы...
ПредупреждениеЗа нарушение общих правил (пункт В.4):
Цитировать
Не лепите несколько вопросов разной тематики в один пост. По типу "Ребят, а ещё такой вопрос...". Каждый вопрос в свою тему.


С уважением, ваш Глобальный модератор.
Так должно быстрее работать.
Код: AutoIt [Выделить]
#include <Encoding.au3>
#include <Array.au3>

Local $s_File = @ScriptDir & '\BV201_ZNO3434343.txt'

Local $a_Search[15] = [14, 'ДатаОпер:', 'ВидДок:', 'НомДок:', 'ДатаДок:', 'НомКорСч:', 'НаимБП:', 'БИКБП:', 'НаимПП:', 'ИННПП:', 'КПППП:', 'НомСчПП:', _
        'Дебет:', 'Кредит:', 'НазнПл:'], $v_Tmp, $a_Str, $a_Ret[1], $a_Tmp[$a_Search[0] + 1]

Local $i_Timer = TimerInit()

$v_Tmp = StringStripCR(_Encoding_OEM2ANSI(FileRead($s_File)))
For $i = 1 To $a_Search[0]
    If StringRegExp($v_Tmp, '(?m)^' & $a_Search[$i] & '$') Then
        $a_Tmp[0] += 1
        $a_Tmp[$a_Tmp[0]] = $i
    EndIf
Next
If Not $a_Tmp[0] Then Exit MsgBox(64, '', 'All OK!')
$a_Str = StringSplit($v_Tmp, @LF)
$v_Tmp = 0
ReDim $a_Ret[$a_Str[0] + 1][$a_Tmp[0]]
For $i = 1 To $a_Str[0]
    For $j = 0 To $a_Tmp[0] - 1
        If $a_Str[$i] == $a_Search[$a_Tmp[$j + 1]] Then
            $a_Ret[0][$j] += 1
            $a_Ret[$a_Ret[0][$j]][$j] = $i
        EndIf
    Next
Next
For $i = 0 To $a_Tmp[0] - 1
    If $v_Tmp < $a_Ret[0][$i] Then $v_Tmp = $a_Ret[0][$i]
    $a_Ret[0][$i] = $a_Search[$a_Tmp[$i + 1]] & ' (' & $a_Ret[0][$i] & ')'
Next
ReDim $a_Ret[$v_Tmp + 1][$a_Tmp[0]]
ConsoleWrite(TimerDiff($i_Timer) & @LF)
_ArrayDisplay($a_Ret)

« Последнее редактирование: Сентябрь 09, 2013, 21:11:43 от madmasles »

Русское сообщество AutoIt

Re: Не работает внешний цикл при наличие внутреннего
« Ответ #3 Отправлен: Сентябрь 09, 2013, 19:40:06 »

Оффлайн Tyr [?]

  • Новичок
  • *
  • Сообщений: 29

  • Автор темы
  • Репутация: 3
  • Пол: Мужской
    • Награды
madmasles, так реально раз в 10 быстрее - те файлы которые обрабатывал за 2 минуты, за 10 секунд считает. Сейчас разберусь как к каждой записи подтянуть значение строки "ДатаОпер:" относящаяся к ошибке (пока мысли такие: от поля с ошибкой искать вверх "###" и от него "ДатаОпер:" ... и тогда вообще ШИК будет

Оффлайн madmasles [?]

  • Глобальный модератор
  • *
  • Сообщений: 7790
  • Репутация: 2314
  • Пол: Мужской
  • Награды За модерирование форума
    • Награды
  • Версия AutoIt: 3.3.x.x
Tyr  [?]
Цитировать
Сейчас разберусь как к каждой записи подтянуть значение строки "ДатаОпер:" относящаяся к ошибке
Код: AutoIt [Выделить]
#include <Encoding.au3>
#include <Array.au3>

Local $s_File = @ScriptDir & '\BV201_ZNO3434343.txt'

Local $a_Search[15] = [14, 'ДатаОпер:', 'ВидДок:', 'НомДок:', 'ДатаДок:', 'НомКорСч:', 'НаимБП:', 'БИКБП:', 'НаимПП:', 'ИННПП:', 'КПППП:', 'НомСчПП:', _
        'Дебет:', 'Кредит:', 'НазнПл:'], $v_Tmp, $a_Str, $a_Ret[1], $a_Tmp[$a_Search[0] + 1], $i_Len

Local $i_Timer = TimerInit()
$i_Len = StringLen($a_Search[1])
$v_Tmp = StringStripCR(_Encoding_OEM2ANSI(FileRead($s_File)))
For $i = 1 To $a_Search[0]
    If StringInStr($v_Tmp, $a_Search[$i] & @LF, 1) Then
;~  If StringRegExp($v_Tmp, '(?m)^' & $a_Search[$i] & '$') Then
        $a_Tmp[0] += 1
        $a_Tmp[$a_Tmp[0]] = $i
    EndIf
Next
If Not $a_Tmp[0] Then Exit MsgBox(64, '', 'All OK!')
$a_Str = StringSplit($v_Tmp, @LF)
$v_Tmp = 0
ReDim $a_Ret[$a_Str[0] + 1][$a_Tmp[0]]
For $i = 1 To $a_Str[0]
    For $j = 0 To $a_Tmp[0] - 1
        If $a_Str[$i] == $a_Search[$a_Tmp[$j + 1]] Then
            $a_Ret[0][$j] += 1
;~          $a_Ret[$a_Ret[0][$j]][$j] = $i
;~          $a_Ret[$a_Ret[0][$j]][$j] = $i & ' (' & $a_Str[$i - $a_Tmp[$j + 1] + 1] & ')'
            $a_Ret[$a_Ret[0][$j]][$j] = $i & ' (' & StringTrimLeft($a_Str[$i - $a_Tmp[$j + 1] + 1], $i_Len) & ')'
;~          ConsoleWrite($a_Str[$i - $a_Tmp[$j + 1] + 1] & @LF)
        EndIf
    Next
Next
For $i = 0 To $a_Tmp[0] - 1
    If $v_Tmp < $a_Ret[0][$i] Then $v_Tmp = $a_Ret[0][$i]
    $a_Ret[0][$i] = $a_Search[$a_Tmp[$i + 1]] & ' (' & $a_Ret[0][$i] & ')'
Next
ReDim $a_Ret[$v_Tmp + 1][$a_Tmp[0]]
ConsoleWrite(TimerDiff($i_Timer) & @LF)
_ArrayDisplay($a_Ret)

Какой максимальный размер файлов?
« Последнее редактирование: Сентябрь 10, 2013, 12:52:54 от madmasles »

Оффлайн madmasles [?]

  • Глобальный модератор
  • *
  • Сообщений: 7790
  • Репутация: 2314
  • Пол: Мужской
  • Награды За модерирование форума
    • Награды
  • Версия AutoIt: 3.3.x.x
Tyr  [?]
Цитировать
30 000 строк
Дайте реальный, лучше самый большой, файл.

Оффлайн Tyr [?]

  • Новичок
  • *
  • Сообщений: 29

  • Автор темы
  • Репутация: 3
  • Пол: Мужской
    • Награды
madmasles
Цитировать
Дайте реальный, лучше самый большой, файл.
Вот несколько файлов(самых больших - 21170 строк). Обычно обрабатывается сразу штуки 4-7... можно конечно выводить это всё в Listbox используя библиотеки массивов, но удобнее наверное было бы в файл (хотя это как я понимаю усложнит процедуру?)

Русское сообщество AutoIt

Re: Не работает внешний цикл при наличие внутреннего
« Ответ #7 Отправлен: Сентябрь 10, 2013, 15:45:57 »

Оффлайн madmasles [?]

  • Глобальный модератор
  • *
  • Сообщений: 7790
  • Репутация: 2314
  • Пол: Мужской
  • Награды За модерирование форума
    • Награды
  • Версия AutoIt: 3.3.x.x
Tyr,
Предлагаю Вам переместить тему в Стол заказов, Вы ее переоформите в соответствии с Правилами обязательного оформления тем в разделе "Стол заказов", и я там я доделаю вывод в лог в нужном формате.

Оффлайн Z_Lenar [?]

  • Продвинутый
  • ***
  • Сообщений: 209
  • Репутация: 52
  • Пол: Мужской
    • Награды
  • Версия AutoIt: 3.3.12.0
Tyr
Так подойдет:
Код: AutoIt [Выделить]
#include <Encoding.au3>
#include <Array.au3>
#Include <File.au3> ;подключаем необходимые библиотеки

$dirIz = "d:\56756" ;задаем рабочую папку как переменну.

; цикл проверки наличия файлов и получения их имен для цикла проверки самих файлов.
If FileExists($dirIz & '\BV*ZNO1*') Then ;проверяем наличие файла отвечающего маске
$aA = _FileListToArray($dirIz, 'BV*ZNO1*', 1);записываем имена файлов в массив
for $ii = 1 to $aA[0];запускаем цикл по длине массива
  ;  MsgBox(4096,"", $aA[$ii])
 _ProvercaStroc($aA[$ii]) ;Запускае основую процедуру которая внизу кода передавая параметры . элемент массива(имя файла) считывается в переменную
next
Else
    MsgBox(4096,"","Нет файлов для обработки.")
EndIf

Func _ProvercaStroc($file_name)
    TrayTip("Обработка файла:", $file_name, 5)
    Local $lines[1], $results[1], $what[6] = ['НаимБП:~', 'БИКБП:~', 'НаимПП:~', 'ИННПП:~', 'НомСчПП:~', 'НазнПл:~']

    ; 1. Т.к. перевод строки в обрабатываемых файлах состоит из двух символов (@CR & @LF)
    ;    иначе - @CRLF (сначала идет байт @CR потом @LF)
    ; 2. в обрабатываемых файлах отсутсвует '~'
    ;    сначала заменяем последовательность символов ':' & @CR на ':~' & @CR
    ;    в результате получаем пустые строки с окончанием '~'
    ; 3. StringStripCR - убираем байт @CR
    ; 4. StringSplit - создаем массив из предыдущего результата взяв разделителем оставшийся @LF
    $lines = StringSplit(StringStripCR(StringReplace(_Encoding_OEM2ANSI(FileRead($dirIz & "\"  & $file_name)), ':' & @CR, ':~' & @CR)), @LF)
    Local $log_name = $dirIz & "\" & StringTrimRight($file_name,4)  & ".log"
    FileDelete($log_name)

    ; $results = индексы всех вхождений ':~' в массиве строк обрабатываемого файла
    $results = _ArrayFindAll($lines, ':~', 0, 0, 0, 1)

    ; Пересматриваем все строки без значений
    For $i = 0 To UBound($results) - 1

        ; $what = массив пустых строк имеющих повод попасть в лог
        ; сравниваем следующую "пустую" строку с этим массивом
        Local $line = _ArraySearch($what, $lines[$results[$i]])
        If $line <> -1 Then

            ; Ok - поднимаемся наверх по строкам до появления начала блока
            $line = $results[$i]
            While 1
                $line = $line - 1
                If $lines[$line] = '###' Then ExitLoop
            WEnd

            ; Пишем начало блока в лог
            FileWrite($log_name, $line & @TAB)

            ; Поле с отсутсвующим значением
            FileWrite($log_name, StringTrimRight($lines[$results[$i]], 2) & @TAB)

            ; Записываем значащие поля начиная поиск с начала блока
            FileWrite($log_name, $lines[_ArraySearch($lines, 'ДатаОпер', $line, 0, 1, 1)] & @TAB)
            FileWrite($log_name, $lines[_ArraySearch($lines, 'НомДок', $line, 0, 1, 1)] & @TAB)
            FileWrite($log_name, $lines[_ArraySearch($lines, 'Дебет', $line, 0, 1, 1)] & @TAB)
            FileWrite($log_name, $lines[_ArraySearch($lines, 'Кредит', $line, 0, 1, 1)] & @CRLF)
        EndIf
    Next
EndFunc   ;==>_ProvercaStroc
 

« Последнее редактирование: Сентябрь 11, 2013, 21:20:15 от Z_Lenar »

Оффлайн Tyr [?]

  • Новичок
  • *
  • Сообщений: 29

  • Автор темы
  • Репутация: 3
  • Пол: Мужской
    • Награды
Z_Lenar Всё Ок :ok:. То, что надо Результат 1 в 1, как представлял. И даже вывод в трей и то что файлы лога затираются, а не просто до записываются.
« Последнее редактирование: Сентябрь 12, 2013, 09:20:00 от Tyr »

Оффлайн madmasles [?]

  • Глобальный модератор
  • *
  • Сообщений: 7790
  • Репутация: 2314
  • Пол: Мужской
  • Награды За модерирование форума
    • Награды
  • Версия AutoIt: 3.3.x.x
Мой вариант, ИМХО, должен быть самый быстрый.
(нажмите для показа/скрытия)
В прикрепленном архиве ини-файл Check_vrb.ini (должен лежать в одной папке со скриптом), в нем есть некоторые пояснения.

Оффлайн Z_Lenar [?]

  • Продвинутый
  • ***
  • Сообщений: 209
  • Репутация: 52
  • Пол: Мужской
    • Награды
  • Версия AutoIt: 3.3.12.0
madmasles
Забавно... Я не понял откуда "такой" выйгрыш в скорости?  :blink:
Если бы писал на С++ добавил бы простенькую проверку по crc в цикле перебора строк. Но здесь посимвольная обработка не катит :(

Русское сообщество AutoIt


 

Похожие темы

  Тема / Автор Ответов Последний ответ
1 Ответов
2656 Просмотров
Последний ответ Февраль 24, 2010, 22:32:25
от snoitaleR
15 Ответов
9970 Просмотров
Последний ответ Ноябрь 22, 2010, 12:59:47
от Redline
6 Ответов
2139 Просмотров
Последний ответ Февраль 11, 2013, 17:59:09
от AZJIO
24 Ответов
3079 Просмотров
Последний ответ Октябрь 09, 2015, 13:51:01
от ВиталийВВ
7 Ответов
1476 Просмотров
Последний ответ Март 03, 2016, 17:08:24
от mef-t
8 Ответов
929 Просмотров
Последний ответ Август 27, 2016, 09:59:32
от necrobit
11 Ответов
1199 Просмотров
Последний ответ Сентябрь 02, 2016, 16:49:43
от ra4o
5 Ответов
322 Просмотров
Последний ответ Октябрь 18, 2017, 09:43:11
от Rouzenrot
3 Ответов
124 Просмотров
Последний ответ Ноябрь 12, 2017, 21:18:52
от Garrett
2 Ответов
199 Просмотров
Последний ответ Ноябрь 22, 2017, 17:08:31
от hilongpao