Usuwanie znaczników CR w Lazarusie

0

Witam

Od niedawna próbuję pisać drobne aplikacje w Lazarusie. Ostatnio napotkałem na problem znaczników końca linii. 
Otóż wczytuję plik generowany przez inną aplikację, który następnie przerabiam w swojej. Plik umieszcza znaczniki końca linii **LF**. W niektórych liniach jednak dodaje w środku linii znacznik **CR**. Wygląda to mniej więcej tak:
pierwsza linia <LF>
druga linia <LF>
trzecia <CR> linia <LF>
czwarta linia <LF>

W Delphi nie ma problemu, znaczniki CR są pomijane, natomiast Lazarus interpretuje je jako znaczniki końca wiersza.
Chciałbym się pozbyć znaczników CF w pliku. Na tą okoliczność wysmarowałem taką procedurkę (niestety nie działa):

procedure usun_cr(var plik:TextFile;nazwaPliku:string);
var
  cr:integer;
  ile:byte;
  linia,pom:string;
  tymcz:TStringList;
begin

tymcz:=TstringList.Create;

reset(plik);
cr:=0;
ile:=0;
pom:='';
linia:='';
while not eof(plik) do
  begin

   readln(plik,linia);
   cr:=Pos(#13, linia);
    if cr>0 then
     begin
       inc(ile);
         if ile>1 then
          linia:=pom+linia;
       pom:=linia;
     end//if cr>0
     else
      if ile>0 then
       begin
        linia:=pom+linia;
        ile:=0;
        cr:=0;
       end;//if ile>0

    if (cr=0)and(ile=0) then
    tymcz.Add(linia);
  end;//while not eof(plik)
  
CloseFile(plik);
tymcz.SaveToFile(nazwaPliku);
tymcz.Free;

end;//procedure usun_cr
Procedurę chciałbym używać wielokrotnie, gdyż dość często muszę przerabiać pliki generowane przez zewnętrzną aplikację. Nie jestem zawodowym programistą, zajmuję się raczej administrowaniem siecią, dlatego programowanie jest jedynie uzupełnieniem mojej pracy.
Z góry dzięki za wszelkie sugestie.
0

procedure usun_cr(var plik:TextFile;nazwaPliku:string);

I po co ci zmienna plik?

readln(plik,linia);
   cr:=Pos(#13, linia);

Tak, jakie to mądre, skoro Lazarus traktuje #13 jako nową linię to najpierw czytajmy linię a potem szukajmy znaku końca linii który jest usuwany w readln. Genialne!

Z góry dzięki za wszelkie sugestie.

Sugestia - zadaj pytanie.

Plik umieszcza znaczniki końca linii LF. W niektórych liniach jednak dodaje w środku linii znacznik CR.

Czy CR jest tam celowo jako przejście nowej linii, jako część danych czy jako CO. W normalnych plikach tekstowych CR występuje jako nowa linia w MAC OS. Dzisiaj się raczej stosuje CRLF albo LF, ale FPC jest zgodny także z CR bo niektóre systemy to stosują.

Podaj jeszcze o jaki OS chodzi bo to tutaj ma znaczenie.

0

Tak, jakie to mądre, skoro Lazarus traktuje #13 jako nową linię to najpierw czytajmy linię a potem szukajmy znaku końca linii który jest usuwany w readln. Genialne!

Przyznaję, że tu może tkwić błąd. Tak, jak pisałem wcześniej aplikacje piszę dorywczo i na własne potrzeby i dlatego być może źle zinterpretowałem to, co Lazarus robi podczas wczytywania linii. Byłem pewny, że nie dodaje znacznika CRLF, a jedynie wczytuje linię w niezmienionej postaci i przechodzi do odczytu nowej linii w pliku.

Czy CR jest tam celowo jako przejście nowej linii, jako część danych czy jako CO. W normalnych plikach tekstowych CR występuje jako nowa linia w MAC OS. Dzisiaj się raczej stosuje CRLF albo LF, ale FPC jest zgodny także z CR bo niektóre systemy to stosują.

Podaj jeszcze o jaki OS chodzi bo to tutaj ma znaczenie.

Tak jak pisałem, plik jest generowany przez zewnętrzną aplikację (opartą na JBOSS w Linuksie) i jest to niezależne ode mnie. Znacznik CR nie powinien się tam znajdować.

Sugestia - zadaj pytanie.

Otóż moje pytanie było w temacie posta - jak pozbyć się znacznika CR w generowanym przez zewnętrzną aplikację pliku.
Być może wystarczy ustawić coś w opcjach Lazarusa, ale niestety nie mogłem niczego sensownego znaleźć.

0

Być może wystarczy ustawić coś w opcjach Lazarusa, ale niestety nie mogłem niczego sensownego znaleźć.

Wątpię.

Otóż moje pytanie było w temacie posta - jak pozbyć się znacznika CR w generowanym przez zewnętrzną aplikację pliku.

Podczas wczytywania czy chcesz go przerobić i puścić dalej? Jeżeli przerobić to wczytuj go bajtowo i usuwaj bajty 13? Jak wczytywanie to zależy jak wczytujesz.
Taka odpowiedź wystarczy? Super.

Tak jak pisałem, plik jest generowany przez zewnętrzną aplikację (opartą na JBOSS w Linuksie) i jest to niezależne ode mnie. Znacznik CR nie powinien się tam znajdować.

Chodziło mi o OS na którym działasz.

Przyznaję, że tu może tkwić błąd. Tak, jak pisałem wcześniej aplikacje piszę dorywczo i na własne potrzeby i dlatego być może źle zinterpretowałem to, co Lazarus robi podczas wczytywania linii. Byłem pewny, że nie dodaje znacznika CRLF, a jedynie wczytuje linię w niezmienionej postaci i przechodzi do odczytu nowej linii w pliku.

No to już wiesz.

0

Jeżeli faktycznie (jakim cudem to nie wiem...) plik wygląda tak:

pierwsza linia <LF>
druga linia <LF>
trzecia <CR> linia <LF>
czwarta linia <LF>

to nie możesz wykorzystać gotowych rozwiązań jak TStrings/TStringList, bo one podczas ładowania zawartości pliku podzielą go na linie według własnego upodobania; Musisz sam wczytywać linie i określić kiedy będzie jej koniec, a kiedy nie;

Tak jak napisał Ci @-123oho - skorzystaj z plików amorficznych; Wczytuj po kolei znaki aż do napotkania znacznika LF; Po jego napotkaniu przeskanuj bufor czy nie zawiera CR i jeśli jest w niepożądanym miejscu to usuń go i podaj gotową linie dalej; No i tak do końca pliku;

W ten sposób nie ma opcji, że linie zostaną błędnie podzielone; Tylko nie pytaj w jaki sposób obsługuje się pliki amorficzne - poczytaj sam;

1
const
  cr=#13;
  lf=#10;
  crlf=#13#10;
var
  s:string;
  f:file of Char;
  sof:Integer;
//...
//1. Wczytujemy cały plik do zmiennej typu string.
  AssignFile(f,'NazwaPliku');
  Reset(f);
  sof:=FileSize(f);
  SetLength(s,sof);
  BlockRead(f,s[1],sof);
  CloseFile(f);

//2. Wywalamy wszystkie CR z wczytanego stringa
  s:=StringReplace(s,cr,'',[rfReplaceAll]);

//3. Zamieniamy pojedyncze LF na CRLF (standard Windows)
  s:=StringReplace(s,lf,crlf,[rfReplaceAll]);

//4. Teraz możemy to załadować do jakiegoś Memo albo do StringList albo zapisać do pliku
  Memo1.Text:=s;
0
pelsta napisał(a):
const
  cr=#13;
  lf=#10;
  crlf=#13#10;
var
  s:string;
  f:file of Char;
  sof:Integer;
//...
//1. Wczytujemy cały plik do zmiennej typu string.
  AssignFile(f,'NazwaPliku');
  Reset(f);
  sof:=FileSize(f);
  SetLength(s,sof);
  BlockRead(f,s[1],sof);
  CloseFile(f);

//2. Wywalamy wszystkie CR z wczytanego stringa
  s:=StringReplace(s,cr,'',[rfReplaceAll]);

//3. Zamieniamy pojedyncze LF na CRLF (standard Windows)
  s:=StringReplace(s,lf,crlf,[rfReplaceAll]);

//4. Teraz możemy to załadować do jakiegoś Memo albo do StringList albo zapisać do pliku
  Memo1.Text:=s;

Dzięki bardzo, chyba właśnie o to mi chodziło. Jutro w pracy przetestuję to rozwiązanie. Jeżeli zadziała, to pozwoli mi to stosować jako uniwersalną procedurę przy pracy nad obróbką raportów generowanych z zewnętrznej aplikacji.
Wcześniej napisałem programik do obróbki tych raportów w Turbo Delphi i tam problem nie występował - znaczniki CR były ignorowane. Ale ostatnio postanowiłem przesiąść się na Lazarusa i stąd ten temat.
Pozdrawiam
dareck

0

Przykro mi, że @pelsta za swoje otwarte podejście i bezinteresowną pomoc naraził się na takie ataki ze strony niektórych forumowiczów (a właściwie jednego). Nie było moim celem wywoływać żadnej burzy na forum.
Tak jak napisał @pelsta, procedura, którą mi podsunął jest jedynie małą cząstką programu, która rozwiązuje problem występowania niepożądanych znaczników. Uzyskany wynik jest w dalszej części programu obrabiany i tam nie potrzebuję żadnych podpowiedzi. Nie prosiłem również o gotowe rozwiązanie, a jedynie podpowiedź. Również otrzymawszy podpowiedź od @pelsty, nie ograniczyłem się do metody - kopiuj i wklej, a przerobiłem ja na własne potrzeby. O plikach amorficznych kiedyś czytałem, ale nie miałem potrzeby z tych rozwiązań korzystać i dlatego musiałem sobie tą wiedzę odświeżyć.
Jeszcze raz dziękuję @pelscie za udzielona pomoc i mam nadzieję, że w stosunku do innych będzie miał równie życzliwe podejście, jak do mnie.
Na pewno podziękowałbym w inny sposób, jeżeli miałbym taką możliwość. Niestety nie jestem zarejestrowany, gdyż jak wcześniej pisałem, programowanie jest jedynie uzupełnieniem mojej pracy.

0

Przykro mi, że @pelsta za swoje otwarte podejście i bezinteresowną pomoc naraził się na takie ataki ze strony niektórych forumowiczów (a właściwie jednego).

To, że jedna osoba tak odpowiedziała nie znaczy że inni to wspierają. Tutaj każdy się komuś naraża (tzn. większość jednej osobie i jedna osoba większości).

Nie było moim celem wywoływać żadnej burzy na forum.

Jeszcze ci daleko.

Tak jak napisał @pelsta, procedura, którą mi podsunął jest jedynie małą cząstką programu, która rozwiązuje problem występowania niepożądanych znaczników. Uzyskany wynik jest w dalszej części programu obrabiany i tam nie potrzebuję żadnych podpowiedzi.

No dobrze, tylko czy to zmienia fakt że mogłeś/powinieneś napisać to sam?

Nie prosiłem również o gotowe rozwiązanie, a jedynie podpowiedź. Również otrzymawszy podpowiedź od @pelsty, nie ograniczyłem się do metody - kopiuj i wklej, a przerobiłem ja na własne potrzeby.

Bardzo się cieszymy że mamy do czynienia z osobą która jednak pracuje i jej celem nie jest metoda kopiuj&wklej, nie mniej jednak nie wszyscy tacy są.

Jeszcze raz dziękuję @pelscie za udzielona pomoc i mam nadzieję, że w stosunku do innych będzie miał równie życzliwe podejście, jak do mnie.

Mam zgoła odmienne zdanie. Większość osób nie zasługuje na gotowca.

Nie przejmuj się, po prostu ktoś niedawno zapoczątkował ruch przeciw dawaniu gotowców - rozwiązywaniu problemów za autorów wątków bez ich widocznego wkładu; Trzeba btć samodzielnym i kombinować we własnym zakresie zanim zacznie się zadawać pytania, dlatego podchodzę negatywnie do podsuwania gotowych kodów

O to właśnie chodzi.

i; Ważne, że problem został rozwiązany, ale nie można zapominać, że to nie jest nasz problem, więc pomagający nie mogą być jedynymi zainteresowanymi - przede wszystkim autor powinien dążyć do rozwiązania danego problemu;

Sam lepiej bym tego nie ujął.

Ja uważam, że skoro autor pokazał niedziałający kod który był jego, ale jego błędem było złe podejście to najlepiej wytłumaczyć czemu jest źle i jak jest dobrze, nie przez gotowca, bo autor się mniej dowie. Tym samym również jestem przeciwko gotowcom. Natomiast tutaj nie mamy do czynienia z pytaczem-nierobem, dlatego uważam że mały gotowiec jest do przeżycia. Wiem, Furious że chcesz dobrze, ale nie bądź aż tak radykalny jak ja, bo twoje opisy rozwiązań często zajmują więcej miejsca i pracy niż gotowce, a dajesz je nierobom ;) .

Poza tym, nie widzę powodów do robienia afery z jednego gotowca... Tutaj są recydywiści, ich się trzeba czepiać :P .

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