Net-Base Magazín

19.04.2026

Migrace starých Delphi projektů na Unicode: úskalí, strategie a čistá implementace

Mnoho Delphi-existujících aplikací stále používá ANSI řetězce. Migrace na Unicode pak není pouhý přepínač kompilátoru: týká se přístupu k datům, rozhraní, reportů, knihoven třetích stran a testů. Tento článek ukazuje praxí ověřenou migrační cestu – vč...

19.04.2026

Migrace na Unicode ve starších Delphi-projektech je v mnoha podnicích nezbytným krokem, protože provozní aplikace jinak při práci s mezinárodními daty, moderními operačními systémy, integracemi a novými rozhraními začínají narážet na limity. V praxi to zřídka znamená „překompilovat a hotovo“. Delphi od verzí s Unicode (od Delphi 2009) provedl fundamentální změny standardních typů řetězců. Tím se posouvají předpoklady o kódování znaků, rozložení v paměti a signaturách API. Kdo toto podcení, vytváří pozvolné datové chyby, rozbité exporty, nejasné supportní případy a bezpečnostní rizika.

Tento příspěvek poskytuje technicky podložený postup: jak analyzovat stav kódu, rozumně vymezit rozsah, snížit rizika v kritických bodech (databáze, soubory, Windows-API, COM, REST-servisy) a zajistit migraci tak, aby provoz i další vývoj zůstaly paralelně možné. Důraz je na typických nástrahách Delphi ve VCL-aplikacích, službách a rozhraních – s ohledem na modernizační cesty, do kterých lze později zařadit i témata jako BDE-odstranění s nativním napojením, REST-servery nebo multiplatformu.

Proč je přechod na Unicode v Delphi často „větší, než se čekalo“

Ve klasických verzích Delphi byl string ANSI-řetězec (dle systémové codepage). Od Delphi 2009 je string standardně UnicodeString (UTF-16). Současně byla řada knihoven a VCL-tříd převedena na Wide-API. To je z hlediska podpory mezinárodních znaků pozitivní změna. Ovšem: legacy kód byl často vyvíjen s předpoklady „1 znak = 1 byte“, „PChar je PAnsiChar“ nebo „Length() odpovídá počtu bytů“.

Typické příčiny, proč jsou migrace náročnější:

  • Implicitní konverze sice proběhnou, ale mění data (zejména u souborů, rozhraní nebo databázových BLOB/text polí).
  • Byte-orientovaný kód (streamy, buffery, hashing, šifrování) funguje tiše špatně, pokud se obsah řetězců interpretuje jako byty.
  • Třetí knihovny jsou částečně ANSI-only nebo používají vlastní typy řetězců a callbacky.
  • Externí okolí (Windows-API, COM, tisk/reporting, EDI, CSV, XML/JSON) očekává konkrétní kódování.

Cílem by proto nemělo být „co nejméně měnit“, ale cíleně upravit místa, kde je třeba definovat datové toky a kódování. Pečlivá Unicode-migrace je zároveň příležitostí definitivně zdokumentovat a otestovat nejasné hranice kódování.

Technické základy: Delphi-typy řetězců, encodings a jejich vedlejší efekty

string, UnicodeString, AnsiString, WideString – co v projektu skutečně rozhoduje

Pro migraci je rozhodující, jaké typy se používají na rozhraních a v jádrových funkcích:

  • string: Od Delphi 2009 UnicodeString (UTF-16, reference-counted, semantika immutable přes Copy-on-Write).
  • AnsiString: Byte-řetězec s přiřazenou codepage (v závislosti na verzi Delphi může nést informaci o codepage). Vhodný, pokud externí rozhraní explicitně vyžaduje určité 8bitové kódování.
  • UTF8String: Ve novějších verzích Delphi často alias/AnsiString s UTF-8 codepage; praktické pro REST/JSON a mnoho protokolů.
  • WideString: BSTR (COM), spravováno přes SysAllocString; dnes obvykle potřeba jen pro specifické COM-interopy.
  • PChar: Od Unicode-Delphi PWideChar. To je jeden z nejčastějších bodů lomu při volání Windows-API.

Pokud se tyto typy míchají, vznikají konverze. Některé jsou korektní, jiné překvapivé: konverze je „správná“ jen tehdy, když znáte codepage zdroje a očekávané kódování cíle.

Interně UTF-16, externě UTF-8: praktické vodítko

Ve VCL-aplikacích Delphi je často rozumné interně konzistentně pracovat s string (UTF-16). Externě (REST, soubory, messaging) v praxi převládá UTF-8. Robustní pravidla tedy mohou znít:

  • Interně: string/UnicodeString jako standard.
  • Hranice: při vstupu/výstupu explicitně konvertovat přes TEncoding.UTF8 (nebo definované ANSI-codepage).
  • Byte-zpracování: TBytes místo řetězců.

To snižuje implicitní konverze a činí odpovědnosti testovatelnými: „Kde se z bytů stává text a s jakým encodingem?“

Inventura: kde v starých Delphi-projektech Unicode typicky selhává

Než sáhnete do kódu, vyplatí se strukturovaná inventura. V Unicode-migracích starých Delphi-projektů se zdroje chyb obvykle nekoncentrují rovnoměrně, ale v několika hotspotech.

1) Přístup k databázi a typy polí (BDE, ADO, FireDAC)

Mnoho starých projektů stále používá BDE nebo ještě starší vrstvy přístupu k datům. Zde se často objevují problémy:

  • Přiřazení charsetů databáze k Delphi-řetězcům (ANSI vs. Unicode typy polí).
  • „Text“ v BLOBech nebo memo polích bez definovaného kódování.
  • SQL příkazy jako řetězce, které se při přítomnosti umlautů/Unicode znaků interpretují různě.

Pokud je modernizace plánovaná, lze Unicode-migraci dobře zkombinovat s očištěním přístupu k datům, např. směrem k BDE-Ablosung mit nativer Anbindung a jednoznačné konfiguraci charsetů (např. u PostgreSQL nebo MariaDB). Důležité: migrace by neměla automaticky nutit změnu databáze, ale rozhraní mezi DB a Delphi musí být jednoznačné.

2) Souborové a stream I/O: CSV, INI, proprietární formáty, import/export

Klasika: soubory se dříve četly/zapisovaly přes AssignFile/ReadLn, TFileStream nebo TStringList.LoadFromFile bez nastavení encodingu. V Unicode-Delphi pak Delphi heuristicky rozhoduje (BOM) nebo použije výchozí encoding. To vede k:

  • nesprávně interpretovaným umlautům (ä, ö) v CSV/logs,
  • chybám v udávaných délkách u proprietárních formátů,
  • nekompatibilitě s externími partnery, kteří očekávají ISO-8859-1 nebo Windows-1252.

Čisté řešení je definovat pro každý formát pevné kódování a zapracovat to do kódu a dokumentace. Pro CSV/JSON je UTF-8 obvykle správný standard, pro stará rozhraní někdy Windows-1252. Rozhodující je explicitnost.

3) Windows-API, PChar, velikosti bufferů a zpracování zpráv

Mnohé Delphi-aplikace volají WinAPI funkce nebo pracují s buffery. Časté body lomu:

  • Použití PChar ve spojení s funkcemi, které mají ANSI- i Wide-varianty (…A/…W).
  • Velikosti bufferů jsou počítány v bytech, ale Char v UTF-16 zabírá 2 byty.
  • Pointer-aritmetika a layouty recordů, které vycházejí z 1-bytových znaků.

Zde je potřeba přesné refaktoring: buď důsledně používat Wide-API, nebo cíleně volat ANSI-variantu a pracovat s AnsiString/codepage. „Nějak se to zkompiluje“ není kritérium kvality.

4) COM, ActiveX, Office-Automation a třetí knihovny

COM rozhraní často pracují s BSTR (WideString). Starší verze Delphi měly jiné výchozí řetězce, takže kód „náhodou“ fungoval. V Unicode-Delphi se často objevují dvojité konverze nebo nesprávné předpoklady typů v wrapperech. Kritické jsou i třetí knihovny: některé předávají callbacky jako PAnsiChar, jiné očekávají nulou ukončené byte-řetězce.

Stojí za to klasifikovat závislosti: která knihovna je Unicode-ready, která ne, a kterou lze nahradit nebo enkapsulovat? Enkapsulace je často nejrychlejší cesta, jak seskupit Unicode legacy v jasně ohraničené oblasti.

Strategie: Unicode-migrace starých Delphi-projektů jako řízený modernizační program

Nejbezpečnější postup pro migraci je vícestupňový program, který zviditelní rizika včas a udrží aplikaci běžící.

Krok 1: Definovat scope a prioritizovat code-hotspoty

Není nutné okamžitě upravovat každý zdrojový soubor. Prioritizujte podle datových toků a rizika:

  • Rozhraní ven (REST-API, TCP/IP, soubory, e‑mail, tisk/reporting).
  • Přístup k datům (SQL, ORM/Datamodule, BDE/FireDAC vrstvy).
  • Utility funkce blízké řetězcům (parsery, formattery, encoder/decoder).
  • Integrace (COM, DLL-importy, napojení na hardware).

Výsledkem by měl být seznam míst, kde je „encoding specifikací“. Tato místa se později učiní testovatelnými.

Krok 2: Kompilátor-/projektové volby a varování znovu zapnout

V mnoha projektech byla varování po léta vypnuta. Pro Unicode-migraci je to kontraproduktivní. Doporučuje se znovu povolit varování a brát konverzní hlášení vážně. Pomůže také zavést projektová pravidla, např.: žádné implicitní AnsiString-konverze na I/O hranicích, použití TEncoding u operací se soubory, žádné „PChar-triky“ bez jasného kontextu.

Krok 3: Zavést „encoding-hranice“ jako technickou vrstvu

Praktický architektonický zásah je zavedení malých adapterů/helperů, které přesně definují, jak externí data přicházejí a odcházejí. Příklady:

  • CSV-reader/-writer: vždy s TEncoding.UTF8 (nebo definovanou codepage) a jasnými pravidly separátoru.
  • REST-client/server: JSON vždy jako UTF-8-byty, hlavičky správně nastavené, tělo ne „stringově“ streamované.
  • Windows-API-wrapper: centrální funkce, které Wide/Ansi čistě enkapsulují.

Tím zabráníte tomu, aby se rozhodnutí o encodingu rozptýlila napříč kódbází.

Typické pastičky v kódu a jak je bezpečně opravit

Length, SizeOf, ByteLength: když se délka znaků a počet bytů rozejdou

V éře ANSI se Length(s) často zneužívalo jako počet bytů. V UTF-16 to není pravda. Pokud potřebujete byte‑pole, konvertujte explicitně:

  • Pro UTF-8: TEncoding.UTF8.GetBytes(s)
  • Pro definovanou ANSI-codepage: TEncoding.GetEncoding(1252).GetBytes(s) (pouze pokud je to funkčně správné)

Pro velikosti bufferů u volání API platí: ověřte, zda funkce očekává počet znaků nebo bytů. Mnohé Wide-API očekávají počet znaků, ne bytů. Rozhoduje dokumentace a signatura, ne intuice.

PAnsiChar vs. PWideChar: DLL-importy a externí protokoly

U DLL-importů hrozí, že signatury v Delphi-kódu už neodpovídají tomu, co DLL očekává. Stanovte, co DLL vyžaduje:

  • Očekává DLL UTF-8? Pak je běžné předávat PAnsiChar(UTF8String), ale musíte kontrolovat životnost a nulové ukončení.
  • Očekává UTF-16? Pak použijte PWideChar a Wide-řetězce.

V každém případě by importy měly být enkapsulované v samostatné unitě, aby se politika řetězců nerozlévala po celém projektu.

Formátování, převody velikosti písmen, porovnávání: locale a normalizace

Unicode přináší i sémantická témata: změna velikosti písmen není ve všech jazycích triviální a znaky mohou existovat v různých normalizačních formách. V typických podnikových aplikacích to není tak kritické jako v textových editorech, ale týká se to:

  • řazení a filtrování (např. v gridu nebo vyhledávání),
  • case-insensitive porovnání klíčových hodnot,
  • generování názvů souborů nebo identifikátorů.

Důležité je stanovit jasné pravidlo: co jsou „klíče“ (např. čísla artiklů, kódy zákazníků), které by měly zůstat ASCII-ní blízko, a co jsou „texty“, které musí být plně Unicode‑schopné. Tím se omezí následné chyby.

GUI/Reporting: fonty, tisk, PDF a chování komponent

VCL je od verzí s Unicode zásadně Unicode‑schopné, ale provoz závisí na komponentách a výstupních cestách. Rizika vznikají u:

  • starších reportovacích enginů nebo PDF‑generatorů, které očekávají ANSI,
  • tisků čárových kódů/štítků, které vyžadují specifické codepage,
  • hardcodovaných fontů nebo znakových sad.

Plánujte včas testy s reálnými vzorky dat (jména, místa, speciální znaky, ne-latinské abecedy, pokud jsou relevantní). Hodnota není v tom „umí Unicode“, ale v prokázání: „Tento výstup je v našem kontextu korektní.“

Data a perzistence: Unicode nekončí u kódu

Jasné nastavení charsetů a kolací v databázích

Unicode‑migrace bude stabilní jen tehdy, pokud jsou databáze a ovladače správně nakonfigurovány. Příklady:

  • U PostgreSQL je UTF-8 obvykle standard; klientské encodingy a chování ovladače je třeba přesto ověřit.
  • U SQL Server je relevantní rozlišení mezi VARCHAR a NVARCHAR; nesprávný typ sloupce může znaky ztratit.
  • U MariaDB/MySQL jsou klíčové charset/collation (např. utf8mb4), aby se 4‑bytové znaky neodřízly.

V Delphi-kódu by se měly parametry a typy polí tak použít, aby se Unicode neupravoval zpětnou konverzí. FireDAC obvykle nabízí lepší kontrolu než velmi staré přístupové vrstvy.

Legacy souborové formáty: pravidla migrace místo tichých konverzí

Pokud vaše aplikace roky vytvářela soubory (exporty, archivní soubory, proprietární struktury), musíte definovat:

  • které existující soubory zůstanou „tak, jak jsou“ a budou při čtení správně interpretovány,
  • které formáty budou povýšeny na UTF-8,
  • zda existují verze/hlavičky, které jednoznačně odliší nové a staré soubory.

Tichá konverze bez označení je riziková, protože chyby se často objeví až pozdě. Lepší je verzování, jasné rozpoznání a cílená migrace.

Kvalitní zajištění: testy, které Unicode‑problémy skutečně odhalí

Unicode‑chyby závisí často na datech. Proto nestačí „happy‑path“ testy. Rozumné je testovací sady, které pokrývají problematická místa:

  • Roundtrip‑testy: import → zpracování → export a následné byte‑přesné porovnání (pro definované formáty).
  • DB‑roundtrip: zápis/čtení textů s umlauty, akcenty a případně ne‑latinskými znaky; kontrola shody.
  • Rozhraní‑testy: REST‑requesty jako UTF‑8, hlavičky, JSON‑escaping, logging.
  • Regrese: reprodukce starých dat a typických uživatelských scénářů, zejména vyhledávání, filtrování, řazení.

Pro B2B systémy je také důležité, aby chyby byly pozorovatelné: logging by neměl kódování ničit. Kdo zapisuje logy jako ANSI, ztrácí při chybě přesně tu informaci, kterou potřebuje.

Plán a náklady: co skutečně zvyšuje složitost

Náročnost Unicode‑migrace starých Delphi‑projektů závisí méně na počtu řádků kódu a více na vazbách a externích závislostech:

  • Mnoho integrací (DLL, COM, zařízení, ERP/DMS/CRM) zvyšuje rozsah kontroly, protože kódování je relevantní na každé hranici.
  • Historické formáty (staré exporty, zákaznické CSV) vyžadují migrační pravidla a strategii kompatibility.
  • Smíšené verze Delphi nebo více produktů z jednoho kódu zvyšují koordinační nároky.
  • Staré datové přístupové vrstvy (např. BDE) mohou Unicode nepřímo blokovat a naznačit potřebu modernizace.

V praxi se osvědčilo nejprve stabilizovat Unicode v jádru a v kritických datových tocích. Poté lze postupně migrovat moduly. To snižuje riziko a zamezí dlouhým „big bang“ fázím bez releasu.

Zařazení do modernizačních cest: REST, služby, multiplatforma

Unicode je často stavebním kamenem, pokud má dojít k modernizaci stávajícího softwaru. Typické následné otázky:

  • REST‑servery nebo REST‑API doplnit (správné zpracování JSON/UTF‑8).
  • Stabilní provoz Windows‑servisů nebo Linux‑servisů (logging, konfigurační soubory, protokoly).
  • Postupná UI‑modernizace ve VCL a později eventuálně multiplatformní klienti.

Pořadí je důležité: pokud budujete nová rozhraní, měly by být pravidla pro encoding stanovena předem. Unicode‑migrace „souběžně“ s vývojem rozhraní vede k těžko testovatelným chybám, protože se příčina a důsledek míchají.

Pro interní prolinkování v magazínu se nabízí umístit doplňková témata jako Delphi‑modernizace, FireDAC‑přístup k datům nebo architektura REST‑serverů jako prohlubující články, aby čtenář mohl cíleně přejít k dalším technickým krokům.

Závěr: Unicode‑migrace je rizikové téma – s vhodnou metodou je plánovatelné

Migrace na Unicode ve starých Delphi‑projektech není kosmetická aktualizace, ale náprava základních předpokladů o textu, bytech a rozhraních. Kdo postupuje strukturovaně, získá ale víc než „umluví se znaky“: datové toky budou jednoznačnější, integrace odolnější a další modernizace (např. REST‑servery, služby, očištění databáze) snazší, protože kódování se přestane dít implicitně „kdesi“.

Pokud pro svou Delphi‑aplikaci potřebujete konkrétní migrační plán, analýzu rizik hotspotů nebo podporu při realizaci, nejrychlejší další krok je technická úvodní konzultace o vašich podmínkách a závislostech: Kontaktovat.

V odborném kontextu hrají také roli Delphi Unicode migrace a Delphi Ansi Zu Unicode, pokud mají integrace, datové toky a další vývoj fungovat koordinovaně.

Projednat projekt nebo modernizační záměr s Net-Base.

Sdílet příspěvek

Sdílet tento příspěvek přímo

LinkedIn, X, XING, Facebook, WhatsApp a e-mail jsou ihned k dispozici. Pro Instagram připravíme odkaz a stručný text.

E-mail

Instagram se otevře v nové záložce. Odkaz a krátký text budou předtím zkopírovány do schránky.