2016-02-29 4 views
8

Ich habe einen EurekaLog Fehlerbericht, der eine EEncodingError zeigt. Das Protokoll zeigt auf TFile.AppendAllText. Ich nenne TFile.AppendAllText ist dieses Verfahren von mir:Was könnte dazu führen, dass auf der Ziel-Multibyte-Codepage keine Zuordnung für das Unicode-Zeichen existiert?

procedure WriteToFile(CONST FileName: string; CONST uString: string; CONST WriteOp: WriteOpperation; ForceFolder: Boolean= FALSE);  // Works with UNC paths 
begin 
if NOT ForceFolder 
OR (ForceFolder AND ForceDirectoriesMsg(ExtractFilePath(FileName))) then 
    if WriteOp= (woOverwrite) 
    then IOUtils.TFile.WriteAllText (FileName, uString) 
    else IOUtils.TFile.AppendAllText(FileName, uString); 
end; 

Dies sind die Informationen aus Eurekalog.

enter image description here

enter image description here

Was kann dies dazu führen, geschehen?

Antwort

11

Dieses Programm gibt den Fehler, den Sie melden:

{$APPTYPE CONSOLE} 

uses 
    System.SysUtils, System.IOUtils; 

var 
    FileName: string; 

begin 
    try 
    FileName := TPath.GetTempFileName; 
    TFile.WriteAllText(FileName, 'é', TEncoding.ANSI); 
    TFile.AppendAllText(FileName, 'é'); 
    except 
    on E: Exception do 
     Writeln(E.ClassName, ': ', E.Message); 
    end; 
end. 

Hier habe ich die ursprüngliche Datei als ANSI geschrieben. Und dann AppendAllText genannt, die versuchen werden, als UTF-8 zu schreiben. Was passiert, ist, dass wir in dieser Funktion am Ende:

class procedure TFile.AppendAllText(const Path, Contents: string); 
var 
    LFileStream: TFileStream; 
    LFileEncoding: TEncoding; // encoding of the file 
    Buff: TBytes; 
    Preamble: TBytes; 
    UTFStr: TBytes; 
    UTF8Str: TBytes; 
begin 
    CheckAppendAllTextParameters(Path, nil, False); 

    LFileStream := nil; 
    try 
    try 
     LFileStream := DoCreateOpenFile(Path); 
     // detect the file encoding 
     LFileEncoding := GetEncoding(LFileStream); 

     // file is written is ASCII (default ANSI code page) 
     if LFileEncoding = TEncoding.ANSI then 
     begin 
     // Contents can be represented as ASCII; 
     // append the contents in ASCII 

     UTFStr := TEncoding.ANSI.GetBytes(Contents); 
     UTF8Str := TEncoding.UTF8.GetBytes(Contents); 

     if TEncoding.UTF8.GetString(UTFStr) = TEncoding.UTF8.GetString(UTF8Str) then 
     begin 
      LFileStream.Seek(0, TSeekOrigin.soEnd); 
      Buff := TEncoding.ANSI.GetBytes(Contents); 
     end 
     // Contents can be represented only in UTF-8; 
     // convert file and Contents encodings to UTF-8 
     else 
     begin 
      // convert file contents to UTF-8 
      LFileStream.Seek(0, TSeekOrigin.soBeginning); 
      SetLength(Buff, LFileStream.Size); 
      LFileStream.ReadBuffer(Buff, Length(Buff)); 
      Buff := TEncoding.Convert(LFileEncoding, TEncoding.UTF8, Buff); 

      // prepare the stream to rewrite the converted file contents 
      LFileStream.Size := Length(Buff); 
      LFileStream.Seek(0, TSeekOrigin.soBeginning); 
      Preamble := TEncoding.UTF8.GetPreamble; 
      LFileStream.WriteBuffer(Preamble, Length(Preamble)); 
      LFileStream.WriteBuffer(Buff, Length(Buff)); 

      // convert Contents in UTF-8 
      Buff := TEncoding.UTF8.GetBytes(Contents); 
     end; 
     end 
     // file is written either in UTF-8 or Unicode (BE or LE); 
     // append Contents encoded in UTF-8 to the file 
     else 
     begin 
     LFileStream.Seek(0, TSeekOrigin.soEnd); 
     Buff := TEncoding.UTF8.GetBytes(Contents); 
     end; 

     // write Contents to the stream 
     LFileStream.WriteBuffer(Buff, Length(Buff)); 
    except 
     on E: EFileStreamError do 
     raise EInOutError.Create(E.Message); 
    end; 
    finally 
    LFileStream.Free; 
    end; 
end; 

Der Fehler von dieser Linie stammt:

if TEncoding.UTF8.GetString(UTFStr) = TEncoding.UTF8.GetString(UTF8Str) then 

Das Problem ist, dass UTFStr ist in der Tat nicht gültig UTF-8. Und daher löst TEncoding.UTF8.GetString(UTFStr) eine Ausnahme aus.

Dies ist ein Fehler in TFile.AppendAllBytes. Vorausgesetzt, dass es sehr gut weiß, dass UTFStrANSI codiert ist, macht es keinen Sinn, es TEncoding.UTF8.GetString zu nennen.

Sie sollten einen Fehlerbericht an Embarcadero für diesen Defekt senden, der in Delphi 10 Seattle noch vorhanden ist. In der Zwischenzeit sollten Sie nicht TFile.AppendAllBytes verwenden.

+0

Was ist mit TStreamReader? Scheint eine gute Alternative und basiert nicht auf IOUtils. – Ampere

+0

Perf ist ein bisschen zweifelhaft. Ich möchte nicht ohne Wissen über die Lebensdauer der Datei beraten und wer sie sonst verändert. –

Verwandte Themen