Войти

Показать полную графическую версию : Как в файле изменить определённые строки?


NewOLDi
28-01-2010, 13:01
Есть файл с большим количеством строк. Нужно найти определённые строки (вхождения фраз) и, при их обнаружении, добавить к началу каждой из них, скажем, символ комментария - ;.

Я знаю как это сделать путём полной перезаписи существующего файла (т.е. загнать инфу из файла в память и все замены провести там, после чего перезаписать существующий файл), но это, имхо, не совсем правильно и память жрёт :)

madmasles
28-01-2010, 13:11
NewOLDi,

_FileWriteToLine() посмотрите в библиотечных функциях, которые я ооочень люблю...

kaster
28-01-2010, 13:22
$sFile = @ScriptDir & '\test.txt'; путь до текстового файла, который подлежит обработке - должен существовать
$tmpFile = @ScriptDir & '\test_new.txt'; путь до нового файла, который получится после обработки - если не существует создаться автоматически

$hRead = FileOpen($sFile, 0); открываем первый файл для чтения
$hWrite = FileOpen($tmpFile, 2); открываем/создаем второй файл для записи/перезаписи

$template = 'string must exist in file'; фраза которая должна существовать в строке для начала обработки
$sAdd = ';'; символы которые добавятся перед найденной строкой
While 1
$sLine = FileReadLine($hRead); считывание строк первого файла одна за другой
If @error Then ExitLoop; если конец файла выходим из скрипта
If StringInStr($line, $template) Then; условие нахождения нужной строки
FileWriteLine($hWrite, $sAdd & $sLine); добавление символов для найденной строки
Else; условие когда строка не искомая
FileWriteLine($hWrite, $sLine); просто перезаписываем эту строку как есть
EndIf; конец условия
WEnd; конец цикла

FileClose($hRead)
FileClose($hWrite); закрываем файлы для соблюдения правил приличия и хороших манер

madmasles
28-01-2010, 13:42
kaster и NewOLDi,

У меня через массив вот так работает:
#include <file.au3>

$aRecords = ""
_FileReadToArray("my.txt", $aRecords)

For $i = 1 To $aRecords[0]
If StringInStr($aRecords[$i], "То что ищем") > 0 Then
_FileWriteToLine("my.txt", $i, StringReplace($aRecords[$i], $aRecords[$i], ";" & _
$aRecords[$i]), 1)
EndIf
Next

NewOLDi
28-01-2010, 13:55
kaster, у Вас используются два файла, а нужно всё проворачивать в одном, т.е. и читать и записывать (при необходимости) одновременно.

madmasles, массив-память - одно и тоже (в условиях я указал на это), а нужно напрямую, без загона инфы в память. Представьте, что файл размером в 1 Гб :) И это, любить библиотечные функции - не означает все их знать и уметь пользоваться, любовь здесь с точки зрения разумности использования того, что уже давно придумано и просчитано (типа - зачем изобретать велосипед).

Creat0R
28-01-2010, 14:03
это, имхо, не совсем правильно »
Как раз это самый правильный вариант, а память заполняется временно, если переменная массива локальная, то после выхода из функций память высвобождается, а если глобальная, то после использования массива его можно "онулировать":

$aArray = 0

NewOLDi
28-01-2010, 14:30
Нууу.... нет так нет, бум использовать память и полностью перезаписывать имеющийся файл :)

Creat0R
28-01-2010, 14:43
Представьте, что файл размером в 1 Гб »
Но без построчного чтения с начала всё ровно не обойтись:


$sFile = @DesktopDir (http://www.autoitscript.com/autoit3/docs/macros.htm#@DesktopDir) & "\File.txt"
$sInStr = "Some Data"

$hFile = FileOpen (http://www.autoitscript.com/autoit3/docs/functions/FileOpen.htm)($sFile, 0)

While (http://www.autoitscript.com/autoit3/docs/keywords.htm#While) 1
$sLine = FileReadLine (http://www.autoitscript.com/autoit3/docs/functions/FileReadLine.htm)($hFile)
If (http://www.autoitscript.com/autoit3/docs/keywords.htm#If) @error (http://www.autoitscript.com/autoit3/docs/macros.htm#@error) <> 0 Then (http://www.autoitscript.com/autoit3/docs/keywords.htm#Then) ExitLoop (http://www.autoitscript.com/autoit3/docs/keywords.htm#ExitLoop)

If (http://www.autoitscript.com/autoit3/docs/keywords.htm#If) StringRegExp (http://www.autoitscript.com/autoit3/docs/functions/StringRegExp.htm)($sLine, "(?i)^[^;].*" & $sInStr & ".*$") Then (http://www.autoitscript.com/autoit3/docs/keywords.htm#Then)
$iPos = FileGetPos($hFile) - StringLen (http://www.autoitscript.com/autoit3/docs/functions/StringLen.htm)($sLine) - StringLen (http://www.autoitscript.com/autoit3/docs/functions/StringLen.htm)(@CRLF (http://www.autoitscript.com/autoit3/docs/macros.htm#@CRLF))
FileClose (http://www.autoitscript.com/autoit3/docs/functions/FileClose.htm)($hFile)

$hFile = FileOpen (http://www.autoitscript.com/autoit3/docs/functions/FileOpen.htm)($sFile, 1)
FileSetPos($hFile, $iPos, 0) ;$FILE_BEGIN
FileWrite (http://www.autoitscript.com/autoit3/docs/functions/FileWrite.htm)($hFile, ";" & $sLine)
ExitLoop (http://www.autoitscript.com/autoit3/docs/keywords.htm#ExitLoop)
EndIf (http://www.autoitscript.com/autoit3/docs/keywords.htm#EndIf)
WEnd (http://www.autoitscript.com/autoit3/docs/keywords.htm#WEnd)

FileClose (http://www.autoitscript.com/autoit3/docs/functions/FileClose.htm)($hFile)

NewOLDi
28-01-2010, 14:49
Creat0R, нууу - строка не файл, как никак :) Благодарю, вроде как работает.

madmasles
28-01-2010, 16:02
Интересно, сколько таких способов и какой из них наиболее оптимальный и почему.

NewOLDi
28-01-2010, 17:50
madmasles
Самый быстрый и лёгкий - загнать всю инфу в память и там с ней работать. Но этот вариант не всегда подходит, если речь идёт о слишком больших объёмах данных.

Медленный и муторный, но эффективный с точки зрения объёма занимаемой памяти - работа с файлом напрямую.

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

Так что, исходить нужно из задач, стоящих перед Вами. Отсюда и будет выбираться оптимальный путь...

Ну как-то так :)

ЗЫ: А извращаться над каждым из вариантов можно сколь угодно много, хотя от перестановки мест слагаемых... ну разве что сокращать код и заниматься оптимизацией.

Creat0R
05-02-2010, 00:09
NewOLDi, Тема решена?




© OSzone.net 2001-2012