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:
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?