PDA

Показать полную графическую версию : [архив - Часть 2] AutoIt скрипты


Страниц : 1 2 3 4 [5] 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50

Creat0R
22-06-2007, 02:41
Альтернатива подобной функции:


Func _FileReadToArray($sFilePath)
;==============================================
; Local Constant/Variable Declaration Section
;==============================================
Local $hFile = FileOpen($sFilePath, 0)
Local $RetArr[1], $Line, $i=1

If $hFile = -1 Then Return SetError(1)

While 1
$Line = FileReadLine($hFile, $i)
If @error = -1 Then ExitLoop
If $Line <> "" Then
ReDim $RetArr[UBound($RetArr)+1]
$RetArr[UBound($RetArr)-1] = $Line
EndIf
$i += 1
WEnd
$RetArr[0] = UBound($RetArr)-1

FileClose($hFile)
Return $RetArr
EndFunc


Возможно немного(?) медленней, но зато в массив не попадают пустые строки :tongue:

Diamond
22-06-2007, 02:55
Creat0R
Они туда попадают, потому что ты их с самого начала записываешь в текстовой файл. :)
Пожалуй возьму эту функцию на вооружение... Но всё таки, мне кажется что я сделал всё правильно...

Creat0R
22-06-2007, 02:56
Diamond
Я посмотрел содержимое файла в редакторе "Bred" и... оказалось что полученный массив полностью соответствует текстовому файлу... 6 строк, первая и последняя пустые.
Это я вижу и в Notepad(2 ;)), но мне кажется в массив не должны попадать пустые строки, и я считал что пустая строка, это и есть сочетание символов @LF и @CR, и что функция StringSplit() должна поделить на элементы которе не будут содержать тот символ на который делим (используя к примеру, в качестве третьего параметра, 1 - использовать все символы разделителя как метку деления, т.е не вносить сами символы в полученные элементы).

amel27
22-06-2007, 06:50
Creat0R, DiamondТеперь у меня началось - надеюсь это не заразнонет, этого нельзя так оставлять :aggressiv ...для начала нужно ответить на вопросы:

- считать ли пустой строкой промежуток между началом файла и разделителем (@LF/@CR);
- считать ли пустой строкой промежуток между и спецсимволом и концом файла;
- как разбивать на пустые строки произвольную последовательность разделителей.

Обычно за разделитель считают именно @LF, а все вхождения @CR просто удаляют, соответственно последовательность @LF@LF будет означать "разделитель-пустая строка", при этом ответ на первые два вопроса чаще положительный... Можно договориться считать за разделители @CR и @LF, тогда последовательность @CRLF опять же вернет пустую строку (между ними). Мне представляется наиболее удобным следующий вариант:

- ДА
- НЕТ
- разделители: пары @CRLF/@LFCR и в последнюю очередь одиночные @CR и @LF

реализация через RegExp:$array = StringRegExp(FileRead ("Test.txt"),'(?s)(.*?)(?:\n\r|\r\n|[\n\r])', 3)P.S. Ктати, в RegExp метасимволы '^' и '$' по умолчанию различают только позиции в начале и конце файла (т.е. всей строки), а с модификатором '(?m)' указывают на позиции после- и перед- @LF соответственно...

Creat0R
22-06-2007, 08:05
amel27
реализация через RegExp:
Хм... попробуй подобный пример:


#include <Array.au3>

$TestFileHandle = FileOpen("Test.txt", 2)

FileWrite($TestFileHandle, @CR & "Line1" & @LF & @CR & @LF & @CR & @LF & @CR & "Line2" & @CR & "Line3" & @LF & "Line4" & @CRLF)

FileClose($TestFileHandle)

Dim $Array
_FileReadToArray("Test.txt", $Array)

_ArrayDisplay($Array)

Func _FileReadToArray($sFilePath, ByRef $RetArr)
Local $hFile = FileOpen($sFilePath, 0)
If $hFile = -1 Then Return SetError(1)

$RetArr = StringRegExp(FileRead($hFile), '(?s)(.*?)(?:\n\r|\r\n|[\n\r])', 3)
$RetArr[0] = UBound($RetArr)-1

FileClose($hFile)
Return $RetArr
EndFunc


В массив попадают несколько пустных строк...

Кстати, я проверил скорость выполнения функции - С использованием RegExp, в 5-6 раз быстрее чем используя цикл, но зато при использовании цикла возвращаются только текстовые строки :tongue:

amel27
22-06-2007, 12:54
Creat0R
В массив попадают несколько пустных строк
Все правильно, так и запрограммировано - (@LFCR & @LFCR & @LFCR) это разделитель из двух пустых строк... проблема не в том, что остаются пустые строки (почему бы им не быть?), а в том что этими строками считать... Проигнорировать пустые строки как раз проще:$RetArr = StringRegExp(FileRead($hFile),'(?s)(.*?)[\n\r]+', 3)ADD: или так:$RetArr = StringRegExp(FileRead($hFile),'([^\n\r]+)', 3)
З.Ы. StringRegExp() возвращает массив без счетчика.. т.е. первый элемент занят!

Diamond
23-06-2007, 00:43
amel27
Обычно за разделитель считают именно @LF, а все вхождения @CR просто удаляют
Т.е. получается... что функция _FileReadToArray() написана правильно?- ДА
- НЕТ
- разделители: пары @CRLF/@LFCR и в последнюю очередь одиночные @CR и @LF
Я думал что символы @LFCR не могут сосуществовать вместе, т.е. должна получаться пустая строка...
...Если общего правила не существует - то этот вариант, как мне кажется, наиболее подходит.
-Да

Creat0R
23-06-2007, 01:18
amel27
или так:
Вот так лучше, таким образом даже первые пустые строки игнорируются.

StringRegExp() возвращает массив без счетчика.. т.е. первый элемент занят!
Хм... а вот это уже немного досадно... а самой функцией StringRegExp нельзя подвинуть все полученные элементы? пусть даже первый элемент будет содержать пустую строку, его то потом просто можно заменить ($RetArr[0] = Ubound($RetArr)-1).

amel27
23-06-2007, 05:11
DiamondЕсли общего правила не существует в отличие от никсов текстовый файл, сформировнный в Windows не должен содержать одиночных @LF или @CR, только в паре @CRLF - для таких файлов _FileReadToArray() работает правильно

Creat0Rнельзя подвинуть все полученные элементы?а оно того стоит?... зачем городить огород, для совместимости?.. не вижу смысла оформлять UDF ради одной строчки кода

Creat0R
23-06-2007, 07:42
amel27
а оно того стоит?.
Если нет необходимости перебирать массив, то да.

не вижу смысла оформлять UDF ради одной строчки кода
Иногда в скрипте нужно по несколько раз вызывать _FileReadToArray(), не писать же каждый раз одну и туже строку содержащюю две-три комманды :shuffle:

amel27
23-06-2007, 09:47
Creat0RЕсли нет необходимости перебирать массив, то даты думаешь я владею тайным знанием?... :) сам подумай - если бы даже была такая команда, она бы все равно (втайне от нас) делала вставку с передвижкой всего "хвоста" в памяти на одну позицию.

З.Ы. К слову, я уже давно отказался от _FileReadToArray() и некоторых других штатных UDF, так как RegExp-команды более мощные и гибкие... К примеру, при чтении файла кроме обычного деления на строки можно по ходу делать много других полезных вещей - убирать ведущие и оконечные пробелы, проверять строки на условия, etc.

amel27
23-06-2007, 13:33
Creat0R
однако... лучший способ разубедить себя - попытаться убедить другого... =)Func _FileReadToArray($sFilePath, ByRef $RetArr)
Local $str = @LF & FileRead($sFilePath)
If @error Then Return SetError(1)
$RetArr = StringRegExp($str,'(^\n|[^\n\r]+)',3)
$RetArr[0] = UBound($RetArr)-1
Return $RetArr
EndFuncЗ.Ы. вот только работать этот способ будет чуть медленней

Creat0R
23-06-2007, 23:33
amel27
сам подумай - если бы даже была такая команда, она бы все равно (втайне от нас) делала вставку с передвижкой всего "хвоста" в памяти на одну позицию.
Я не это имел ввиду, я думал что может StringRegExp “умеет” как бы добавлять пустую строку в начало массива....

вот только работать этот способ будет чуть медленней
Идеально, по крайней мере не медленней моего примера с циклом ;)

Спасибо, с этой функциецй (о котороый уже около 3-ёх страниц пишем), можно успокоиться :)

proxy
24-06-2007, 01:01
Добрые ночи.

В моей программе много gui элиментов, которые в ходе работы с программой будут очень часто вызываться, обробатываться и т.д.
Эти элементы состоят из целых групп, т.е. парочка текстовых полей и несколько кнопок, список и несколько кнопок и т.д.

Как лучше организовать, со стороны наилучшей работоспособности программы, вариант:

1) насоздовать все gui элименты и не нужным дать статус $GUI_HIDE и показывать их только при необходимости?

2) все gui элименты создовать при необходимости и удалять по завершении работы с ними?

Creat0R
24-06-2007, 01:29
proxy
Как лучше организовать, со стороны наилучшей работоспособности программы
Мой личный совет - 1)

Поясню...

* Я не раз приходил к выводу, что создавая элементы "на лету", ими потом очень тяжело управлять (хотя не всегда), особенно если используется больше чем один Гуи.
* Когда мы создаём сразу все необходимые элементы (под нужными GUI), мы потом можем легко присваивать им нужные атрибуты/свойства/статусы, удалять их, или менть их значения.

Исходя из этого, я бы создавал всё сразу, но главное, обьявлять глобально все переменные элементов, и постараться “не забыть” из имена ;)

Вывод:
Если есть терпение, желание, стремление, то лучше сразу привыкнуть, хоть и не к лёгкому, но зато верному методу, чтобы потом можно было клипать ГУИ с увереностью в том, что будет наименьшее количество припятсвии и ошибок (а они всегда будут).
Однако, в некоторых случая бывает как раз наоборот, когда более удобнее создавать “на лету”, но это уже на расмотрение автора, нужно учитывать такие факторы как количество окон Гуи которые планируется создавать, насколько часто будут обращения к создаваемым элементам, и другие подобные факторы... возможно иногда, лучшим методом окажется помещение в отдельную функцию всей процедуры создания элементов, чтобы без затруднении можно было пересоздать (с удалением внутри функции к примеру) необходимые элементы.

Diamond
24-06-2007, 03:54
amel27
лучший способ разубедить себя - попытаться убедить другого...Хорошо сказано, обычно так и случается...
По поводу _FileReadToArray, большое спасибо! Уже не один раз убеждался что 'RegExp' мощный инструмент, особенно в опытных руках. Жалко только что в справке AutoIt, об этом слишком сжато написано...

amel27
24-06-2007, 08:43
DiamondЖалко только что в справке AutoIt, об этом слишком сжато написанолучшее из переведенного: http://shop.piter.com/lib/978531800056/regvir.phtml

Diamond
24-06-2007, 09:21
Кто ни будь знает, как использовать команду PluginOpen() и где взять сами плагины?

amel27
лучшее из переведенного:Я и не подозревал что есть такая книга, да ещё и на русском... Спасибо!

Creat0R
А твоя версия функции _FileReadToArray() та которая с циклом, тоже пригодилась. Я её изменил немного, чтобы она считывала файл один к одному, включая пустые строки.
Вот только переменную $i можно было бы совсем убрать, имхо лишняя... Как считаешь?
Получается, что если была использована FileOpen() - то при каждом новом вызове команды: FileReadLine(), автоматически генерируется новый номер строки. Выходит что для FileReadLine() номер то, можно и не указывать...?

proxy
24-06-2007, 13:49
Creat0R, спасибо.

в моей программе только одно окно GUI и в нем меняется куча элементов,
так что я сразу создал все и не нужное скрыл. И вот после этого задумался
не станет ли это "грузит" мою программу.

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

Creat0R
24-06-2007, 21:21
Diamond
Получается, что если была использована FileOpen() - то при каждом новом вызове команды: FileReadLine(), автоматически генерируется новый номер строки. Выходит что для FileReadLine() номер то, можно и не указывать...?
Так и есть, из справки:

If no line number to read is given, the "next" line will be read. ("Next" for a newly opened file is initially the first line.)
Но по непонятной мне причине, первая попытка это сделать, выдала только одну строку, хотя файл содержал немного больше строк, возможно была ошибка чтнения?

proxy
не станет ли это "грузит" мою программу.
Естественно сам процесс создания элементов, использует память, но сильно нагружать не будет, как только создаются элементы, они как бы висят в памяти.
Это кстати, ещё одна причина по которой стоит сразу создавать нужные элементы, т.к создавая и удаляя их в процессе выполнения разных задач программы, память будет пополняться, при удалении элементов она обычно не высвобождается самостоятельно, кстати для этого есть функция на оф. форуме (_ReduceMemory()).




© OSzone.net 2001-2012