UTF8 umwandeln

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
Mathias
Beiträge: 6927
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

UTF8 umwandeln

Beitrag von Mathias »

Ich bin mit den UTF8-Befehlen am experimentieren, um genauer zu verstehen was da passiert.

Als Vorgabe habe ich folgende Text-Dateien.

Code: Alles auswählen

äöü.txt
使用下列语言.txt
test.txt
Beim ersten Code, wandle ich die Dateinamen mit SysToUTF8(... selbst um.
Mit den Umlauten klappt es, aber mit den chinesischen Zeichen hat FPC Probleme.
Das Writeln nur die Umlaute schluckt ist mit klar.

Mit 2. Code-Abschnitt geht es ohne Probleme.

Was ist die Ursache.

Code: Alles auswählen

procedure TForm1.FindFirst0Click(Sender: TObject);
var
  SR: TSearchRec;
 
begin
  SetCurrentDir('.');
  Memo1.Clear;
 
  if FindFirst('*.txt', faAnyFile, SR) = 0 then begin
    repeat
      Memo1.Lines.Add(SysToUTF8(SR.Name));
    until FindNext(SR) <> 0;
    FindClose(SR);
    Writeln(UTF8toConsole(Memo1.Lines.Text));
  end;
end;

Code: Alles auswählen

procedure TForm1.FindFirst_UTF8Click(Sender: TObject);
var
  SR: TSearchRec;
 
begin
  SetCurrentDir('.');
  Memo1.Clear;
 
  if FindFirstUTF8('*.txt', faAnyFile, SR) = 0 then begin
    repeat
      Memo1.Lines.Add(SR.Name);
    until FindNextUTF8(SR) <> 0;
    FindClose(SR);
    Writeln(UTF8toConsole(Memo1.Lines.Text));
  end;
end;
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Benutzeravatar
theo
Beiträge: 10897
Registriert: Mo 11. Sep 2006, 19:01

Re: UTF8 umwandeln

Beitrag von theo »

Der Unterschied ist, dass FindFirstUTF8 eine andere Windows Funktion dafür benutzt (FindFirstFileW statt FindFirstFileA).
Mit UTF8ToSys etc. bleibst du in der Welt der 8bit Zeichen, also nur 256.
Man kann damit zwar einen deutschen UTF-8 Umlaut auf einen deutschen Windows Zeichensatz abbilden, aber keine "fremden" Zeichen.

Das geht nur mit den entsprechenden Unicode Funktionen von Windows (xxxW statt xxxA)

PS: Wenn du mal die verschiedenen Unicode Ranges anschauen willst, kannst du mal meine Unicode Tabelle in Lazarus benutzen.
Menu: Bearbeiten -> Aus der Zeichentabelle einfügen... -> Unicode Tab.
Dort kannst du in der Combobox die verschiedenen Ranges auswählen. Zeichen werden natürlich nur angezeigt, wenn ein entsprechender Font installiert ist.
Zuletzt geändert von theo am Mo 29. Dez 2014, 18:19, insgesamt 2-mal geändert.

Mathias
Beiträge: 6927
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: UTF8 umwandeln

Beitrag von Mathias »

Mit UTF8ToSys etc. bleibst du in der Welt der 8bit Zeichen, also nur 256.
Wieso kann dann TMemo die chinesischen Zeichen abbilden, ich dachte TMemo sei auch UTF8 ?
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Benutzeravatar
theo
Beiträge: 10897
Registriert: Mo 11. Sep 2006, 19:01

Re: UTF8 umwandeln

Beitrag von theo »

Mathias hat geschrieben:
Mit UTF8ToSys etc. bleibst du in der Welt der 8bit Zeichen, also nur 256.
Wieso kann dann TMemo die chinesischen Zeichen abbilden, ich dachte TMemo sei auch UTF8 ?
Ja eben, UTF-8 ist Unicode, "ToSys" oder "ToConsole" bei Windows oder "Ansi" sind nicht Unicode.

Schau dir auch noch oben mein P.S. an, vllt. hilft dir das.

Michl
Beiträge: 2511
Registriert: Di 19. Jun 2012, 12:54

Re: UTF8 umwandeln

Beitrag von Michl »

Ist zwar auf Englisch, doch so versteht man die Problematik wahrscheinlich etwas besser (müsste man eigentlich mal eindeutschen): http://www.joelonsoftware.com/articles/Unicode.html

Code: Alles auswählen

type
  TLiveSelection = (lsMoney, lsChilds, lsTime);
  TLive = Array[0..1] of TLiveSelection;  

Mathias
Beiträge: 6927
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: UTF8 umwandeln

Beitrag von Mathias »

kannst du mal meine Unicode Tabelle in Lazarus benutzen.
Wen ich es richtig verstehe, ist UniCode immer 16Bit lang ?

Was muss ich bei folgenden Code ändern, damit es geht ?

Code: Alles auswählen

procedure TForm1.Button1Click(Sender: TObject);
var
  s: string;
  f: Text;
begin
  s := '使用下列语言';     // geht nicht
//  s := 'äöü';              // geht
  AssignFile(f, UTF8toSys(s + '.txt'));
  ReWrite(f);
  Writeln(Length(s));
  s := UTF8toSys(s);
  Writeln(Length(s));
  CloseFile(f);
end;    
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Socke
Lazarusforum e. V.
Beiträge: 3178
Registriert: Di 22. Jul 2008, 19:27
OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
CPU-Target: 32bit x86 armhf
Wohnort: Köln
Kontaktdaten:

Re: UTF8 umwandeln

Beitrag von Socke »

Mathias hat geschrieben:Wen ich es richtig verstehe, ist UniCode immer 16Bit lang ?

Was muss ich bei folgenden Code ändern, damit es geht ?
1. Unicode ist nicht 16 Bit lang. Unicode ist die Zuordnung von Zeichen zu Code Points und hat mit Bits nichts zu tun.

2. AssignFile vergessen unt warten bis FPC 2.8 draußen ist. In der Zwischenzeit musst du direkt mit dem Betriebssystem sprechen (Unter Windows verwendest du z.B. die Funktion OpenFileW())
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

Mathias
Beiträge: 6927
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: UTF8 umwandeln

Beitrag von Mathias »

Unicode ist nicht 16 Bit lang. Unicode ist die Zuordnung von Zeichen zu Code Points und hat mit Bits nichts zu tun.
Ich habe hier gelesen http://de.wikipedia.org/wiki/Unicode , Unicode ist eine recht komplexe Sache.
AssignFile vergessen unt warten bis FPC 2.8 draußen ist.
Wen ich das richtig verstehe, wird FPC 2.8 Unicode unterstützen ?
Aber wenigstens kommt FPC 2.6 mit unseren gängigen Umlauten zurecht.

Was verwendet Windows intern, ist dies UTF16 ?
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Benutzeravatar
theo
Beiträge: 10897
Registriert: Mo 11. Sep 2006, 19:01

Re: UTF8 umwandeln

Beitrag von theo »

Mathias hat geschrieben: Was verwendet Windows intern, ist dies UTF16 ?
Soweit ich weiss ja. http://en.wikipedia.org/wiki/Unicode_in ... ft_Windows
Linux benutzt aber normalerweise UTF-8

Mathias
Beiträge: 6927
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: UTF8 umwandeln

Beitrag von Mathias »

Dieser Code hat folgende Ausgabe

Code: Alles auswählen

  s := 'äöü';
  for i := 1 to Length(s) do begin
    Write(byte(s[i]), '-');  // Ausgabe: 195-164-195-182-195-188
  end;
Somit wird mit 195 angedeutet, das es sich um ein Umlaut handelt.

Anstelle von UTF8toSys kann man UTF8toUTF16 verwenden, dann aber nur unter Windows.

Wieso wird der String bei folgenden Code nicht 6Byte lang ?

Code: Alles auswählen

  s := 'abc';
  s := UTF8toUTF16(s);
  for i := 1 to Length(s) do begin
    Write(byte(s[i]), '-');  // Ausgabe: 97-98-99
  end;
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Benutzeravatar
theo
Beiträge: 10897
Registriert: Mo 11. Sep 2006, 19:01

Re: UTF8 umwandeln

Beitrag von theo »

Mathias hat geschrieben: Somit wird mit 195 angedeutet, das es sich um ein Umlaut handelt.
So kann man das nicht sagen.
195=$C3
Schau dir auf der Unicode Zeichentabelle den Auschnitt "Latin-1 Supplement" an.
Dort siehst du, wenn du mit der Maus über die Buchstaben fährst, u.a. die UTF-8 Repräsentation.
Das startet mit $C2 sowie $C3
Mathias hat geschrieben: Anstelle von UTF8toSys kann man UTF8toUTF16 verwenden, dann aber nur unter Windows.

Wieso wird der String bei folgenden Code nicht 6Byte lang ?

Code: Alles auswählen

  s := 'abc';
  s := UTF8toUTF16(s);
  for i := 1 to Length(s) do begin
    Write(byte(s[i]), '-');  // Ausgabe: 97-98-99
  end;
Warum sollte er? Du darfst dort nicht zweimal das gleiche "s" verwenden, denn du wandelst ja um.
UTF8toUTF16(s) gibt einen UnicodeString zurück, keinen Ansistring.
UTF-8 ist zwar auch Unicode, aber das kann in einem Ansistring untergebracht werden, da es sich um (Byte-) Sequenzen handelt.
Das hat Vor- und Nachteile.

Mathias
Beiträge: 6927
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: UTF8 umwandeln

Beitrag von Mathias »

Du darfst dort nicht zweimal das gleiche "s" verwenden, denn du wandelst ja um.

Code: Alles auswählen

  s := 'abc';
  s2 := UTF8toUTF16(s);
  for i := 1 to Length(s2) do begin
    Write(byte(s2[i]), '-');
  end;   
Es kommt das selbe.
Als Ausgabe hätte ich 00-97-00-98-00-99, oder was ähnliches erwartet.

Das ist ja ein riessen Mischmasch mit den Strings, unter Turbo-Pascal hatte man einen ASCII-String mit 256 Zeichen und fertig. :roll:
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Benutzeravatar
theo
Beiträge: 10897
Registriert: Mo 11. Sep 2006, 19:01

Re: UTF8 umwandeln

Beitrag von theo »

Mathias hat geschrieben: Das ist ja ein riessen Mischmasch mit den Strings, unter Turbo-Pascal hatte man einen ASCII-String mit 256 Zeichen und fertig. :roll:
Du willst ja chinesische Zeichen... und nachher meckern... :lol:

Ullman
Beiträge: 5
Registriert: Fr 28. Feb 2014, 23:08
OS, Lazarus, FPC: Windows8.1 64bit (L 1.4.0 FPC 2.6.4)
CPU-Target: x86
Wohnort: Krefeld

Re: UTF8 umwandeln

Beitrag von Ullman »

Hi,
Mathias möchte gerne chinesische Schriftzeichen haben...und ich werde sie nicht los!
Ich habe eine Text-Datei, die, mit dem Hex-Editor betrachtet mit FFFE beginnt.
Eine BOM-Kennung - OK.
Ich möchte mit Hilfe von TStringList die Datei einlesen und verändern.
Egal was ich anstelle: mein StringList.Add ('Hier der Text'); wird ins chinesische übersetzt :lol:
Ich hab getestet mit SysToUTF8 und umgekehrt...mit AnsiToUTF8 und umgekehrt...
Ich bin wohl irgendwie zu blöd :cry:

Kann mich bitte einer aufs richtige Pferd setzten?
Das ganze soll als Konsolen-Anwendung laufen.

Code: Alles auswählen

 sl_var := TStringList.Create;
 
 try
   sl_var.LoadFromFile (SysToUTF8(LogFileName));
 
 
   sl_var.AddText ('File was modified by dpinst-log analyser.');
   sl_var.AddText ('-----------------------------------------');
 
   sl_var.SavetoFile (UTF8ToSys(LogFileName));
 
 except
 
   on E: EInOutError do
      writeln('File handling error occurred. Reason: ', E.Message);
 
 end;
 
 sl_var.Free;
Führt zu:

楆敬眠獡洠摯晩敩⁤祢搠楰獮⵴潬⁧湡污獹牥മⴊⴭⴭⴭⴭⴭⴭⴭⴭⴭⴭⴭⴭⴭⴭⴭⴭⴭⴭⴭⴭ਍


Windows 8.1 64, Lazarus 1.40

LG Ullman
Zuletzt geändert von Lori am Sa 9. Mai 2015, 09:31, insgesamt 1-mal geändert.
Grund: Highlighter
"When a man speaks in a forest, and no woman is there to hear him, is he still wrong?"

Benutzeravatar
theo
Beiträge: 10897
Registriert: Mo 11. Sep 2006, 19:01

Re: UTF8 umwandeln

Beitrag von theo »

Das müsste mit meinem TCharEncStream klappen:
http://wiki.lazarus.freepascal.org/UTF8_Tools

Siehe dort auch /demo/charenc/

Antworten