Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Cross-Platform-Entwicklung (https://www.delphipraxis.net/91-cross-platform-entwicklung/)
-   -   EEncodingError Fehler (https://www.delphipraxis.net/180079-eencodingerror-fehler.html)

greenmile 21. Apr 2014 19:53

EEncodingError Fehler
 
Hallo,

ich möchte auf dem Mac eine INI mittels TMemIniFile einlesen. Unter XE4 habe ich das immer mit "TMemIniFile.Create(Datei,TEncoding.UTF8)" gemacht, unter XE6 bekomme ich jedesmal die Exception "Im Projekt xxx ist eine Exception der Klasse EEncodingError mit der Meldung 'Keine Zuordnung für Unicode-Zeichen in der Multibyte-Zielcodeseite vorhanden' aufgetreten.". Habe es auch schon mit "TIniFile" versucht, selbiges Problem. Was bedeutet die Meldung? Was ist zu tun? Weiß das jemand?

Betrifft: Firemonkey Mac.

Harry Stahl 21. Apr 2014 21:22

AW: EEncodingError Fehler
 
Also z.B. meine (normalen) Ini-Files zum Speichern und Wiederherstellen der Formpositionen funktionieren:

Delphi-Quellcode:
ini := TIniFile.Create(AppIniName);
Hast Du ein konkretes Beispiel, das man nachvollziehen kann?

Bambini 22. Apr 2014 11:44

AW: EEncodingError Fehler
 
Zitat:

Zitat von greenmile (Beitrag 1256400)
Was bedeutet die Meldung? Was ist zu tun? Weiß das jemand?

Betrifft: Firemonkey Mac.

Die Meldung deutet darauf hin, dass die INI Datei Zeichen enthält,
dies es im Zielzeichensatz (MacOS = UTF8) nicht gibt. wenn z.B. deine INI Datei deutsche Umlaute (öäüÖÄÜß) enthält, die nicht UTF8 codiert sind.

Ronald

greenmile 22. Apr 2014 11:45

AW: EEncodingError Fehler
 
Hmmm, das kein durchaus sein, aber unter XE4 lief es. Gibt es da einen Aufrufparameter in .Create, womit er es "Egal wie, Hauptsache laden" erledigt?

mjustin 22. Apr 2014 11:55

AW: EEncodingError Fehler
 
Zitat:

Zitat von greenmile (Beitrag 1256400)
ich möchte auf dem Mac eine INI mittels TMemIniFile einlesen. Unter XE4 habe ich das immer mit "TMemIniFile.Create(Datei,TEncoding.UTF8)" gemacht

Erfolgen alle Zugriffe nur über Delphi mit vorhergehendem TMemIniFile.Create(Datei,TEncoding.UTF8)?

Wurde die Datei eventuell mit einem Editor manuell bearbeitet, der ein anderes Encoding verwendet?

Das Default Encoding auf OSX ist zwar UTF-8, aber Texteditoren "können auch anders" ;)

greenmile 22. Apr 2014 15:40

AW: EEncodingError Fehler
 
Die Datei lade ich direkt aus dem Internet, die kommt also immer Frisch auf den Tisch :)
Die Datei wird mit Indy mittels GET direkt in einen Stream geschrieben und ja, ich lese Sie nur mit TMemIni ein. Wieso greift da irgendein Encoding-Gedöns?

himitsu 22. Apr 2014 16:04

AW: EEncodingError Fehler
 
Und in Windows ist es standardmäßig ANSI (wie bekommt man im iOS/OSX raus, ob eine Datei ANSI ist, wenn es für ANSI doch kein BOM gibt)

Und ja, Encoding (Umkodierung) brauchst du fast immer, außer
wenn das Format der Datei dem Format der Stringauswertung entspricht.

Und die INI ist vermutlich nicht als Unicode gespeichert.

greenmile 22. Apr 2014 16:07

AW: EEncodingError Fehler
 
Nochmal: Ich lade die Datei mittels IndyHTTP.GET aus dem Netz, es handelt sich halt nur um eine INI Datei. In XE4 geht es einwandfrei, also das einlesen. In XE6 plötzlich nicht mehr. Jetzt kann ich die Quelle natürlich schlecht ändern, weil sonst meine XE4 Anwendungen nicht mehr laufen, also muss ich XE6 irgendwie überreden.

mjustin 22. Apr 2014 16:27

AW: EEncodingError Fehler
 
Zitat:

Zitat von greenmile (Beitrag 1256539)
Die Datei lade ich direkt aus dem Internet

Wie sieht denn der Code zum laden aus dem Internet aus?
Encoding ist immer relevant, wenn man mit mehr als einem Rechner zu tun hat: es kann zu Encoding-Problemen zwischen der auf dem Server liegenden Datei und dem Server, und Encoding-Problemen zwischen dem Server und dem Client kommen.

greenmile 22. Apr 2014 16:55

AW: EEncodingError Fehler
 
Also, ich habe mir die Datei mal mit Notepad++ angeschaut, sie scheint eine UTF8 Datei zu sein, ich kann auch alles darin lesen.
Wenn ich die Datei allerdings mit "TMemIniFile.Create(TempFile,TEncoding.UTF8);" öffne, kommt die Exception.
Genau wie bei TMemIniFile.Create(TempFile,TEncoding.AutoDetect);

Harry Stahl 22. Apr 2014 22:47

AW: EEncodingError Fehler
 
Was meinst Du mit

Delphi-Quellcode:
TMemIniFile.Create(TempFile,TEncoding.AutoDetect);
?

Meinst Du das ohne Parameterangabe (.AutoDetect gibt es ja so als Bezeichner nicht),

also so:

Delphi-Quellcode:
TMemIniFile.Create(TempFile);


Wie auch immer, ich habe hier mal eine UTF8-Ini-Datei auf dem MAC erzeugt und kann die auch ohne Probleme in allen Varianten einlesen (auch wenn die Umlaute oder ähnliches enthält).

Folge doch einfach mal mit dem Debugger den weiteren Verlauf, dann siehst Du ja genau, wo es kracht und erhältst evtl. einen hilfreichen Hinweis, wo das Problem liegen könnte.

greenmile 23. Apr 2014 07:55

AW: EEncodingError Fehler
 
Ich schicke Dir die Datei per PN, sobald ich dazu komme.

Union 23. Apr 2014 08:57

AW: EEncodingError Fehler
 
In XE6 hat sich viel am TEncoding getan. In Anbetracht bisheriger Erfahrungen vermute ich, dass unsere amerikanischen Freunde mal wieder eine Standard-Codepage im Constructor verwendet haben. Kannst Du einen reproduzierbaren Code posten, bspw. mit zwei Buttons zum Speichern / Laden einer Ini, mit der das unter XE6 nachvollziehbar ist? Interessant wäre auch die sw_vers des Mac sowie die sonstige Konfiguration.
Und was gibt file für die Datei aus (z.b. ASCII)?

Bambini 23. Apr 2014 09:16

AW: EEncodingError Fehler
 
Zitat:

Zitat von Harry Stahl (Beitrag 1256599)

Delphi-Quellcode:
TMemIniFile.Create(TempFile,TEncoding.AutoDetect);
?

Denke nicht das es Autodetect gibt, da es für Windows 1252 Zeichensatz kein BOM gibt. Wenn es also eine Datei mit der Codepage 1252 ist, dann stehen die deutschen Umlaute wie z.B. ö mit dem Hexwert $F6 in der Datei. In einer UTF8 codierten Datei steht das ö als zwei Byte $C3 $B6 drin.

Wenn man auf Mac Seite einen String von Codepage 1252 in UTF8 konvertiert möchste, müßte man die
Datei so öffen:
Delphi-Quellcode:
TMemIniFile.Create(TempFile,TEncoding.GetEncoding(1252));
Aber ich denke nicht das das MacOS alle Codepages und deren Konvertierung von und zu UTF8 kennt.
Entweder man sorgt dafür, dass die Datei bereits in UTF8 vorliegt oder man liesst die Datei in TBytes und konvertiert die deutschen Umlaute selbst ins UTF8.

Vielleicht so:
Delphi-Quellcode:
for i:=Low(DateiInBytes) to High(DateiInBytes) do
  case DateiInBytes[i] of
    $F6 : Result := Result + 'ö';

...

himitsu 23. Apr 2014 11:52

AW: EEncodingError Fehler
 
Zitat:

Denke nicht das es Autodetect gibt, da es für Windows 1252 Zeichensatz kein BOM gibt
Es gibt für alle ANSI kein BOM.

Das bekannte BOM ist im Prinzip nur ein Unicode-Zeichen #$FFFE (eventuell war es auch #$FEFF ... vergess das immer), welches mit dem Text kodiert wurde.
(Das Zeichen #$FFFE als UTF-8 kodiert, ergibt die bekannten 3 Byte des UTF-8-BOM)

Alle Zeichensätze, die kein Unicode darstellen können, können also dieses BOM nicht besitzen.
Da würde dann maximal ein "?", oder welches Ersatzzeichen bei der Umwandlung von Unicode verwendet wurde, dort stehen.

(Drum find ich es im Windows besser, wenn dort ohne BOM der Standard die lokale ANSI-Codepage ist, da es für UTF-8 ein BOM gibt)

Die einzige und unsichere Lösung wäre also, wenn man den Text analysiert, bzw. erst nach dem BOM sieht und das verwendet, oder versucht es als UTF-8 zu laden und wenn das knallt, es dann als ANSI zu behandeln.

Harry Stahl 23. Apr 2014 18:42

AW: EEncodingError Fehler
 
Also ich hatte die gleiche Fehlermeldung unter XE6, als ich unter MAC OSX eine Ansi-Datei einlesen wollte (ohne konkrete Encoding-Angabe unterstellt Delphi unter MAC OSX -anders als unter Windows: dort Ansi- , dass die Datei im UTF8-Format vorliegt). Die habe ich dann als Unicode-16 gespeichert (das ist das Format, dass ich für Programme verwende, wenn die Daten Plattformübergreifend unter Windows, MAC OSX, Android uns IOS austauschbar sein sollen), dann war wieder alles OK.

Also ist Deine Datei aus dem Internet wohl doch eine ANSI-Datei.

Delphi kann das nicht richtig erkennen. Für mein TEditor-Programm unter MAC musste ich auch was eigenes entwickeln, um eine ANSI-Datei von UTF8 (und andere Unicode-Varianten) unterscheiden zu können. Da eigentliche Problem ist hauptsächlich die Unterscheidung zwischen UTF8 und ANSI, da ja UTF-8 in den ersten 128 Zeichen identisch ist mit ANSI. Davon abgesehen gibt es auch Unicode-Dateien ohne BOM!

greenmile 23. Apr 2014 20:37

AW: EEncodingError Fehler
 
Hmm, bei der Datei handelt es sich um Text-Daten, die ich vorher mittels PHP aus einer mySQL Datei auslese. Die gebe ich dann, grob formatiert, zurück. Eigentlich sollten sich darin nur (deutsche) lesbare Zeichen befinden, also ANSI. Dass das so nicht funktioniert ist ja schon irgendwie krass. Ich pfusche es jetzt so da ich nicht weiß, was mich in Zukunft so als eingehendes Format erwartet:

Code:
      Err := false;
      Try TempIni := TMemIniFile.Create(TempFile,TEncoding.UTF8); Except Err := true; End;
      if Err then begin
        Err := false;
        Try TempIni := TMemIniFile.Create(TempFile,TEncoding.Ansi); Except Err := true; End;
      End;
      if Err then begin
        Err := false;
        Try TempIni := TMemIniFile.Create(TempFile,TEncoding.Ascii); Except Err := true; End;
      End;
      if Err then begin
        Err := false;
        Try TempIni := TMemIniFile.Create(TempFile,TEncoding.BigEndianUnicode); Except Err := true; End;
      End;
      if Err then begin
        Err := false;
        Try TempIni := TMemIniFile.Create(TempFile,TEncoding.Unicode); Except Err := true; End;
      End;
      if Err then begin
        Err := false;
        Try TempIni := TMemIniFile.Create(TempFile,TEncoding.UTF7); Except Err := true; End;
      End;

Union 23. Apr 2014 21:30

AW: EEncodingError Fehler
 
Wie sieht denn das encoding in request und response aus?

himitsu 23. Apr 2014 21:30

AW: EEncodingError Fehler
 
Meinst du nicht, daß die Logik andersrum einfacher ist?
Delphi-Quellcode:
      Ok := False;
      if not Ok then // ich weiß, das IF ist sinnlos, aber was soll's ... ich mag Symetrie und ich mag es nicht, wie die DP Leerzeichen löscht.
        try TempIni := TMemIniFile.Create(TempFile, TEncoding.UTF8);  Ok := True; except end;
      if not Ok then
        try TempIni := TMemIniFile.Create(TempFile, TEncoding.ASCII); Ok := True; except end;
      if not Ok then
        try TempIni := TMemIniFile.Create(TempFile, TEncoding.UTF7);  Ok := True; except end;
      if not Ok then
        try TempIni := TMemIniFile.Create(TempFile, TEncoding.ANSI);  Ok := True; except end;
Wobei du ein Problem haben wirst, denn man kann einige Kodierugen nicht prüfen, bzw. einige Codierungen lassen alle Daten zu, da sie keine "ungültigen" Byte-Kombinationen kennen.

Als Erstes kann man schauen ob die Datei ein Encoding besitzt.
z.B. über TFileStream und TEncoding.GetBufferEncoding

Wenn es ein BOM gibt, dann über die Automatik laden, also ohne Encoding-Parameter, bzw. man besorgt sich einen passenden über TEncoding.GetEncoding .

Ohne BOM kann man nur versuchen sich gegenseitig ausschließende Codierungen nacheinander durchzuprobieren.

Unicode und BEUnicode nehmen alles an, was (zufällig) eine grade Anzahl an Bytes besitzt, aber wenn man Chinesisch als Sprache erlaubt, dann kann man damit auch jedes andere Format einlesen.

UTF-7 ist 7 Bit pro Zeichen, was zufällig der Spezifikation von von ASCII entspricht, auch als ANSI kann man es problemlos laden und mit UTF-8 geht es auch.
Alles mit 7 Bit lässt sich mit UTF-8 Laden, da das UTF-8 erst am 8. Bit erkennen kann, daß es kein UTF-8 ist.

usw.



Aber ja, hier hat man den Vorteil das eventuell aus dem HTTP-Header rauszubekommen.
Bei einigen Protokollen kann der Client sagen, was er gern haben möchte. (die möglichen Encodings, die unterstützten Komprimierungen, bestimmte Dateiformate, ...)
Und der Server "kann" umgekehrt auch sagen was er letztendlich ausgeliefert hat. (DatenFormat, Datenmenge, ...)

greenmile 24. Apr 2014 08:47

AW: EEncodingError Fehler
 
So, Sch..e voll, mache es jetzt anders:

Code:
TempListDL := TStringlist.Create;
TempListDL.Text := IdHTTP1.Get(URL);
TempListDL.SaveToFile(TempFile);
Dann läuft's auch ...

himitsu 24. Apr 2014 10:40

AW: EEncodingError Fehler
 
Vergiss das TempListDL.Free nicht, sonst läuft das auch noch voll. :zwinker:

Delphi-Quellcode:
TFile.WriteAllText(TempFile, IdHTTP1.Get(URL));
(System.IOUtils)

Matthias 15. Mai 2014 21:42

AW: EEncodingError Fehler
 
Tritt dieser Fehler aus der IDE heraus auf und wenn ja, nutzt Du als IDE Language "Deutsch"?

Bei mir wird diese Meldung 'Keine Zuordnung für Unicode-Zeichen in der Multibyte-Zielcodeseite vorhanden' in xe6 (nicht in xe4 und xe5) im Zusammenhang mit dem Korzh Localizer ausgegeben, wenn ich versuche die Language Files aus der IDE heraus zu aktualisieren. Stelle ich mit Hilfe von BDSSetLang die Sprache der "IDE-Benutzeroberfläche" auf Englisch, dann wird diese Meldung nicht ausgegeben und alles funktioniert wie erwartet.

greenmile 26. Mai 2014 17:17

AW: EEncodingError Fehler
 
Super, jetzt bekomme ich diese nervige Meldung auch dem Android Handy.
Habe es da jetzt so (gepfuscht) gelöst:

function strFileLoad(const aFile: String): String;
var Err: Boolean;
var
aStr : TStrings;
begin
Result:='';
aStr:=TStringList.Create;
try
Err := false;
Try aStr.LoadFromFile(aFile, TEncoding.Ansi); Err := false; Except Err := true; End;
If Err then Try aStr.LoadFromFile(aFile, TEncoding.Default); Err := false; Except Err := true; End;
If Err then Try aStr.LoadFromFile(aFile, TEncoding.Ascii); Err := false; Except Err := true; End;
If Err then Try aStr.LoadFromFile(aFile, TEncoding.UTF8); Err := false; Except Err := true; End;
Result:=aStr.Text;
finally
aStr.Free;
end;
end;


Alle Zeitangaben in WEZ +1. Es ist jetzt 16:59 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz