Einzelnen Beitrag anzeigen

knaeuel

Registriert seit: 2. Jul 2007
110 Beiträge
 
Delphi 10.3 Rio
 
#1

Delphi und Linux - Encoding-Salat?

  Alt 8. Aug 2019, 12:33
Ich bastele gerade an einer XML-Schnittstelle, welche unter Linux und Windows funktionieren soll. Die XML-Dateien kommen ISO-8859-1 kodiert hier an. Das sollte "ANSI - Lateinisch I" entsprechen, wenn ich das richtig sehe.

Unter Windows gibt es keinerlei Probleme mit den Dateien. Einfach in den Parser werfen und los gehts. Linux ist da schon etwas zickiger. Sobald eine Datei geladen wird, die einen Umlaut (ä,ö,ü) enthält, kommt die Fehlermeldung

"No mapping for the Unicode character exists in the target multi-byte code page"

Dasselbe würde sicherlich auch noch bei dem einen oder anderen Sonderzeichen passieren.

Ok, kein Problem, dachte ich mir. Konvertieren wir halt die Dateien zu Unicode, dann sollte es laufen. Zur Konvertierung gibt es ein prima Beispiel von Delphi - rausgesucht und in mein Programm eingebaut.

Unter Windows und unter Linux kann ich jetzt das Encoding der XML-Dateien anzeigen lassen und wandeln und wieder anzeigen lassen. Theoretisch... Folgendermaßen sind die Ergebnisse, wenn ich die Kodierung von einigen Dateien mit Windows und mit Linux bestimmen lasse (Spalten "Abfrageergebnisse") und wenn ich versuche, die XML-Datei mit dem Parser zu öffnen:
encoding-tabelle.png

Für mich ist das Encoding-Thema ziemlich neu. Ist es erwartungsgemäß, dass Windows die Ascii-Datei für Ansi erklärt? Und wie siehts mit Linux aus? Liegt das mit den ganzen angeblichen UTF-8-Dateien am Dateisystem? Oder macht mein Code nicht was er soll? Oder hat Ddelphi da Schwächen?

Quellcode: Umwandlung
Delphi-Quellcode:
function TDM_XMLSchnittstelle.ConvertFile(filename:string;destination:TEncoding;filename_option:integer):string;
var LBuffer: TBytes;
    LByteOrderMark: TBytes;
    LOffset: Integer;
    LEncoding, DestEncoding: TEncoding;
    LFileStream: TFileStream;
    out_filename:string;
begin
  LEncoding:= nil;
  DestEncoding := destination;
  LFileStream := TFileStream.Create(filename, fmOpenRead);
  try
    //Datei einlesen und im LBuffer ablegen
    SetLength(LBuffer, LFileStream.Size);
    LFileStream.ReadBuffer(Pointer(LBuffer)^, Length(LBuffer));

    //aktuelle Kodierung einlesen
    LOffset := TEncoding.GetBufferEncoding(LBuffer, LEncoding);
    //Konvertierung zur gewünschten Ziel-Kodierung durchführen
    LBuffer := LEncoding.Convert(LEncoding, DestEncoding, LBuffer, LOffset, Length(LBuffer) - LOffset);
  finally
    LFileStream.Free;
  end;

  if filename_option=0 then
    out_filename:=filename
  else if filename_option=1 then
    out_filename:=filename+'.converted'
  else if filename_option=2 then
    out_filename:=filename+'.'+DestEncoding.EncodingName;

  LFileStream := TFileStream.Create(out_filename, fmCreate);
  try
    //zuerst Encoding-Byte-Order-Mark in die Datei schreiben
    LByteOrderMark := DestEncoding.GetPreamble;
    LFileStream.Write(LByteOrderMark[0], Length(LByteOrderMark));
    //danach den Buffer wegschreiben
    LFileStream.Write(LBuffer[0], Length(LBuffer));
  finally
    LFileStream.Free;
  end;
end;
Quellcode Abfrage der Kodierung:
Delphi-Quellcode:
function TDM_XMLSchnittstelle.GetCurrentEncoding(filename:string):TEncoding;
var LBuffer: TBytes;
    LOffset: Integer;
    LEncoding: TEncoding;
    LFileStream: TFileStream;
begin
  LFileStream := TFileStream.Create(filename, fmOpenRead);
  try
    //Datei einlesen und im LBuffer ablegen
    SetLength(LBuffer, LFileStream.Size);
    LFileStream.ReadBuffer(Pointer(LBuffer)^, Length(LBuffer));
    //aktuelle Kodierung einlesen
    LEncoding:= nil; //<-- wichtig, weil die nächste Procedure sonst Käse zurückliefert!
    LOffset := TEncoding.GetBufferEncoding(LBuffer, LEncoding);
  finally
    LFileStream.Free;
  end;
  result:=LEncoding;
end;
Als Quelldatei diente ursprünglich eine ANSI-Datei, die ich mit dieser Konvertierungs-Function umgewandelt habe (unter Windows).

Warum wird ASCII unter Windows nicht als ASCII erkannt?
Warum erkennt Linux gleich mehrere Kodierungen als UTF-8?
Wolfgang
  Mit Zitat antworten Zitat