Wykonywanie operacji na każdej linii pliku tekstowego.

0

Dzień dobry.
W ramach nauki języka Delphi pragnę utworzyć program, który wczyta plik tekstowy, wykona na każdej jego linijce osobno określone działania (np. usunięcie części linijki funkcją Truncate) po czym nadpisze plik po wykonaniu tych modyfikacji. Wymyśliłem jak na razie to co poniżej.

var
Tekst : TextFile;  //plik z tekstem//
Linia : String; //zmienna do przechowywania linijki tekstu//
begin
  AssignFile(Tekst, Sciezka.Text);
  Reset(Tekst); //przypisuję plik do zmiennej i go otwieram//

  While not Eof(Tekst) do  //tworzę pętlę wykonującą się, dopóki nie skończą się linijki z tekstem//
  begin
    Readln(Tekst, Linia); //wczytuję linię tekstu do zmiennej Linia//
    //działania na linii w tym miejscu, nadpisanie tej linijki, jak to zrobić?//    
  end;

CloseFile(Tekst);  //zamykam plik//
end.

Proszę o pomoc w jaki sposób to wykonać, oraz co poprawić w powyższym kodzie.

2

nie da się tak - po odczytaniu i zmodyfikowaniu linii zapisz ją do nowego pliku. Alternatywą może być wczytanie całości do pamięci (np. przy użyciu TStringList), zmodyfikowaniu i zapisanie całości zmodyfikowanej z powrotem do tego samego pliku

0

Rozumiem, dziękuję za odpowiedź. Zmodyfikowałem kod. Czy jest dobrze?

var
Tekst : TextFile;  //plik z tekstem//
Tekst2 : TextFile; //zapisywany plik//
Linia : String; //zmienna do przechowywania linijki tekstu//
begin
  AssignFile(Tekst, Sciezka.Text);
  Reset(Tekst); //przypisuję plik do zmiennej i go otwieram//
  AssignFile(Tekst2, SciezkaZapisu.Text);
  Rewrite(Tekst2); //tworzę plik do zapisu//

  While not Eof(Tekst) do  //tworzę pętlę wykonującą się, dopóki nie skończą się linijki z tekstem//
  begin
    Readln(Tekst, Linia); //wczytuję linię tekstu do zmiennej Linia//
    //działania na wczytanej linii w tym miejscu, np. Truncate//
    Writeln(Tekst2, Linia);
  end;

CloseFile(Tekst);
CloseFile(Tekst2);//zamykam pliki//
end.

O ile się nie mylę, jeśli ścieżka zapisu będzie identyczna, to plik zostanie nadpisany.

1
abrakadaber napisał(a)

nie da się tak - po odczytaniu i zmodyfikowaniu linii zapisz ją do nowego pliku.

Nie do końca, ale mniej więcej jest to prawda;

To co wiem że możesz zrobić to zastosować klasę TFileStream - wczytać łańcuch do zmiennej, zmodyfikować go, po czym przesunąć kursor strumienia w dół o ilość znaków łańcucha i tam wpisać nowy łańcuch np. metodą WriteBuffer; Dzięki temu faktycznie nadpiszesz istniejące dane;

Niestety w praktyce nie jest to takie proste, a ponadto ma swoje ograniczenia; Z tego co wiem klasa ta nie ma metody umożliwiającej wczytanie linii znaków do napotkania sekwencji CRLF, więc nie wiadomo ile znaków ma aktualna linia (nie ma odpowiednika procedury Readln); Po drugie aby możliwe było prawidłowe nadpisanie danej linii w pliku, długości starej i nowej wersji linii muszą być takie same - jeśli wczytana linia ma 10 znaków, to po modyfikacji musi mieć także 10 znaków, aby nadpisanie było prawidłowe;

Mały przykład - mając plik o poniższej zawartości:

000
111
222
333

i wywołując poniższy kod:

const
  BUFF_SIZE = 3;
var
  fsInput: TFileStream;
  arrBuffer: TByteDynArray;
begin
  fsInput := TFileStream.Create('C:\foo.txt', fmOpenReadWrite or fmShareExclusive);
  try
    SetLength(arrBuffer, BUFF_SIZE);
    fsInput.ReadBuffer(arrBuffer[0], BUFF_SIZE);

    FillChar(arrBuffer[0], BUFF_SIZE, 65);
    fsInput.Seek(-BUFF_SIZE, soFromCurrent);
    fsInput.Write(arrBuffer[0], BUFF_SIZE);
  finally
    fsInput.Free();
  end;
end.

pierwsza linia pliku zostanie wypełniona znakami o kodzie 65, czyli A; Zawartość pliku po wykonaniu programu:

AAA
111
222
333

Jednak tak jak napisałem wcześniej - zbyt wąskie możliwości ma taki sposób, więc najlepszym rozwiązaniem będzie albo przepisywanie linia po linii do nowego pliku, albo wczytanie pliku do pamięci, przerobienie go i zapisanie z powrotem do tego samego pliku;


nieznany napisał(a)

Rozumiem, dziękuję za odpowiedź. Zmodyfikowałem kod. Czy jest dobrze?

Jest dobrze, ale wypadałoby dodać bloki Try Finally.

0

@nieznany
Kod jest jak najbardziej poprawny.

nieznany napisał(a):

O ile się nie mylę, jeśli ścieżka zapisu będzie identyczna, to plik zostanie nadpisany.

W tym przypadku ścieżka zapisu musi być inna niż ścieżka oryginału, ponieważ plik Sciezka.Text masz cały czas otwarty do odczytu i wtedy nie można dokonywać do niego zapisu.
Zresztą, w ramach nauki, nadaj jednakowe wartości Sciezka.Text i SciezkaZapisu.Text i zobacz jaki wygenerujesz błąd.

0

Dziękuję Wam za pomoc, program działa prawidłowo.:)

1 użytkowników online, w tym zalogowanych: 0, gości: 1