Migrácia na Unicode starých Delphi-projektov je v mnohých firmách nevyhnutný krok, pretože existujúce aplikácie inak pri medzinárodných dátach, moderných operačných systémoch, integráciách a nových rozhraniach čoraz častejšie narážajú na limity. V praxi to zriedka znamená „Recompile und fertig“. Delphi odvtedy, čo prišli verzie s Unicode (od Delphi 2009), urobil fundamentálne zmeny v štandardných typoch reťazcov. Tým sa posunuli predpoklady o kódovaní znakov, rozložení v pamäti a API-signatúrach. Kto to podcení, vytvára skryté chyby v dátach, poškodené exporty, nejasné podporné prípady a bezpečnostné riziká.
Tento článok poskytuje technicky podložené postupy: ako analyzovať existujúci stav, rozumne ohraničiť rozsah, znížiť riziká v hotspotoch (databázy, súbory, Windows-API, COM, REST-servisy) a zabezpečiť migráciu tak, aby prevádzka a ďalší vývoj mohli prebiehať paralelne. Zameranie je na Delphi-typické úskalia vo VCL-aplikáciách, servisoch a rozhraniach – s ohľadom na modernizačné cesty, do ktorých sa neskôr dajú zaradiť aj témy ako BDE-nahradenie s natívnym napojením, REST-servery alebo multiplatformnosť.
Prečo je prechod na Unicode v Delphi často „väčší, než sa zdá“
V klasických verziách Delphi bol string ANSI-reťazec (v závislosti od systémovej codepage). Od Delphi 2009 je string štandardne UnicodeString (UTF-16). Zároveň boli mnohé knižnice a VCL-triedy prepracované na Wide-API. To je v zásade pozitívne, lebo robustne podporuje medzinárodné znaky. Avšak: legacy-kód sa často počas rokov budoval okolo predpokladov „1 znak = 1 byte“, „PChar je PAnsiChar“ alebo „Length() zodpovedá počtu bajtov“.
Typické príčiny, prečo sú migrácie náročnejšie:
- Implicitné konverzie síce prechádzajú, ale menia dáta (obzvlášť pri súboroch, rozhraniach alebo databázových BLOB/text poliach).
- Byte-orientovaný kód (streams, buffery, hashing, šifrovanie) sa nepozorovane pokazí, keď sa obsah reťazcov interpretuje ako surové bajty.
- Tretie komponenty sú čiastočne ANSI-only alebo používajú vlastné typy reťazcov a callbacky.
- Externé prostredie (Windows-API, COM, tlač/reporting, EDI, CSV, XML/JSON) očakáva konkrétne kódovania.
Cieľ by preto nemal byť „zmeniť čo najmenšie“, ale cielená zmena tam, kde treba definovať dátové toky a kódovania. Čistá Unicode-migrácia je zároveň príležitosť na dokumentáciu a testovanie doteraz nejasných hraníc kódovania.
Technické základy: Delphi-typy reťazcov, kódovania a ich vedľajšie efekty
string, UnicodeString, AnsiString, WideString – čo v projekte naozaj rozhoduje
Pre migráciu je rozhodujúce, ktoré typy sa používajú na rozhraniach a v jadrových funkciách:
- string: Od Delphi 2009 UnicodeString (UTF-16, reference-counted, nemenná semantika cez Copy-on-Write).
- AnsiString: Bajtový reťazec s priradenou codepage (v závislosti od verzie Delphi môže niesť informáciu o codepage). Vhodný, ak externé rozhranie explicitne vyžaduje konkrétne 8-bit kódovanie.
- UTF8String: V novších verziách Delphi často alias/AnsiString s UTF-8 codepage; praktické pre REST/JSON a mnohé protokoly.
- WideString: BSTR (COM), pamäťovo spravované cez SysAllocString; dnes potrebné prevažne pre špecifické COM-interop scenáre.
- PChar: Od Unicode-Delphi PWideChar. To je jeden z najčastejších bodov zlomu pri Windows-API volaniach.
Ak sa tieto typy miešajú, vznikajú konverzie. Niektoré sú korektné, iné prekvapivé: konverzia je „správna“ len vtedy, keď viete, aká codepage je na zdroji a aká sa očakáva na cieli.
UTF-16 interne, UTF-8 externe: praktické odporúčanie
Vo VCL-aplikáciách Delphi je často rozumné pracovať interne konzistentne s string (UTF-16). Externe (REST, súbory, messaging) v praxi často prevažuje UTF-8. Robustné pravidlo teda môže byť:
- Interné: string/UnicodeString ako štandard.
- Hranice: pri vstupe/výstupe explicitne konvertovať cez TEncoding.UTF8 (alebo definované ANSI-codepage).
- Byte-založené spracovanie: TBytes namiesto Strings.
Tým sa znižujú implicitné konverzie a zodpovednosti sa dajú overiť: „Kde sa z bajtov vytvára text a s akým kódovaním?“
Inventúra: kde Unicode v starých Delphi-projektoch typicky zlyháva
Predtým, než sa pustíte do kódu, stojí za to urobiť štruktúrovanú inventúru. Pri Unicode-migrácii starých Delphi-projektov sa zdroje chýb zvyčajne nekoncentrujú náhodne, ale v niekoľkých hotspotoch.
1) Prístup k databáze a typy polí (BDE, ADO, FireDAC)
Mnohé staré projekty stále používajú BDE alebo staršie dátové vrstvy. Tu sú problémy časté:
- Mapovanie kódových stránok databázy na Delphi-reťazce (ANSI vs. Unicode typy polí).
- „Text“ v BLOBoch alebo memo poliach bez definovaného kódovania.
- SQL príkazy ako Strings, ktoré sa pri Umlautoch/Unicode-znakoch rôzne interpretujú.
Ak sa plánuje modernizácia, dá sa Unicode-migrácia dobre spojiť s očistením prístupu k dátam, napr. smerom k BDE-Ablosung mit nativer Anbindung a jasnej konfigurácii charsetov (napr. pri PostgreSQL alebo MariaDB). Dôležité: migrácia by nemala automaticky vnucovať zmenu databázy, ale rozhranie medzi DB a Delphi musí byť jednoznačné.
2) Súborové a stream I/O: CSV, INI, proprietárne formáty, import/export
Klasika: súbory sa kedysi čítali/písali cez AssignFile/ReadLn, TFileStream alebo TStringList.LoadFromFile bez nastavenia kódovania. V Unicode-Delphi potom rozhoduje heuristika (BOM) alebo sa použijú default-encodings. To vedie k:
- nesprávne interpretovaným Umlautom (ä, ö) v CSV/log súboroch,
- chybným údajom o dĺžke v proprietárnych formátoch,
- nekompatibilitám s externými partnermi, ktorí očakávajú ISO-8859-1 alebo Windows-1252.
Čisté riešenie je definovať pre každý formát pevné kódovanie a zakonzervovať to v kóde a dokumentácii. Pre CSV/JSON je väčšinou správny štandard UTF-8, pre staré rozhrania niekedy Windows-1252. Rozhodujúca je explicitnosť.
3) Windows-API, PChar, veľkosti bufferov a spracovanie správ
Mnohé Delphi-aplikácie volajú WinAPI funkcie alebo pracujú s buffermi. Časté miesta zlomu:
- používanie PChar v spojení s funkciami, ktoré majú ANSI- alebo Wide-varianty (…A/…W).
- veľkosti bufferov sa počítajú v bajtoch, ale Char v UTF-16 zaberá 2 bajty.
- arichmetika pointerov a rozloženie Recordov, ktoré sú navrhnuté pre 1-bajtové chary.
Tu je potrebné presné refaktorovanie: buď dôsledne používať Wide-API, alebo vedome volať ANSI-variant a pracovať s AnsiString/codepage. „Irgendwie kompiliert“ nie je kritérium kvality.
4) COM, ActiveX, Office-automatizácia a tretie knižnice
COM rozhrania často pracujú s BSTR (WideString). Staré verzie Delphi mali iné defaultné reťazce, takže kód „náhodou“ fungoval. V Unicode-Delphi často vznikajú dvojité konverzie alebo nesprávne predpoklady v wrapperoch. Tretie knižnice sú tiež kritické: niektoré poskytujú callbacky ako PAnsiChar, iné očakávajú null-terminované bajtové reťazce.
Tu sa oplatí klasifikovať závislosti: ktorá knižnica je Unicode-ready, ktorá nie, a ktorú možno nahradiť alebo zabaliť do adaptéra? Kapsulácia je často najrýchlejšia cesta, ako presunúť Unicode-dlhy do jasne ohraničenej oblasti.
Stratégia: Unicode-migrácia starých Delphi-projektov ako kontrolovaný modernizačný program
Najbezpečnejší postup je viacstupňový program, ktorý sprístupní riziká včas a pritom udrží aplikáciu spustiteľnú.
Krok 1: Definovať scope a priorizovať kódové hotspoty
Nielen každý zdrojový súbor potrebuje okamžitú úpravu. Prioritizujte podľa dátových tokov a rizika:
- rozhrania von (REST-API, TCP/IP, súbory, e‑mail, tlač/reporting).
- prístup k dátam (SQL, ORM/Datamodule, BDE/FireDAC vrstvy).
- utility funkcie blízke reťazcom (parsery, formattery, encoder/decoder).
- integrácie (COM, DLL-importy, napojenia na hardware).
Výsledkom by mal byť zoznam miest, kde je „kódovanie špecifikáciou“. Tieto miesta sa neskôr spravia testovateľnými.
Krok 2: Kompilátor-/projektové voľby a sprísnenie varovaní
V mnohých projektoch boli varovania roky vypnuté. Pre Unicode-migráciu je to kontraproduktívne. Rozumné je varovania znova zapnúť a brať konverzné varovania vážne. Pomôže tiež zaviesť pravidlá na úrovni projektu, napr. žiadne implicitné AnsiString-konverzie na I/O hraniciach, používanie TEncoding pri súborových operáciách, žiadne „PChar-triky“ bez jasného kontextu.
Krok 3: Zaviesť „encoding-hranice“ ako technickú vrstvu
Praktický architektonický prístup je zavedenie malých adapterov/helperov, ktoré presne definujú, ako prichádza a odchádza externá data. Príklady:
- CSV-reader/-writer: vždy s TEncoding.UTF8 (alebo definovanou codepage) a jasnými pravidlami separátora.
- REST-Client/Server: JSON vždy ako UTF-8-byty, header korektne nastavený, telo nie „stringovo“ streamované.
- Windows-API-wrapper: centrálne funkcie, ktoré Wide/Ansi čisto kapsulujú.
Tým zabránite, aby sa rozhodnutia o kódovaní roztrúsili naprieč kódbázou.
Typické kódové pasce a ich čisté opravy
Length, SizeOf, ByteLength: keď sa dĺžka znakov a počet bajtov rozchádzajú
V čase ANSI sa Length(s) často zneužíval ako počet bajtov. V UTF-16 je to nesprávne. Ak potrebujete pole bajtov, konvertujte explicitne:
- Pre UTF-8: TEncoding.UTF8.GetBytes(s)
- Pre definovanú ANSI-codepage: TEncoding.GetEncoding(1252).GetBytes(s) (len ak je to odborne správne)
Pre veľkosti bufferov pri API volaniach platí: overte, či funkcia očakáva jednotky znakov alebo bajtov. Mnohé Wide-API očakávajú počet znakov, nie bajtov. Rozhoduje dokumentácia a signatúra, nie intuícia.
PAnsiChar vs. PWideChar: DLL-importy a externé protokoly
Pri DLL-importoch hrozí, že signatúry v Delphi-kóde už nezodpovedajú. Rozhodnite, čo DLL očakáva:
- Očakáva DLL UTF-8? Potom je obvyklé odovzdať PAnsiChar(UTF8String), ale musíte riadiť životnosť a null-termináciu.
- Očakáva UTF-16? Potom použite PWideChar a wide-stringy.
V každom prípade by mali byť imports zabalené v separátnej jednotke, aby sa politika reťazcov nerozťahovala po celom projekte.
Formátovanie, zmena veľkosti písmen, porovnávanie: locale a normalizácia
Unicode prináša aj sémantické témy: uppercase/lowercase nie sú v každom jazyku triviálne a znaky môžu mať rôzne normalizačné formy. V bežných podnikových aplikáciách sú tieto aspekty menej kritické než v textových editoroch, no dotýkajú sa:
- zoradenia a filtrovania (napr. v gridoch alebo vyhľadávaní),
- case-insensitive porovnaní pre kľúčové hodnoty,
- generovania názvov súborov alebo identifikátorov.
Dôležité je jasné pravidlo: čo sú „kľúče“ (napr. čísla položiek, kódy zákazníkov), ktoré by mali zostať ASCII-nízkoúrovňové, a čo sú „texty“, ktoré musia byť plne Unicode-kompatibilné? Toto oddelenie znižuje následné chyby.
GUI/Reporting: fonty, tlač, PDF a správanie komponentov
VCL je od Unicode-verzií všeobecne Unicode-ready, ale v praxi záleží na komponentách a výstupných tokoch. Riziká vznikajú pri:
- starších report-engineoch alebo PDF-generátoroch, ktoré predpokladajú ANSI,
- barcode/label tlači, ktorá potrebuje konkrétne codepage,
- hardcodovaných fontoch alebo charsetoch.
Plánujte včas testy s reálnymi dátami (mená, lokality, diakritika, nerímske písma, ak relevantné). Hodnota nie je len v tom, že „vie Unicode“, ale v dôkaze: „Tento výstup je v našom kontexte správny.“
Dáta a perzistencia: Unicode nekončí pri kóde
Nastaviť databázové charsety a collations presne
Unicode-migrácia je stabilná len ak sú databázy a ovládače korektne nakonfigurované. Príklady:
- Pri PostgreSQL je UTF-8 obyčajne štandard; napriek tomu treba skontrolovať client-encoding a správanie ovládača.
- Pri SQL Server je relevantné rozlíšenie medzi VARCHAR a NVARCHAR; nesprávny výber stĺpcov môže znamenať stratu znakov.
- Pri MariaDB/MySQL sú charset/collation (napr. utf8mb4) rozhodujúce, aby sa 4-bajtové znaky neobstrihli.
V Delphi-kóde by sa mali parametre a typy polí využívať tak, aby sa Unicode na ceste „neprevádzal späť“. FireDAC tu často poskytuje lepšiu kontrolu než veľmi staré prístupové vrstvy.
Legacy súborové formáty: pravidlá migrácie namiesto tichých konverzií
Ak vaša aplikácia roky generovala súbory (exporty, archívy, proprietárne štruktúry), musíte definovať:
- ktoré existujúce súbory zostanú „tak, ako sú“ a pri čítaní sa správne interpretujú?
- ktoré formáty sa povýšia na UTF-8?
- existujú verziové polia/hlavičky, aby sa nové a staré súbory jednoznačne rozlišovali?
Tichá konverzia bez označenia je riziková, pretože chyby sa často ukážu neskoro. Lepšie: verzovať, jednoznačne rozpoznať a cielene migrovať.
Zaistenie kvality: testy, ktoré Unicode-chyby naozaj odhalia
Unicode-chyby závisia často od dát. Preto nestačia „happy path“ testy. Rozumné je testovacia sada, ktorá pokrýva problematické miesta:
- Roundtrip-testy: import → spracovanie → export, následne bajtovo presné porovnanie (pri definovaných formátoch).
- DB-roundtrip: zápis/čítanie textov s Umlautami, akcentami a prípadne nerímskymi znakmi; overenie rovnosti.
- Rozhraniové testy: REST-requesty ako UTF-8, header, JSON-escaping, logovanie.
- Regresné testy: reprodukcia starých dát a typických užívateľských scenárov, obzvlášť pri vyhľadávaní, filtrovaní, triedení.
Pre B2B-systémy je tiež dôležité, aby boli chyby pozorovateľné: logging by nemal kódovania rozbíjať. Ak zapisujete logy ako ANSI, v prípade chyby stratíte presne informáciu, ktorú potrebujete.
Plánovanie a náklady: čo skutočne zvyšuje zložitosť
Náročnosť Unicode-migrácie starých Delphi-projektov závisí menej od „počíta riadkov kódu“, a viac od väzieb a externých závislostí:
- Množstvo integrácií (DLL, COM, zariadenia, ERP/DMS/CRM) zvyšuje objem overovania, pretože kódovania sú relevantné na každej hranici.
- Historické formáty (staré exporty, zákaznícke CSV) vyžadujú migračné pravidlá a stratégie kompatibility.
- Zmiešané verzie Delphi alebo viaceré produkty z jedného kmeňa zvyšujú potrebu koordinácie.
- Staré dátové vrstvy (napr. BDE) môžu Unicode nepriamo blokovať a naznačujú potrebu modernizácie.
V praxi sa osvedčil prístup, ktorý najprv stabilizuje Unicode v jadre a v najkritickejších dátových tokoch. Potom sa moduly postupne doťahujú. To znižuje riziko a zabraňuje dlhým „Big Bang“ fázam bez releasu.
Zaradenie do modernizačných ciest: REST, servisy, multiplatforma
Unicode je často jedným z pilierov, ak sa má existujúci softvér modernizovať. Typické následné otázky sú:
- REST-servery alebo REST-API doplniť (JSON/UTF-8 korektne spracovať).
- Windows-servisy alebo Linux-servisy stabilne prevádzkovať (logovanie, konfiguračné súbory, protokoly).
- postupnú modernizáciu UI vo VCL, neskôr prípadne multiplatformné klienty.
Dôležitá je postupnosť: pri vývoji nových rozhraní by mali byť pravidlá kódovania vopred stanovené. Unicode-migrácia „bokom“ počas vývoja rozhraní inak vedie k ťažko overiteľným chybám, pretože sa miešajú príčiny a následky.
Pre interné prelinkovanie v magazíne je vhodné umiestniť príbuzné témy ako Delphi-modernizácia, FireDAC-prístup k dátam alebo architektúra REST-serverov ako prehĺbujúce články, aby si čitatelia mohli vybrať ďalší technický krok.
Záver: Unicode-migrácia je riziková téma – s vhodnou metódou je plánovateľná
Migrácia na Unicode starých Delphi-projektov nie je kozmetická aktualizácia, ale korekcia základných predpokladov o texte, bajtoch a rozhraniach. Kto postupuje štruktúrovane, získa viac než „Umlauty opäť fungujú“: dátové toky sú jednoznačnejšie, integrácie robustnejšie a neskoršia modernizácia (napr. REST-servery, servisy, očistenie databázy) je jednoduchšia, pretože kódovania sa už nedejú implicitne „niekde“.
Ak potrebujete pre vašu Delphi-aplikáciu konkrétny migračný plán, analýzu rizík hotspotov alebo pomoc pri realizácii, najrýchlejší ďalší krok je technická úvodná konzultácia o vašich rámcoch a závislostiach: Kontaktovať nás.
V odbornom kontexte majú význam aj témy Delphi Unicode Migration a Delphi Ansi Zu Unicode, keď musia integrácie, dátové toky a ďalší vývoj spolu korektne fungovať.