Delphi-PRAXiS
Seite 3 von 4     123 4   

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Mal wieder Kodierungsprobleme. ANSI UTF8 UTF16 (https://www.delphipraxis.net/194418-mal-wieder-kodierungsprobleme-ansi-utf8-utf16.html)

LTE5 17. Nov 2017 23:00

AW: Mal wieder Kodierungsprobleme. ANSI UTF8
 
Ich glaube greenmiles erster Satz aus Beitrag #20 spiegelt gerade meine Stimmung wieder

http://www.delphipraxis.net/180079-e...-fehler-3.html

Ich habe nicht mal Ahnung von Encodings. Denkst du wirklich ich habe Ahnung von dem was in #6 steht? Nee ;)

ich bin ja nicht so, also hab ichs versucht. Ging nur leider in die hose. Egal welche Datei ich reinwerfe, es ist immer False.
Delphi-Quellcode:
 function IsUTF8(FileName: string): Boolean;
 var
  _FileStream: TFileStream;
  _Word: Word;
 begin
  _FileStream := TFileStream.Create(FileName, fmOpenRead);
  _FileStream.Read(_Word, SizeOf(_Word));

  try
   case _Word of
    $FEFF:
     Result := False; // UTF-16
    $FFFE:
     Result := False; // UTF-16
    $EFBB:
     Result := True; // UTF-8
   end;
  finally
   _FileStream.Free
  end;
 end;

mensch72 17. Nov 2017 23:26

AW: Mal wieder Kodierungsprobleme. ANSI UTF8
 
Stimmungen und Gefühle beim programmieren vermeide ich, weil letztendlich macht die CPU ja doch nur was man ihr gesagt hat und nicht das was man will.
(Selbst Frauen sind da einfacher, die machen zwar selten das was man ihnen sagt, aber oft doch das was (M)man will:) )

Delphi-Quellcode:
function IsUTF8(const data:TStream):boolean;
var
  Value:BYTE;
begin
Result:=False;

data.Position:=0;
while(data.Position<>data.Length) do begin
  Value:=GetByteAndMovePos(data);
  if((Value and $c0)=$c0) and (data.Position<>data.Length) then begin
    Value:=GetByteAndMovePos(data);
    if((Value and $80)=$00) then exit;
  end;
end;

Result:=True;
end;
Wenn dir 5Minuten für so ein paar Zeilen basierend auf #6 zu anstrengend sind, dann investiere eben weiter ständig überall sonst deine Nerven...




ps:
Sichwort "Intel-Speicherformat":
$EFBB: // MSBLSB
Result := True; // UTF-8
$BBEF: // LSBMSB
Result := True; // UTF-8

..."Was ich nicht verstehe ist, warum Google nicht voll von solchen Problemen ist"...
weil die meisten es BYTEbyBYTE auswerten und nicht als WORD, was bei IntelCPUs eben "gedreht" ist... aber alles kein Problem wenn man etwas in HEX denkt:)

LTE5 17. Nov 2017 23:29

AW: Mal wieder Kodierungsprobleme. ANSI UTF8
 
Ich dachte man überprüft verschiedene Encodings so wie mein versuch da oben.
Nur mein Code da oben gibt $BBEF zurück, obwohl meine Datei UTF8 sogar mit BOM ist.

Am liebsten wäre mir natürlich alles ohne Streams. Es gibt nichts was ich mehr hasse als Streams.
Außerdem habe ich keine Ahnung woher ich Streams bekommen soll an den Stellen wo ich diese Prüfung durchführen müsste.
Mit Streams sind das bestimmt X Zeilen pro Aufruf mehr...

Was ich nicht verstehe ist, warum Google nicht voll von solchen Problemen ist. Das kann ja nur heißen, dass das total unwichtig ist.

Redeemer 17. Nov 2017 23:31

AW: Mal wieder Kodierungsprobleme. ANSI UTF8
 
Zitat:

Zitat von LTE5 (Beitrag 1386531)
Ist das hier auch annehmbar?

Delphi-Quellcode:
Memo1.Lines.LoadFromFile('file.txt');
Memo1.Text := UTF8ToString(Memo1.Text);
Das Problem mit der Ini-Datei besteht trotzdem noch. Wenn jemand auf die irrsinnige Idee kommt die Datei nach Ansi zu konvertieren, gibts natürlich ein Problem denn ich hab als Encoding UTF8 beim Create der Ini angegeben.

Und ob das hier eine Lösung ist weiß ich auch nicht
Delphi-Quellcode:
 try
  inherited Create(FileName, TEncoding.UTF8);
 except
  on E: EEncodingError do
   inherited Create(FileName);
 end;

1. Nein, denn LoadFromFile konvertiert von ANSI nach UTF-16. UTF-16, UCS-2 sowie ANSI, CP1252 und ISO 8859-1 (LATIN-1) sehen zwar auf westlichen Computern gleich aus, sind es aber nicht. ANSI ist hier zwar das gleiche wie CP1252, aber UTF-16 (bzw. UCS-2) unterscheidet sich davon bei Zeichen 128-159, weil es dort ISO 8859-1 und nicht CP1252 entspricht. Das Laden eines ANSI-Datei bildet diese CP1252-Zeichen auf völlig andere Zeichen ab. UTF-8 erwartet aber 128-159 dort, sprich es schlägt fehl.
2. Ich speichere solche Dinge nicht in der INI. Strings konvertiere ich nach etwas sicherem, Base64 oder Hex.
3. Encoding produziert keine Fehler. Encoding tut im Fehlerfall einfach nichts.

LTE5 17. Nov 2017 23:36

AW: Mal wieder Kodierungsprobleme. ANSI UTF8
 
Zitat:

3. Encoding produziert keine Fehler. Encoding tut im Fehlerfall einfach nichts.
Wenn man eine ANSI-Datei mit TEncoding.UTF8 lädt, gibt es eine hässliche Fehlermeldung.

Aus dem MSDN Forum
Zitat:

The only easily identifiable text files are those encoded in UTF16 and ones with a BOM. If you have neither, and the vast majority of your files won't, you cannot detect the encoding from the content. Every 8 bit encoding uses all 8 bits to encode characters. You'll need human eyes to look at the decoded text to decide if it is correctly decoded. That's especially hard to do with Western European text, it will be correct for quite a while until you encounter a Word "smart quote".
Ich glaube ich lasse es einfach sein. Ich lasse alles so wie es ist. Es funktioniert und wenn jemand in den Daten rumpfuscht ist es nicht mein Problem.

Klar wäre es schön, wenn ich Unicode-support hätte. Ich denke mit einem Ini > Create (..., TEncoding.Unicode); (UC2-Little-Endian) würden auch nicht-westliche Zeichen gespeichert und geladen.
Aber sobald die Datei mal nicht Unicode ist, gibt es leider wieder diese Fehlermeldungen.

Und ehrlich gesagt... den Aufwand wäre es mir auch wert, um Unicode-fähig zu sein! Delphi ist schon länger Unicodefähig was strings angeht, warum also nicht nutzen.

Ich schlafe mal eine Nacht drüber, lasse mein Kopfkissen meine grenzenlose Wut spüren, indem ich ein paar Tränen vergieße und komme morgen wieder.

Letzte Frage bevor ich aufhöre zu nerven. Angenommen ich stelle nach BigEndianUnicode um.. oder Little, egal.
Muss ich dann allen Funktionen die ich so nutze, sei es zum Lesen oder Schreiben, als Encoding das Unicode-Encoding übergeben?

Redeemer 18. Nov 2017 01:13

AW: Mal wieder Kodierungsprobleme. ANSI UTF8
 
Dann wurd das geändert. Bei mir schlägt TEncoding.UTF8 ohne Fehlermeldung fehl und tut einfach überhaupt nichts.

Auch UTF-16 kann nicht sicher erkannt werden. Das ist interessant, dass gerade Microsoft das behauptet, wo sie doch in Windows XP beim Erkennen von UTF-16 versagt haben. In einigen wenigen Fällen kann man sicher sagen, dass eine Datei kein UTF-16 bzw. UCS-2 ist, aber man kann nie sagen, dass eine Datei UTF-16 ist.

Man kann übrigens Dateien nicht in Unicode speichern und laden, denn Unicode ist keine Kodierung.
Windows und Delphi benutzen als Kodierung UTF-16LE, das kann man theoretisch direkt aus der Datei in WideStrings und wieder zurück schreiben. Auch UCS-2LE kann man ohne Veränderung in WideStrings laden, speichern geht aber nicht.

Für westliche Texte benötigen alle UTF-Kodierungen mehr Platz als ANSI, aber dann ist es immerhin auf allen Systemen gleich. UTF-16 benötigt zudem bei westlichen Texten viel mehr Platz als UTF-8.

Ich kann nicht nachvollziehen, was für Daten du hast. Mach es einheitlich und am besten ohne ANSI.

LTE5 18. Nov 2017 09:06

AW: Mal wieder Kodierungsprobleme. ANSI UTF8
 
Ich habe nur Ini-Dateien bei denen die Section-Namen sowie wenn überhaupt eine Hand voll Bezeichner Alle Zeichen enthalten könnten. Aktuell aber nur westliche Zeichen.

Was ich bisher herausgefunden habe:
versuche ich eine Ini-Datei mit TEncoding.UTF8 zu laden und es ist keine > Fehlermeldung
versuche ich eine Ini-Datei mit TEncoding. BigEndian zu laden und es ist keine > keine Fehlermeldung

Ist eine Datei mit UTF8 rund 1,8KB groß, sind es bei BigEndian schon 3,6 circa. LittleEndian ist gleich. Hier ist es nur ein Bit das woanders gespeichert wird wenn ich das richtig verstanden habe.
Von daher kann ich auch direkt TEncoding.Unicode nehmen.

Ist es denn ratsam nach Unicode umzustellen? Alleine wegen der Möglichkeit nicht-westliche Zeichen schreiben/lesen zu können?
Wenn Unicode doch so viel besser ist, warum ist der Inno Setup Installer dann nur nicht-Unicode und die Unicode-Variante hat so wenige Downloads und ist ein Extra-Download?

Redeemer 18. Nov 2017 10:11

AW: Mal wieder Kodierungsprobleme. ANSI UTF8
 
Da der Benutzer vermutlich keine INI-Dateien aus fremden Quellen benutzt, denn dafür sind die nicht da:
Zitat:

Zitat von Redeemer (Beitrag 1386551)
Mach es einheitlich und am besten ohne ANSI.

Wenn die Section plötzlich irgendwas mit "]" heißen muss, hast du ein Problem, daher wie gesagt die Empfehlung, die Daten als Base64 oder Hex zu speichern, dann muss man sich auch nicht mit Encodings herumschlagen, weil es dann ASCII ist.

Da ich mich jetzt schon zum zehnten Mal wiederhole, lasse ich diesen Thread lieber in Frieden.

LTE5 18. Nov 2017 10:59

AW: Mal wieder Kodierungsprobleme. ANSI UTF8 UTF16
 
Zitat:

Wenn die Section plötzlich irgendwas mit "]" heißen muss, hast du ein Problem
Ich habe das gerade mal getestet.
Code:
[[Testsection]]
klappt erstaunlicherweise ohne Probleme.

Base64 kann ich nicht wirklich verwenden, aufgrund des Unterbaus meines Programms.
Ich gucke aber trotzdem mal was sich machen lässt.
Es sieht aber, das kann ich jetzt schon sagen, eher mager aus. Denn es gibt noch eine weitere Datei die ggf. Unicode-Zeichen enthalten kann.
Alles nun in Base64 zu kodieren und beim Auslesen wieder zu dekodieren, puh, ich weiß nicht. Da setze ich das Encoding lieber auf Unicode.

Aber die Frage nochmal da mir das unklar ist:
wenn Unicode so viel besser ist, da mehr Zeichen gespeichert werden können, warum machen das dann nicht alle so und warum speziell Jordan Russel nicht? Er pflegt mit Compiler-Switches im Grunde zwei Versionen. Einmal Unicode und einmal normal. Warum nicht nur Unicode.

mensch72 18. Nov 2017 11:41

AW: Mal wieder Kodierungsprobleme. ANSI UTF8 UTF16
 
..."Warum nicht nur Unicode."...
Weil bis Delphi2007 die VCL NonUniCode war und UniCode mit TEncoding.XXX insbesondere UTF8 eigentlich erst seit XE5 wo erstmals richtig IOS&Android Mobile funktionieren und die NextGen Compiler brauchbar liefen. Da war dann auch die gemeinsame Delphi RTL soweit, dass man entschieden AnsiString unter FMX auf MobileDevices komplett zu entfernen so das ed dort nurnoch UniCode gibt.

Will man also aktuell portable Quelltexte schreiben, muss man für Delphi kleiner gleich D2007 rein NonUnicode mit AnsiStrings für RTL&VCL arbeiten.
Will man mit D2009..XE4 arbeiten, hat man zwar UniCode RTL&VCL in UTF16 UniCode, aber die anderen Varianten wie UTF8 hakeln dort OutOfThe Box.
Ab XE5 muss man dann bei den NextGen Compilern bei DelphiStrings auch noch beachten, das diese unter Mobile "0" nun basiert sind, also man portabel bei Strings immer schön in Schleifen mit Low(stringX) bis High(stringX) arbeitet. Und immer schön Length(stringX) verwendet, statt der früher noch möglichen Variante per [0]Index.

Da es mittlerweile also praktisch 4 Varianten von "default" DelphiStrings gibt erklärt sich dir eventuell, warum einige wenigsten das alte NonUnicode als AnsiOnly getrennt als eigene Version weiter führen.

1. Wenn du erst jetzt mit XE10.2 "einsteigst" bleibt nur der Rat: Realisiere und akzeptiere das deine gesammte Software per Default als UTF16 läuft.
2. Kümmere dich also nicht um UniCode ja/nein, sondern kümmere dich da wo es sein muss bei Kontakt zur WinApi (spziell also bei IniFiles) um eine EIGENE sichere Erkennung und Behandlung und nutze im Programm ausschließlich das per RTL/VCL gepufferte "TMemIniFile".
3. Verlasse dich nicht auf aktuell "zufällig" gerade noch funktionierende Vereinfachung per Cast oder direkter Zuweisung unter Nutzung impliziter Konvertierung durch den Delphikompiler... das wurde seit D2009 bis aktuell XE10.2.1 speziell bei UTF8 und ANSI schon ein paar mal intern angepasst(wie wenn du genau hier mitgelesen hast erkennst, schreiben ja einige das sie bei TEncoding mal keine Exception bekommen, wo du mit XE10.2 jetzt eine bekommst)
4. auch wenn es schwer fällt, lerne aus der Vergangenheit und nimm jetzt nicht den vermeintlich leichtesten Weg... "früher" (vor D2009) war Delphi mal wegen der "CompilerMagic" die Sprache der Wahl, wenn es um einfaches String handlig ging... jetzt kurz vor dem Sprung auf NextGen Kompiler auch für den Desktop tue dir den Gefallen und denke in UTF16 und behandle alles andere SELBST und kapsele die Konvertierungen in eigene kleine Toolfunktionen... so fällt es dir zukünftig leich nur dort mit ein paar IFDEFs deinen Quelltext mit alten und dann neuen Delphi Versionen zu übersetzen


Alle Zeitangaben in WEZ +1. Es ist jetzt 04:47 Uhr.
Seite 3 von 4     123 4   

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