Die Problematik liegt eigentlich in der Unterscheidung zwischen
ANSI und UTF-8 ohne BOM. Welche CodePage bei
ANSI verwendet werden soll kannst du eh kaum raus finden, wenn du keine Informationen über die Art des Inhaltes hast (manche Zeichen kommen in einer bestimmten Art Text halt nicht vor und sind ein Trigger für eine falsche Codierung). Allerdings beginnen in UTF-8 alle Zeichen > #127 mit einer bestimmten Sequenz. Sind also Zeichen > #127 vorhanden, die nicht mit einer dieser UTF-8 Sequenzen beginnen, handelt es sich offenbar nicht um ein UTF-8 Encoding.
Ein sehr einfacher Ansatz um
ANSI und UTF-8 zu unterscheiden wäre z.B. einfach erst mit TEncoding.UTF8 (BOM oder nicht erkennt er automatisch) einzulesen und falls das eine
Exception wirft eben mit TEncoding.ANSI zu lesen. Bei dieser Vorgehensweise braucht man auch nicht erst das Encoding ermitteln, sondern bekommt das beim Lesen gleich mit. Das spart ein erneutes Durchlaufen zur eigentlichen Verarbeitung der Daten, denn wozu brauche ich das Encoding der Daten, wenn ich sie danach nicht damit lesen will. Das könnte dann in etwa so aussehen:
Delphi-Quellcode:
function StreamToString(Stream: TStream):
string;
var
enc: TEncoding;
reader: TStreamReader;
savePosition: Int64;
begin
savePosition := Stream.Position;
try
{ ANSI als letztes, denn das klappt immer }
for enc
in TArray<TEncoding>.Create(TEncoding.UTF8, TEncoding.ANSI)
do begin
Stream.Position := savePosition;
reader := TStreamReader.Create(Stream, enc, false);
try
try
result := reader.ReadToEnd;
{ Wenn es geklappt hat, Schleife verlassen }
Break;
except
on EEncodingError
do ;
end;
finally
reader.Free;
end;
end;
finally
Stream.Position := savePosition;
end;
end;