Net-Base Revistă

19.04.2026

Migrarea la Unicode a proiectelor Delphi vechi: capcane, strategie și implementare curată

Multe aplicații existente Delphi încă folosesc șiruri ANSI. O migrare la Unicode este mai mult decât un comutator de compilator: afectează accesul la date, interfețele, rapoartele, bibliotecile terțe și testele. Acest articol prezintă un traseu de migrare practic – incl...

19.04.2026

Migrarea la Unicode a proiectelor mai vechi Delphi-Projekte este, în multe companii, un pas necesar, deoarece aplicațiile existente altfel întâmpină din ce în ce mai multe limitări la date internaționale, sisteme de operare moderne, integrări și interfețe noi. În practică, rar este vorba de un „Recompile și gata“. Delphi a făcut, începând cu versiunile Unicode (de la Delphi 2009), modificări fundamentale asupra tipurilor standard de string. Astfel se schimbă presupunerile despre codificarea caracterelor, layout-ul în memorie și semnăturile API. Cine subestimează acest lucru generează erori de date care apar treptat, exporturi corupte, cazuri de suport neclare și riscuri de securitate.

Acest articol oferă o procedură tehnic solidă: cum să analizați stocul, să tăiați scope-ul în mod rezonabil, să reduceți riscurile în hotspot-uri (baze de date, fișiere, Windows-APIs, COM, REST-services) și să asigurați migrarea astfel încât operarea și dezvoltarea continuă să rămână posibile în paralel. Accentul este pus pe capcanele tipice Delphi în aplicații VCL, servicii și interfețe – cu privirea către căi de modernizare în care ulterior pot fi integrate și subiecte precum BDE-Ablösung mit nativer Anbindung, REST-Server sau multiplatformă.

Warum die Unicode-Umstellung in Delphi so oft „größer als gedacht“ ist

In klassischen Delphi-Versionen war string ein ANSI-String (je nach Systemcodepage). Seit Delphi 2009 ist string standardmäßig ein UnicodeString (UTF-16). Gleichzeitig wurden viele Bibliotheken und VCL-Klassen auf Wide-APIs umgestellt. Das ist grundsätzlich positiv, weil es internationale Zeichen robust unterstützt. Aber: Legacy-Code ist häufig über Jahre um die Annahmen „1 Zeichen = 1 Byte“, „PChar ist PAnsiChar“ oder „Length() entspricht Byte-Anzahl“ gewachsen.

Die typischen Ursachen, warum Migrationen aufwändiger werden:

  • Implizite Konvertierungen laufen zwar durch, verändern aber Daten (besonders bei Dateien, Schnittstellen oder Datenbank-Blob/Textfeldern).
  • Byte-orientierter Code (Streams, Buffer, Hashing, Verschlüsselung) wird unbemerkt falsch, wenn String-Inhalte als Bytes interpretiert werden.
  • Drittkomponenten sind teils ANSI-only, oder verwenden eigene String-Typen und Callbacks.
  • Externes Umfeld (Windows-APIs, COM, Druck/Reporting, EDI, CSV, XML/JSON) erwartet bestimmte Encodings.

Das Ziel sollte deshalb nicht sein, „möglichst wenig zu ändern“, sondern gezielt dort zu ändern, wo Datenflüsse und Encodings definiert werden müssen. Eine saubere Unicode-Migration ist auch eine Chance, unklare Codierungsgrenzen endlich zu dokumentieren und zu testen.

Technische Grundlagen: Delphi-Stringtypen, Encodings und ihre Nebenwirkungen

string, UnicodeString, AnsiString, WideString – was im Projekt wirklich zählt

Für die Migration ist entscheidend, welche Typen an Schnittstellen und in Kernfunktionen verwendet werden:

  • string: Seit Delphi 2009 ein UnicodeString (UTF-16, reference-counted, immutable semantics über Copy-on-Write).
  • AnsiString: Byte-String mit zugeordneter Codepage (je nach Delphi-Version kann eine Codepage mitgeführt werden). Geeignet, wenn eine externe Schnittstelle explizit eine bestimmte 8-Bit-Codierung verlangt.
  • UTF8String: In neueren Delphi-Versionen häufig als Alias/AnsiString mit UTF-8-Codepage; praktikabel für REST/JSON und viele Protokolle.
  • WideString: BSTR (COM), speicherverwaltet über SysAllocString; heute meist nur noch nötig für bestimmte COM-Interops.
  • PChar: Seit Unicode-Delphi PWideChar. Das ist einer der häufigsten Bruchpunkte bei Windows-API-Calls.

Werden diese Typen gemischt, entstehen Konvertierungen. Manche sind korrekt, manche sind überraschend: Eine Konvertierung ist nur dann „richtig“, wenn Sie wissen, welche Codepage an der Quelle anliegt und welche am Ziel erwartet wird.

UTF-16 intern, UTF-8 extern: ein praxistaugliches Leitbild

In Delphi-VCL-Anwendungen ist es oft sinnvoll, intern konsequent mit string (UTF-16) zu arbeiten. Extern (REST, Dateien, Messaging) dominiert in der Realität UTF-8. Eine robuste Linie lautet daher:

  • Intern: string/UnicodeString als Standard.
  • Grenzen: Beim Ein-/Ausgang explizit über TEncoding.UTF8 (oder definierte ANSI-Codepages) konvertieren.
  • Byte-basierte Verarbeitung: TBytes statt Strings.

Das reduziert implizite Konvertierungen und macht Verantwortlichkeiten prüfbar: „Wo wird aus Bytes Text, und mit welchem Encoding?“

Bestandsaufnahme: Wo Unicode in alten Delphi-Projekten typischerweise bricht

Bevor Sie Code anfassen, lohnt eine strukturierte Inventur. In der Unicode-Migration alter Delphi-Projekte sind die Fehlerquellen meist nicht gleichmäßig verteilt, sondern konzentrieren sich auf einige Hotspots.

1) Datenbankzugriff und Feldtypen (BDE, ADO, FireDAC)

Viele Altprojekte nutzen noch BDE oder ältere Datenzugriffsschichten. Hier sind die Probleme häufig:

  • Zuordnung von Datenbank-Charsets zu Delphi-Strings (ANSI vs. Unicode-Feldtypen).
  • „Text“ in BLOBs oder Memo-Feldern ohne definierte Kodierung.
  • SQL-Statements als Strings, die bei Umlauten/Unicode-Zeichen unterschiedlich interpretiert werden.

Wenn ohnehin Modernisierung ansteht, lässt sich eine Unicode-Migration gut mit einer Bereinigung des Datenzugriffs verbinden, z. B. Richtung BDE-Ablosung mit nativer Anbindung und klarer Charset-Konfiguration (etwa bei PostgreSQL oder MariaDB). Wichtig: Eine Migration sollte nicht automatisch eine Datenbankmigration erzwingen, aber die Schnittstelle zwischen DB und Delphi muss eindeutig sein.

2) Datei- und Stream-I/O: CSV, INI, proprietäre Formate, Import/Export

Ein Klassiker: Dateien wurden früher per AssignFile/ReadLn, TFileStream oder TStringList.LoadFromFile gelesen/geschrieben, ohne Encoding zu setzen. In Unicode-Delphi entscheidet dann Delphi heuristisch (BOM) oder nutzt Default-Encodings. Das führt zu:

  • falsch interpretierten Umlauten (ä, ö) in CSV/Logfiles,
  • fehlerhaften Längenangaben in proprietären Formaten,
  • Inkompatibilitäten zu externen Partnern, die ISO-8859-1 oder Windows-1252 erwarten.

Eine saubere Lösung ist, pro Dateiformat ein festes Encoding zu definieren und das in Code und Dokumentation zu verankern. Für CSV/JSON ist UTF-8 meistens der richtige Standard, für alte Schnittstellen manchmal Windows-1252. Entscheidend ist die Explizitheit.

3) Windows-API, PChar, Buffergrößen und Message-Handling

Viele Delphi-Anwendungen rufen WinAPI-Funktionen auf oder arbeiten mit Buffern. Häufige Bruchstellen:

  • Verwendung von PChar in Verbindung mit Funktionen, die ANSI- oder Wide-Varianten besitzen (…A/…W).
  • Buffergrößen werden in Bytes gerechnet, aber Char ist in UTF-16 2 Byte.
  • Pointer-Arithmetik und Record-Layouts, die auf 1-Byte-Chars basieren.

Hier ist präzises Refactoring nötig: entweder konsequent Wide-APIs nutzen oder bewusst die ANSI-Variante aufrufen und mit AnsiString/Codepage arbeiten. „Irgendwie kompiliert“ ist kein Qualitätskriterium.

4) COM, ActiveX, Office-Automation und Drittbibliotheken

COM-Interfaces arbeiten häufig mit BSTR (WideString). Alte Delphi-Versionen hatten andere Default-Strings, sodass Code „zufällig“ passte. In Unicode-Delphi entstehen oft doppelte Konvertierungen oder falsche Typannahmen in Wrappern. Drittbibliotheken sind ebenfalls kritisch: Manche liefern Callbacks als PAnsiChar, andere erwarten nullterminierte Byte-Strings.

Hier lohnt es sich, Abhängigkeiten zu klassifizieren: Welche Bibliothek ist Unicode-ready, welche nicht, und welche kann ersetzt oder gekapselt werden? Eine Kapselung ist oft der schnellste Weg, um Unicode-Altlasten in einen klar umrissenen Bereich zu verlagern.

Strategie: Unicode-Migration alter Delphi-Projekte als kontrolliertes Modernisierungsprogramm

Die migrationssicherste Vorgehensweise ist ein mehrstufiges Programm, das Risiken früh sichtbar macht und die Anwendung dabei lauffähig hält.

Schritt 1: Scope definieren und Code-Hotspots priorisieren

Nicht jeder Quelltext braucht sofort Anpassungen. Priorisieren Sie nach Datenfluss und Risiko:

  • Schnittstellen nach außen (REST-API, TCP/IP, Dateien, E-Mail, Druck/Reporting).
  • Datenzugriff (SQL, ORM/Datamodule, BDE/FireDAC-Schichten).
  • String-nahe Utility-Funktionen (Parser, Formatter, Encoder/Decoder).
  • Integrationen (COM, DLL-Imports, Hardware-Anbindungen).

Ergebnis sollte eine Liste sein, wo „Encoding eine Spezifikation“ ist. Diese Stellen werden später testbar gemacht.

Schritt 2: Compiler-/Projektoptionen und Warnungen bewusst scharfstellen

In vielen Projekten wurden Warnungen über Jahre abgeschaltet. Für eine Unicode-Migration ist das kontraproduktiv. Sinnvoll ist, Warnungen wieder zu aktivieren und Konvertierungswarnungen ernst zu nehmen. Zusätzlich hilft es, projektweit Regeln festzulegen, etwa: keine impliziten AnsiString-Konvertierungen an I/O-Grenzen, Nutzung von TEncoding bei Dateioperationen, keine „PChar-Tricks“ ohne klaren Kontext.

Schritt 3: „Encoding-Grenzen“ als technische Schicht einziehen

Ein praxistauglicher Architekturgriff ist die Einführung kleiner Adapter/Helper, die genau definieren, wie externe Daten rein und raus gehen. Beispiele:

  • CSV-Reader/-Writer: immer mit TEncoding.UTF8 (oder definierter Codepage) und klaren Separatorregeln.
  • REST-Client/Server: JSON immer als UTF-8-Bytes, Header korrekt setzen, Body nicht „stringbasiert“ streamen.
  • Windows-API-Wrapper: zentrale Funktionen, die Wide/Ansi sauber kapseln.

So verhindern Sie, dass sich „Encoding-Entscheidungen“ quer durch die Codebasis verteilen.

Typische Code-Fallen und wie man sie sauber behebt

Length, SizeOf, ByteLength: wenn Zeichenlänge und Bytegröße auseinanderlaufen

In ANSI-Zeiten wurde Length(s) oft als Byteanzahl missbraucht. In UTF-16 ist das falsch. Wenn Sie Byte-Arrays benötigen, konvertieren Sie explizit:

  • Für UTF-8: TEncoding.UTF8.GetBytes(s)
  • Für definierte ANSI-Codepage: TEncoding.GetEncoding(1252).GetBytes(s) (nur, wenn fachlich korrekt)

Für Buffergrößen bei API-Calls gilt: Prüfen, ob die Funktion Zeichen- oder Byteeinheiten erwartet. Viele Wide-APIs erwarten Zeichenanzahl, nicht Bytes. Dokumentation und Signatur entscheiden, nicht Intuition.

PAnsiChar vs. PWideChar: DLL-Imports und externe Protokolle

Bei DLL-Imports ist die Gefahr groß, dass Signaturen im Delphi-Code nicht mehr passen. Legen Sie fest, was die DLL erwartet:

  • Erwartet die DLL UTF-8? Dann ist die Übergabe als PAnsiChar(UTF8String) üblich, aber Sie müssen Lebenszeit und Nullterminierung kontrollieren.
  • Erwartet sie UTF-16? Dann nutzen Sie PWideChar und Wide-Strings.

In jedem Fall sollten die Imports in einer separaten Unit kapselt werden, damit sich die String-Politik nicht im gesamten Projekt verteilt.

Formatierung, Case-Umwandlung, Vergleich: Locale und Normalisierung

Unicode bringt auch semantische Themen: Groß-/Kleinschreibung ist nicht in allen Sprachen trivial, und Zeichen können verschiedene Normalformen haben. In typischen Unternehmensanwendungen ist das weniger kritisch als in Consumer-Textverarbeitung, aber es betrifft:

  • Sortierung und Filterung (z. B. in Grids oder Suchfunktionen),
  • Case-insensitive Vergleiche für Schlüsselwerte,
  • Generierung von Dateinamen oder Identifiern.

Wichtig ist eine klare Regel: Was sind „Schlüssel“ (z. B. Artikelnummern, Kundencodes), die ASCII-nah bleiben sollten, und was sind „Texte“, die voll Unicode-fähig sein müssen? Diese Trennung reduziert Folgefehler.

GUI/Reporting: Fonts, Druck, PDF und Komponentenverhalten

VCL ist seit den Unicode-Versionen grundsätzlich Unicode-fähig, aber die Praxis hängt an Komponenten und Ausgabepfaden. Risiken entstehen bei:

  • älteren Report-Engines oder PDF-Generatoren, die ANSI annehmen,
  • Barcode-/Label-Druck, der bestimmte Codepages benötigt,
  • Hardcodierten Fonts oder Zeichensätzen.

Planen Sie früh Tests mit realen Beispieldaten (Namen, Orte, Sonderzeichen, nicht-lateinische Schriften, wenn relevant). Der Wert liegt weniger im „kann Unicode“, sondern im Nachweis: „Dieser Output ist in unserem Kontext korrekt.“

Daten und Persistenz: Unicode endet nicht beim Code

Datenbank-Charsets und Collations sauber festlegen

Eine Unicode-Migration ist nur dann stabil, wenn Datenbanken und Treiber korrekt konfiguriert sind. Beispiele:

  • Bei PostgreSQL ist UTF-8 im Regelfall Standard; dennoch müssen Client-Encoding und Treiberverhalten geprüft werden.
  • Bei SQL Server ist die Unterscheidung zwischen VARCHAR und NVARCHAR relevant; falsche Spaltenwahl kann Zeichen verlieren.
  • Bei MariaDB/MySQL sind Charset/Collation (z. B. utf8mb4) entscheidend, damit 4-Byte-Zeichen nicht abgeschnitten werden.

Im Delphi-Code sollten Parameter und Feldtypen so genutzt werden, dass Unicode nicht auf dem Weg „zurückkonvertiert“ wird. FireDAC bietet hier meist bessere Kontrolle als sehr alte Zugriffsschichten.

Legacy-Dateiformate: Migrationsregeln statt stiller Konvertierung

Wenn Ihre Anwendung über Jahre Dateien erzeugt hat (Exportformate, Archivdateien, proprietäre Strukturen), müssen Sie definieren:

  • Welche Bestandsdateien bleiben „wie sie sind“ und werden beim Lesen korrekt interpretiert?
  • Welche Formate werden auf UTF-8 angehoben?
  • Gibt es Versionsfelder/Headers, um neue und alte Dateien eindeutig zu unterscheiden?

Stille Konvertierung ohne Kennzeichnung ist riskant, weil Fehler oft erst spät auffallen. Besser: versionieren, klar erkennen, gezielt migrieren.

Qualitätssicherung: Tests, die Unicode-Probleme wirklich finden

Unicode-Fehler sind häufig datenabhängig. Deshalb reichen „Happy Path“-Tests nicht aus. Sinnvoll ist ein Testset, das die problematischen Stellen abdeckt:

  • Roundtrip-Tests: Import → Verarbeitung → Export, danach Byte-genauer Vergleich (bei definierten Formaten).
  • DB-Roundtrip: Schreiben/Lesen von Texten mit Umlauten, Akzenten und ggf. nicht-lateinischen Zeichen; Prüfung auf Gleichheit.
  • Schnittstellen-Tests: REST-Requests als UTF-8, Header, JSON-Escaping, Logging.
  • Regression: Altdaten und typische Benutzerfälle reproduzieren, vor allem bei Suche, Filter, Sortierung.

Für B2B-Systeme ist außerdem relevant, dass Fehler beobachtbar werden: Logging sollte Encodings nicht zerstören. Wer Logs als ANSI schreibt, verliert im Fehlerfall genau die Information, die man braucht.

Planung und Aufwand: Was die Komplexität wirklich treibt

Der Aufwand der Unicode-Migration alter Delphi-Projekte hängt weniger von „Zeilen Code“ ab, sondern von Kopplungen und externen Abhängigkeiten:

  • Viele Integrationen (DLLs, COM, Geräte, ERP/DMS/CRM) erhöhen Prüfaufwand, weil Encodings an jeder Grenze relevant sind.
  • Historische Formate (alte Exporte, kundenspezifische CSVs) erfordern Migrationsregeln und Kompatibilitätsstrategien.
  • Gemischte Delphi-Versionen oder mehrere Produkte aus einem Code-Stamm erhöhen Koordinationsbedarf.
  • Alte Datenzugriffsschichten (z. B. BDE) können Unicode indirekt blockieren und eine Modernisierung nahelegen.

In der Praxis hat sich ein Vorgehen bewährt, das Unicode zuerst im Kern und in den kritischsten Datenflüssen stabilisiert. Danach kann man schrittweise Module nachziehen. Das reduziert Risiko und verhindert lange „Big Bang“-Phasen ohne Release.

Einordnung in Modernisierungspfade: REST, Services, Multiplattform

Unicode ist häufig ein Grundpfeiler, wenn Bestandssoftware modernisiert werden soll. Typische Anschlussfragen sind:

  • REST-Server oder REST-API nachrüsten (JSON/UTF-8 sauber behandeln).
  • Windows-Services oder Linux-Services stabil betreiben (Logging, Konfigdateien, Protokolle).
  • Schrittweise UI-Modernisierung in VCL, später ggf. Multiplattform-Clients.

Wichtig ist die Reihenfolge: Wenn Sie neue Schnittstellen bauen, sollten Encoding-Regeln vorher feststehen. Eine Unicode-Migration „nebenbei“ während der Schnittstellenentwicklung führt sonst zu schwer prüfbaren Fehlerbildern, weil Ursache und Wirkung vermischt werden.

Für die interne Verlinkung im Magazin bietet sich an, angrenzende Themen wie Delphi-Modernisierung, FireDAC-Datenzugriff oder Architektur von REST-Servern als vertiefende Artikel zu platzieren, sodass Leser gezielt in den nächsten technischen Schritt springen können.

Fazit: Unicode-Migration ist ein Risiko-Thema – mit der richtigen Methode wird es planbar

Die Unicode-Migration alter Delphi-Projekte ist kein kosmetisches Upgrade, sondern eine Korrektur grundlegender Annahmen über Text, Bytes und Schnittstellen. Wer strukturiert vorgeht, gewinnt jedoch mehr als „Umlaute funktionieren wieder“: Datenflüsse werden eindeutiger, Integrationen robuster, und spätere Modernisierung (z. B. REST-Server, Services, Datenbankbereinigung) wird einfacher, weil Encodings nicht mehr implizit „irgendwo“ passieren.

Wenn Sie für Ihre Delphi-Anwendung einen konkreten Migrationsplan, eine Risikoanalyse der Hotspots oder Unterstützung bei der Umsetzung benötigen, ist der schnellste nächste Schritt ein technisches Erstgespräch über Ihre Rahmenbedingungen und Abhängigkeiten: Kontakt aufnehmen.

Im fachlichen Umfeld spielen auch Delphi Unicode Migration und Delphi Ansi Zu Unicode eine wichtige Rolle, wenn Integrationen, Datenflüsse und Weiterentwicklung sauber zusammenspielen müssen.

Projekt oder Modernisierungsvorhaben mit Net-Base besprechen.

Partajează postarea

Distribuiți această postare direct

LinkedIn, X, XING, Facebook, WhatsApp și e-mail sunt disponibile imediat. Pentru Instagram pregătim linkul și textul scurt imediat.

E-mail

Instagram se deschide într-o filă nouă. Linkul și textul scurt se copiază în prealabil în clipboard.