Zeichensatz Win1252 vs. UTF8

Forum zu diversen Themen rund um die Firebird-Programmierung

Moderator: martin.koeditz

Antworten
zappa2
Beiträge: 31
Registriert: Fr 5. Okt 2018, 10:59

Meine Frage hier ist schon zig mal von anderen in diversen Foren gestellt worden, allerdings habe ich nirgendwo eine brauchbare Lösung finden können:

Ich programmiere in Lazarus und muss auf ziemlich viele 2.5-Firebird-DBs. Deren Varchars sind sämtlich mit Charset Win1252 definiert. Auf diesen DBs rödeln diverse Applikationen rum, die z.T. in Delphi5, einige in Delphi10 usw. geschrieben sind. Demzufolge ist ein Umbau der DB auf UTF8 leider keine Option - was mir das Liebste wäre.

Einzelne Datenfelder kann ich mit WinCPToUTF8 bzw. UTF8ToWinCP gerade biegen. Das funzt auch super.

Was mache ich aber mit Datenmengen-Queries? Bin zwar selbst kein Fan von DbGrid, ist aber Vorgabe.

In der IBConnection Win1252 im CharSet festzulegen bringt leider keinen Erfolg.
Benutzeravatar
martin.koeditz
Beiträge: 478
Registriert: Sa 31. Mär 2018, 14:35

Hallo,

leider kenne ich DbGrid nicht. Arbeitet das intern mit UTF8?

Ich gehe davon aus, dass die DBs unangetastet bleiben sollen. Ist es möglich, den verwendeten Zeichensatz als Verbindungsparameter mit auf den Weg zu geben? Ich weiß allerdings nicht, ob dies was bringt.

Gruß
Martin
Martin Köditz
it & synergy GmbH
bfuerchau
Beiträge: 546
Registriert: Mo 7. Mai 2018, 18:09
Kontaktdaten:

Da heute so gut wie alle höheren Sprachen Strings grundsätzlich in Unicode verarbeiten, bist du eigentlich gezwungen die Datenbank sowie die Tabellen komplett auf UTF8 umzustellen.
Deine Konvertierungsfunktionen sollten eigentlich alle erstmal unnötig sein, da normalerweise alle verwendeten Zugriffe (ADO, .Net, ODBC) die Konvertierungen zwischen WinCP und UNICODE (das ist WideChar und nicht UTF8) vornehmen.
Deine FBConnection sollte also mit CHRSET=WIN1252 funktionieren.

Setze hier nicht auf UTF8, da du dann tatsächlich selber alles von UTF8 nach Unicode und zurück durchführen musst, was du ja auch zusätzlich mit dem Umweg über WINACP (hier also WIN1252) auch tust.

Auch beim Befüllen eines Commandobjektes wird die Konvertierung bei Verwendung von Parameter-Objekten berücksichtig, wenn diese als Type String oder WideChar definiert sind.
Solltest du den Commandstring allerdings selber zusammenbauen (nicht zu empfehlen), so wird alles in WinCP umgewandelt. Erst ab FB3 kann man auch die SQL's in Unicode (Widechar) absetzen.

UTF8 ist generell nur ein Transportwerkzeug (Variabel 1-4 Bytes).
DIe verarbeitbaren Darstellungen sind hier grundsätzlich nur
Byte (8-Bit SBCS SingleByteCharacterSet)
WChar (16-Bit UCS2 UniversalCharacterSet 2Btye)
UCS4 (32-Bit UniversalCharacterSet 4Btye, wird aber real noch nirgends unterstützt)
CString/String/BSTR (WChar[<n>])

Die Darstellung eines Frontends arbeitet ebenso in Strings und benötigt dann eine Unicodefähige Schrift (also WChars > 256).
Bei Webfrontends sieht es wieder etwas anders aus, hierführ gibt es das sog. HTML-Encoding, das dann meist 2 Varianten:
UTF8toHTML
UnicodeToHTML (Default, da wieder von WChar).
Dann wird z.B. aus unserem "Ü" ein "&Uuml;".

Deine WinCP-Routinen haben auch noch den Nachteil, dass sie mit der aktuellen Codepage von Windows umgehen. Kommst du mal auf einen Client/Server mit einer anderen Codepage (WIN1251 = Osteuropa) passen deine Konvertierungen nicht mehr!

Desweiteren:
Dein Frontend wie DBGrid ist Unicodefähig erlaubt also auch die Eingabe von anderen Sprachen. Diese gehen dir aber bei der Übersetzung nach Win1252 verloren, häufig werden sie durch "?" ersetzt.
bfuerchau
Beiträge: 546
Registriert: Mo 7. Mai 2018, 18:09
Kontaktdaten:

Nachtrag:
Wenn du Standardsteuerelemente verwendest, wie DBGrid, dann unterstützen diese auch direkte Datenbindung.
Dies klappt aber nur, wenn die Inhalte auch bindbar sind, also von typ Char oder Wchar und nicht native UTF8!
Du kannst dir das Leben da also massiv vereinfachen, wenn du den Charset der DB in der Verbindung verwendest.
Das klappt dann auch ebenso, wenn du die DB später mal auf UTF8 umgestellt hast, da der FB-Treiber dann Strings verwendet.
zappa2
Beiträge: 31
Registriert: Fr 5. Okt 2018, 10:59

Vielen Dank für die ausführlichen Infos.

Wenn ich der Chefentwickler wäre, würde ich die DB nach UTF8 umstellen (über den Umweg ExtractMetadata=>Edit=>Neuaufbau). Leider bin ich hier nur ein Nebendarsteller, muss mich also dem Druck von oben beugen. Unglaublich, wieviel Zeit man mit diesem Quatsch verballert, ohne irgendwie befriedigend weiter zu kommen.
bfuerchau
Beiträge: 546
Registriert: Mo 7. Mai 2018, 18:09
Kontaktdaten:

Warum kommst du nicht weiter?
Connecte einfach mit Win1252, so wie die DB definiert ist.
Und lass einfach den Quatsch mit der von/nach-UTF8-Konvertierung.
Da WIN1252 eben nur westeuropäisch kann, können eben keine osteuropäischen oder sonstigen Zeichen in der DB gespeichert werden.
Den Steuerelementen und den Programmen ist das egal, da Strings generell Unicode sind (UCS2) und der Treiber die Codewandlung von UCS2 in WIN1252 und umgekehrt erledigt.
Sollte irgendwann die DB in UTF8 umgewandelt sein, brauchst du nur die Connection auf UTF8 anzupassen, ansonsten läuft alles so weiter wie bisher.
Auch dann ist eine zusätzliche Konvertierung nicht erforderlich, das ist Aufgabe des Treibers.
Das Leben kann so einfach sein.
zappa2
Beiträge: 31
Registriert: Fr 5. Okt 2018, 10:59

Geht nun mal nicht. Ohne Konvertierung habe ich immer wieder in diversen Controls anstelle der Umlaute Fragezeichen, ebenso bei einigen Aufrufen im Lazarus-Prog wie z.B. FileExists. Lazarus arbeitet standardmäßig mit UTF8.

Bei anderen Projekten ziehe ich konsequent UTF8 sowohl in der DB als auch im Client durch. Da gibt es nie solche Probleme.
bfuerchau
Beiträge: 546
Registriert: Mo 7. Mai 2018, 18:09
Kontaktdaten:

Ja, ich habe da mal nachgelesen:
https://wiki.freepascal.org/Lazarus_Dat ... utorial/de

So wie es aussieht kann Lazarus ausschließlich UTF8, was an sich schon ungewöhnlich ist da dann spätestens bei der Ausgabe (Druck, Anzeige) wieder in Unicode (UCS2) umgewandelt werden muss und Funktionen wie Substring ungleich aufwändiger werden. Aber das ist Sache der Umgebung.
Nun kann ich das nicht ausprobieren, aber theoretisch sollte dann der Treiber bei der Verwendung von UTF8 im Connectionstring alles korrekt machen ohne dass es zu Problemen in der Darstellung kommen sollte.
Nun sollte dann allerdings Lazarus ebenso bei der Generierung von SQL's dann keine normalen Strings sondern wirklich UTF8-Strings abegeben.
Hierbei ist u.U. besonderes Augenmerk auf die Verwendung von Parametermarkern in SQL's zu legen, dann es gibt eine unterschiedliche Behandlung von SQL-Strings und Parameterwerten.
Parameterwerte müssen nämlich im korrekten Zeichensatz übergeben werden, während der SQL-String selber z.B. kein UTF8 unterstützt.
Also z.B:
"Select * from MyTable where F1=? and F2=?"
1.? = "X"
2.? = 1234
Dasselbe gilt dann insbesonders bei Update/Insert mit den Feldinhalten.
Antworten