Autor Téma: Textový súbor v ANSI kódovaní  (Přečteno 7389 krát)

Offline Slavomir

  • Mladík
  • **
  • Příspěvků: 58
  • Karma: 0
    • Verze Delphi: XE2 + 10.3 Community Edition
    • RQ Money
Textový súbor v ANSI kódovaní
« kdy: 18-03-2014, 11:08:33 »
Snažím sa načítať do Lazarusu (v1.2.0) obyčajný textový súbor v ANSI kódovaní (pár riadkov). Žiaľ, neviem, ho dostať do Lazarusu bez poškodenia, stále namiesto znakov s diakritikou (napr. č, š, ť, á) dostávam otázniky v texte.
Skúsil som načítať súbor cez TFileStream, TStringList aj TMemo.
Viem, že Lazarus je silno orientovaný na UTF8, ale toto by hádam mohol zvládnuť. Alebo robím chybu ja?  :-[
Lazarus, Delphi - RQ Money

Offline < z >

  • Administrátoři
  • Guru
  • *****
  • Příspěvků: 1145
  • Karma: 44
    • Verze Delphi: 7, 2010
Re:Textový súbor v ANSI kódovaní
« Odpověď #1 kdy: 18-03-2014, 11:18:04 »
Google tvrdi toto:
Strings.LoadFromStream(TDecodingStream.Create(TFileStream.Create('myfile'), '...', 'utf-8'));

Offline Slavomir

  • Mladík
  • **
  • Příspěvků: 58
  • Karma: 0
    • Verze Delphi: XE2 + 10.3 Community Edition
    • RQ Money
Re:Textový súbor v ANSI kódovaní
« Odpověď #2 kdy: 18-03-2014, 14:12:14 »
Vďaka za nakopnutie, skúšam to (i keď zatiaľ bez úspechu). :(
Ak správne uvažujem, tak:
Strings = čokoľvek, čo podporuje funkciu LoadFromStrings (napr. TStrings, TMemo, ...)
TDecodingStream = TOwnerStream (to som našiel na webe)
TFileStream = TFileStream (ten sa nemení)
...
Nevadí, budem skúšať ďalej.
Lazarus, Delphi - RQ Money

Offline < z >

  • Administrátoři
  • Guru
  • *****
  • Příspěvků: 1145
  • Karma: 44
    • Verze Delphi: 7, 2010
Re:Textový súbor v ANSI kódovaní
« Odpověď #3 kdy: 18-03-2014, 14:21:09 »
TFileStream muze byt zrejme zastoupen jakymkoliv steamem, jde o zdroj dat.
TDecodingStream je to, co te zajima - mel by provest prislusnou konverzi.
A ano, Strings bude tvoje Memo ... snad :)

Offline < z >

  • Administrátoři
  • Guru
  • *****
  • Příspěvků: 1145
  • Karma: 44
    • Verze Delphi: 7, 2010
Re:Textový súbor v ANSI kódovaní
« Odpověď #4 kdy: 18-03-2014, 14:34:40 »
... aha ... zrejme pujde o "udelej si sam" funkci :)

ale kdyz udelas toto:
  Memo1.Lines.LoadFromFile('...');
  Memo1.Lines.Text:=UTF8Encode(Memo1.Lines.Text);
tak by se to melo zobrazit spravne
« Poslední změna: 18-03-2014, 14:42:57 od < z > »

Offline Ondřej Pokorný

  • Guru
  • *****
  • Příspěvků: 815
  • Karma: 59
    • Verze Delphi: Primárně Lazarus, jinak D7 až aktuální
    • Kluug.net
Re:Textový súbor v ANSI kódovaní
« Odpověď #5 kdy: 18-03-2014, 18:22:07 »
... aha ... zrejme pujde o "udelej si sam" funkci :)

ale kdyz udelas toto:
  Memo1.Lines.LoadFromFile('...');
  Memo1.Lines.Text:=UTF8Encode(Memo1.Lines.Text);
tak by se to melo zobrazit spravne

<z>, prosím tě, neraď lidem podobné prasokódy, které jsou za a naprosto krutopřísně blbě a za b ještě k tomu nefungují...

----

Slavomíre, nejjednodušší pro tebe bude stáhnout si mojí OXml z http://www.kluug.net/oxml.php. Ta má mimo jiné tyto unity:
- OEncoding.pas: port TEncoding z Delphi 2009+ pro Lazarus a D6-2007.
- OTextReadWrite.pas: rychlé čtení stringů ze streamu s bufferem.

Pak ti stačí tento kód:

Kód: [Vybrat]
procedure TForm1.Button7Click(Sender: TObject);
var
  xFileStream: TFileStream;
  xReader: TOTextReader;
  S: String;
begin
  xFileStream := nil;
  xReader := nil;
  try
    xFileStream := TFileStream.Create('S:\test-ansi.txt', fmOpenRead or fmShareDenyNone);//vytvoř file stream
    xReader := TOTextReader.Create(xFileStream, TEncoding.ANSI);//vytvoř TOTextReader, použij kódování ANSI, pokud neexistuje BOM

    S := xReader.ReadString(High(Integer));//přečti kompletní soubor najednou

    //v S je uložen obsah souboru, dělej si s ním co chceš...
    ShowMessage(S);
  finally
    xReader.Free;
    xFileStream.Free;
  end;
end;
« Poslední změna: 18-03-2014, 18:30:44 od oxo »
Embarcadero Technology Partner

Offline < z >

  • Administrátoři
  • Guru
  • *****
  • Příspěvků: 1145
  • Karma: 44
    • Verze Delphi: 7, 2010
Re:Textový súbor v ANSI kódovaní
« Odpověď #6 kdy: 18-03-2014, 21:01:11 »
s a) bych souhlasil, s b) zasadne souhlasit nemuzu - uz jen proto, ze funguji ;)

ale jinak ty OXml vypadaj dobre

Offline Ondřej Pokorný

  • Guru
  • *****
  • Příspěvků: 815
  • Karma: 59
    • Verze Delphi: Primárně Lazarus, jinak D7 až aktuální
    • Kluug.net
Re:Textový súbor v ANSI kódovaní
« Odpověď #7 kdy: 18-03-2014, 23:00:44 »
s a) bych souhlasil, s b) zasadne souhlasit nemuzu - uz jen proto, ze funguji ;)
Tvůj kód v Lazarusu nefunguje... ;)

ale jinak ty OXml vypadaj dobre
Díky!
Embarcadero Technology Partner

Offline < z >

  • Administrátoři
  • Guru
  • *****
  • Příspěvků: 1145
  • Karma: 44
    • Verze Delphi: 7, 2010
Re:Textový súbor v ANSI kódovaní
« Odpověď #8 kdy: 19-03-2014, 07:45:14 »
Tvůj kód v Lazarusu nefunguje... ;)


Offline Slavomir

  • Mladík
  • **
  • Příspěvků: 58
  • Karma: 0
    • Verze Delphi: XE2 + 10.3 Community Edition
    • RQ Money
Re:Textový súbor v ANSI kódovaní
« Odpověď #9 kdy: 19-03-2014, 09:11:03 »
Ďakujem obidvom za radu.
To oxo: nie som až tak zbehlý, aby som si v tej hromade súborov od Teba našiel len to, čo potrebujem. Možno neskôr, keď zlyhajú iné spôsoby.
To <z>: podľa nákresu to funguje. Podľa Lazarusu nie.  :-[
Niečo iné je vložiť do TMemo nejaký ANSI text a potom to vedľa previesť do UTF8 a niečo iné použiť funkciu LoadFromFile. Možno sa mýlim, preto prikladám môj kód funkcie - udalosť na TMenuItem (+ náhľad obrázku + ANSI súbor na stiahnutie):


Kód: [Vybrat]
procedure TfrmMain.mnuOtvoritClick(Sender: TObject);
begin
if OpenDialog.Execute <> True then Exit;
If FileExists(OpenDialog.FileName) = True then begin
    memSprievodka.Lines.LoadFromFile(OpenDialog.FileName);
    memSprievodka.Lines.Text := UTF8Encode(memSprievodka.Lines.Text);
end;
end;

Tak netuším, kde robím chybu.
Lazarus, Delphi - RQ Money

Offline < z >

  • Administrátoři
  • Guru
  • *****
  • Příspěvků: 1145
  • Karma: 44
    • Verze Delphi: 7, 2010
Re:Textový súbor v ANSI kódovaní
« Odpověď #10 kdy: 19-03-2014, 10:01:50 »
oxo ti to cele naserviroval ... staci do uses pouzit to OEncoding a frcis.

Muj blby napad neni vhodny prave proto, ze neni univerzalni a musis natvrdo prijit na to,
jak to spravne dekodovat. Zajimave je, ze me to funguje i s tvym souborem :)

muzes jeste vyzkouset toto?
AnsiToUtf8(AnsiString(memSprievodka.Lines.Text))

oxo me sice zabije, kdyz to uvidi :D

resp. mozna by bylo lepsi to udelat takto, aby ses vyhnul tem prasackym
nekontrolovatelnym konverzim

Kód: [Vybrat]
var
  txt: TextFile;
  textline: AnsiString;
begin
  AssignFile(txt, 'sprievodka.txt');
  Reset(txt);
  Repeat
  Readln(txt,textline);
  Memo1.Lines.Add(AnsiToUtf8(textline));
  Until EOF(txt);
  Closefile(txt);

A jeste jedna moznost
http://wiki.lazarus.freepascal.org/Theodp
... jeden soubor, je tam i priklad
« Poslední změna: 19-03-2014, 10:18:07 od < z > »

Offline Slavomir

  • Mladík
  • **
  • Příspěvků: 58
  • Karma: 0
    • Verze Delphi: XE2 + 10.3 Community Edition
    • RQ Money
Re:Textový súbor v ANSI kódovaní
« Odpověď #11 kdy: 19-03-2014, 10:38:08 »
Citace
muzes jeste vyzkouset toto?
AnsiToUtf8(AnsiString(memSprievodka.Lines.Text))
Tak toto nefungovalo ani náhodou ... :D

Citace
resp. mozna by bylo lepsi to udelat takto, aby ses vyhnul tem prasackym nekontrolovatelnym konverzim ...
Tak toto našťastie fungovalo v poriadku!!! Jupí.  :) :) :)
Dúfam len, že spätne to pôjde nejak takto uložiť (v prípade zmeny v texte) zase naspäť do ANSI súboru bez problémov.
Srdečná vďaka za pomoc, < z > !!!
Je to predsa len jednoduchšie riešenie, ako navrhoval oxo.
Lazarus, Delphi - RQ Money

Offline Ondřej Pokorný

  • Guru
  • *****
  • Příspěvků: 815
  • Karma: 59
    • Verze Delphi: Primárně Lazarus, jinak D7 až aktuální
    • Kluug.net
Re:Textový súbor v ANSI kódovaní
« Odpověď #12 kdy: 19-03-2014, 10:43:13 »
To oxo: nie som až tak zbehlý, aby som si v tej hromade súborov od Teba našiel len to, čo potrebujem. Možno neskôr, keď zlyhajú iné spôsoby.

Hmmm, jasně jsem ti napsal, co potřebuješ: OEncoding a OTextReadWrite. Stačí být dost zběhlý ve čtení... :)

----

< z >:
Kód: [Vybrat]
  Memo1.Lines.LoadFromFile('...');
  Memo1.Lines.Text:=UTF8Encode(Memo1.Lines.Text);

podobné kódy možná fungují u tebe, u mě a (podle jeho reakcí) u Slavomíra taky ne. Používáš tam implicitní konverze v rámci různých kódování, které se mohou na různých počítačích (system locale) chovat různě - a to i jako kompilovaný projekt... Takže ne-e, tak fakt ne.

A používat TextFile, to už je skoro předminulé století... :)
Embarcadero Technology Partner

Offline < z >

  • Administrátoři
  • Guru
  • *****
  • Příspěvků: 1145
  • Karma: 44
    • Verze Delphi: 7, 2010
Re:Textový súbor v ANSI kódovaní
« Odpověď #13 kdy: 19-03-2014, 11:00:23 »
Tak me to je jasny, ze se to bude chovat ruzne :)
Jen jsem nechtel brat bazuku na komara ...

Tak aby byli vsichni stastni
Kód: [Vybrat]
var
  s: AnsiString;
  m: TMemoryStream;
begin
  m:=TMemoryStream.Create;
  try
     // load
     m.LoadFromFile('test.txt');
     SetString(s, PAnsiChar(M.Memory), M.Size);
     Memo1.Lines.Text:=AnsiToUtf8(s);

     // save
     m.Clear;
     s:=Utf8ToAnsi(Memo1.Lines.Text);
     m.Write(Pointer(s)^, length(s));
     m.SaveToFile('test2.txt');
  finally
    m.Free;
  end;
end;

Offline Slavomir

  • Mladík
  • **
  • Příspěvků: 58
  • Karma: 0
    • Verze Delphi: XE2 + 10.3 Community Edition
    • RQ Money
Re:Textový súbor v ANSI kódovaní
« Odpověď #14 kdy: 19-03-2014, 11:02:37 »
Citace
Hmmm, jasně jsem ti napsal, co potřebuješ: OEncoding a OTextReadWrite. Stačí být dost zběhlý ve čtení... :)
Máš pravdu, bolo to jasne napísané, ešte raz ďakujem za ponuku súborov.
Ale musiš uznať, že riešenie od < z > je krátke a aj pre mňa (laika) zrozumiteľné (a vôbec mi nevadí, že je to funkcia či premenná "z minulého storočia"). Hlavné je, že funguje.  ;)
Lazarus, Delphi - RQ Money

Offline < z >

  • Administrátoři
  • Guru
  • *****
  • Příspěvků: 1145
  • Karma: 44
    • Verze Delphi: 7, 2010
Re:Textový súbor v ANSI kódovaní
« Odpověď #15 kdy: 19-03-2014, 11:04:03 »
... kdyby sis nevsiml ... jeste jsem ti to prepsal na "modernejsi" variantu - mas tam i nacitani, i ulozeni ;)

Offline Ondřej Pokorný

  • Guru
  • *****
  • Příspěvků: 815
  • Karma: 59
    • Verze Delphi: Primárně Lazarus, jinak D7 až aktuální
    • Kluug.net
Re:Textový súbor v ANSI kódovaní
« Odpověď #16 kdy: 19-03-2014, 11:37:38 »
Tak me to je jasny, ze se to bude chovat ruzne :)
Jen jsem nechtel brat bazuku na komara ...

Tak aby byli vsichni stastni

Kdepak, to je už konečně aspoň systematicky správně! A jednoduché to je taky dost, žádná bazuka...

Dvě poznámky:
1.) Máš ten soubor třikrát v paměti - jednou v TMemoryStream, pak v proměnné s a pak ho konvertuješ. Pro práci se soubory tu je TFileStream, není důvod ho nepoužít - a tak si ušetřít aspoň paměť nutnou pro TMemoryStream:

Kód: [Vybrat]
procedure TForm1.Button8Click(Sender: TObject);
var
  s: AnsiString;
  f: TFileStream;
begin
  // load
  f := TFileStream.Create('S:\test-ansi.txt', fmOpenRead or fmShareDenyNone);
  try
     SetLength(s, f.Size);
     f.ReadBuffer(PAnsiChar(s)^, f.Size);
     Memo1.Lines.Text:=AnsiToUtf8(s);
  finally
    f.Free;
  end;

  // save
  f := TFileStream.Create('S:\test-ansi-2.txt', fmCreate);
  try
     s:=Utf8ToAnsi(Memo1.Lines.Text);
     f.WriteBuffer(PAnsiChar(s)^, length(s));
  finally
    f.Free;
  end;
end;

Ale opět ten soubor máš v paměti dvakrát, protože ho konvertuješ celý najednou. Moje řešení s OTextReadWrite/OEncoding ho načítá a konvertuje po částech přes stejný buffer, takže je v paměti jen jednou. To je ale pro malé soubory vlastně jedno...

2.) Funkci TStream.Write() není vhodné takto používat, protože ignoruješ návratovou hodnotu (počet bytů, které zapsala). Pro takové věci se používá TStream.WriteBuffer(), která to ošetřuje.
Embarcadero Technology Partner

Offline Slavomir

  • Mladík
  • **
  • Příspěvků: 58
  • Karma: 0
    • Verze Delphi: XE2 + 10.3 Community Edition
    • RQ Money
Re:Textový súbor v ANSI kódovaní
« Odpověď #17 kdy: 19-03-2014, 12:09:52 »
Citace
... kdyby sis nevsiml ... jeste jsem ti to prepsal na "modernejsi" variantu - mas tam i nacitani, i ulozeni ;)
Skúsil som obidve funkcie, je to výborné!
Ešte raz ďakujem za pomoc.

(Nerozumiem, prečo toto nemá Lazarus ošetrené nejakou funkciou ...)  :o
Lazarus, Delphi - RQ Money