Unicode-migracija starih Delphi-projekata u mnogim preduzećima je neophodan korak, jer postojeće aplikacije inače kod internacionalnih podataka, modernih operativnih sistema, integracija i novih interfejsa sve češće nailaze na ograničenja. U praksi to rijetko znači „Recompile i gotovo“. Delphi je od Unicode-verzija (od Delphi 2009) izvršio temeljne promjene u standardnim string-tipovima. Time su se pomjerila očekivanja o kodiranju znakova, rasporedu u memoriji i potpisima API-ja. Ko to podcijeni, proizvodi postepene greške u podacima, pokvarene exporte, nejasne support-slučajeve i sigurnosne rizike.
Ovaj članak pruža tehnički utemeljenu proceduru: kako analizirati postojeći sistem, razumno odrediti opseg, smanjiti rizike na hotspotovima (baze podataka, fajlovi, Windows-APIs, COM, REST-servisi) i osigurati migraciju tako da rad sistema i dalji razvoj mogu teći paralelno. Fokus je na Delphi-tipičnim zamkama u VCL-aplikacijama, servisima i interfejsima – s pogledom na puteve modernizacije u koje se kasnije mogu uklopiti i teme poput BDE-zamjene s nativnim priključkom, REST-servera ili multiplatformskog rada.
Zašto je Unicode-prelazak u Delphi često „veći nego što se misli“
U klasičnim verzijama Delphi tip string je bio ANSI-string (ovisno o sistemskoj codepage). Od Delphi 2009 string je standardno UnicodeString (UTF-16). Istovremeno su mnoge biblioteke i VCL-klase prešle na Wide-API-je. To je generalno pozitivno jer robustno podržava internacionalne znakove. Ali: legacy-kod je često tokom godina nastao pod pretpostavkama „1 znak = 1 bajt“, „PChar je PAnsiChar“ ili „Length() odgovara broju bajtova”.
Tipični uzroci zbog kojih migracije postaju zahtjevnije:
- Implicitne konverzije prolaze, ali mijenjaju podatke (posebno kod fajlova, interfejsa ili polja tipa BLOB/Text u bazama).
- Bajt-orijentirani kod (streamovi, bufferi, hashing, enkripcija) postaje neprimjetno netačan kada se sadržaj stringova interpretira kao bajtovi.
- Komponente trećih strana su ponekad ANSI-only ili koriste vlastite string-tipe i callback-e.
- Spoljašnji kontekst (Windows-APIs, COM, štampa/reporting, EDI, CSV, XML/JSON) očekuje određena kodiranja.
Cilj zato ne bi trebao biti „što manje mijenjati“, nego ciljano mijenjati tamo gdje treba jasno definirati tokove podataka i kodiranja. Čista Unicode-migracija je i prilika da se nedoređene granice kodiranja napokon dokumentuju i testiraju.
Tehničke osnove: Delphi-stringtipovi, encodingi i njihove nuspojave
string, UnicodeString, AnsiString, WideString – šta u projektu zaista znači
Za migraciju je presudno koji se tipovi koriste na interfejsima i u ključnim funkcijama:
- string: od Delphi 2009 UnicodeString (UTF-16, reference-counted, immutable semantika preko Copy-on-Write).
- AnsiString: bajt-string s pridruženom codepage (ovisno o verziji Delphi može nositi informaciju o codepage). Pogodan kad eksterni interfejs eksplicitno zahtijeva određeno 8-bitno kodiranje.
- UTF8String: u novijim verzijama Delphi često alias/AnsiString s UTF-8 codepage; praktičan za REST/JSON i mnoge protokole.
- WideString: BSTR (COM), upravljanje memorijom preko SysAllocString; danas obično potreban samo za određene COM-interop-e.
- PChar: od Unicode-Delphi PWideChar. To je jedna od najčešćih tačaka preloma kod Windows-API poziva.
Ako se ovi tipovi miješaju, nastaju konverzije. Neke su ispravne, neke iznenađujuće: konverzija je „tačna“ samo ako znate koju codepage ima izvor i šta cilj očekuje.
Interno UTF-16, eksterno UTF-8: praktično vodilo
U VCL-aplikacijama baziranim na Delphi često je smisleno interno dosljedno raditi s string (UTF-16). Eksterno (REST, fajlovi, messaging) u praksi dominira UTF-8. Robusna linija glasi:
- Interno: string/UnicodeString kao standard.
- Granice: pri ulazu/izlazu eksplicitno konvertovati preko TEncoding.UTF8 (ili definirane ANSI-codepage-e).
- Bajt-bazirana obrada: TBytes umjesto String-ova.
To smanjuje implicitne konverzije i čini odgovornosti provjerljivim: „Gdje se bajtovi pretvaraju u tekst i koje je kodiranje?“
Inventar: gdje Unicode u starim Delphi-projektima tipično puca
Prije nego što dirate kod, vrijedi strukturirana inventura. U Unicode-migracijama starih Delphi-projekata izvori grešaka obično nisu ravnomjerno raspoređeni, nego se koncentriraju na nekoliko hotspotova.
1) Pristup bazi podataka i tipovi polja (BDE, ADO, FireDAC)
Mnogi stari projekti još koriste BDE ili starije slojeve za pristup podacima. Problemi su često:
- Povezivanje charset-a baze s Delphi-stringovima (ANSI nasuprot Unicode-polju).
- „Tekst“ u BLOB-ovima ili memo-poljima bez definirane enkodacije.
- SQL-naredbe kao String-ovi koji se pri umlautima/Unicode-znakovima različito interpretiraju.
Ako ionako planirate modernizaciju, Unicode-migraciju je dobro kombinovati s čišćenjem pristupa podacima, npr. u smjeru BDE-Ablosung mit nativer Anbindung i jasne konfiguracije charset-a (kao kod PostgreSQL ili MariaDB). Važno: migracija ne mora automatski iznuditi promjenu baze, ali sučelje između DB i Delphi mora biti nedvosmisleno.
2) Fajl- i stream-I/O: CSV, INI, proprietarni formati, import/export
Klasičan slučaj: fajlovi su ranije čitani preko AssignFile/ReadLn, TFileStream ili TStringList.LoadFromFile bez postavljenog encodinga. U Unicode-Delphi tada Delphi heuristički odlučuje (BOM) ili koristi default-encoding. To dovodi do:
- pogrešno interpretiranih umlauta (ä, ö) u CSV/log fajlovima,
- netočnih informacija o dužini u proprietarnim formatima,
- nekompatibilnosti s vanjskim partnerima koji očekuju ISO-8859-1 ili Windows-1252.
Čisto rješenje je definirati po formatu fajla fiksno kodiranje i to zabilježiti u kodu i dokumentaciji. Za CSV/JSON je UTF-8 najčešće ispravan standard, za stare interfejse ponekad Windows-1252. Presudna je eksplicitnost.
3) Windows-API, PChar, veličine buffera i rukovanje porukama
Mnoge Delphi-aplikacije zovu WinAPI funkcije ili rade s bufferima. Česte točke loma:
- korištenje PChar u vezi s funkcijama koje imaju ANSI- ili Wide-varijante (…A/…W).
- veličine buffera se računaju u bajtovima, a Char u UTF-16 zauzima 2 bajta.
- aritmetika pokazivača i layout record-a koji su zasnovani na 1-bajtnih char-ovima.
Ovdje je potrebno precizno refaktoriranje: ili dosljedno koristiti Wide-API-je ili svjesno pozivati ANSI-varijantu i raditi s AnsiString/codepage-om. „Negdje se kompajlira“ nije kriterij kvaliteta.
4) COM, ActiveX, Office-automation i biblioteke trećih strana
COM-interface-i često rade s BSTR (WideString). Stare verzije Delphi imale su drugačije default-stringove, pa je kod „slučajno“ radio. U Unicode-Delphi često nastaju duple konverzije ili pogrešne pretpostavke tipova u wrapper-ima. Biblioteke trećih strana su također kritične: neke vraćaju callback-e kao PAnsiChar, druge očekuju null-terminirane bajt-stringove.
Vrijedi klasificirati ovisnosti: koja biblioteka je Unicode-ready, koja nije i koja se može zamijeniti ili enkapsulirati? Enkapsulacija je često najbrži put da se Unicode-legacy ograniči na jasno definiranu zonu.
Strategija: Unicode-migracija starih Delphi-projekata kao kontrolisani program modernizacije
Najjača migraciona procedura je višestupanjski program koji rizike čini vidljivima rano i drži aplikaciju u radu.
Korak 1: Definisati scope i prioritizovati kod-hotspote
Nije svaki izvorni kod odmah za prilagodbu. Prioritizirajte prema protoku podataka i riziku:
- Interfejsi prema van (REST-API, TCP/IP, fajlovi, e-mail, štampa/reporting).
- Pristup podacima (SQL, ORM/Datamodule, BDE/FireDAC-slojevi).
- String-bliske utility-funkcije (parseri, formatteri, encoder/decoderi).
- Integracije (COM, DLL-importi, priključci na hardver).
Rezultat treba biti lista mjesta gdje „encoding ima specifikaciju“. Ta mjesta će kasnije postati testabilna.
Korak 2: Svjesno oštrije postaviti compiler-/projekt-opcije i upozorenja
U mnogim projektima su upozorenja godinama isključena. Za Unicode-migraciju je to kontraproduktivno. Podesite upozorenja ponovo i shvatite konverzijska upozorenja ozbiljno. Također pomaže definirati projektno pravilo, npr.: nema implicitnih AnsiString-konverzija na I/O-granicama, upotreba TEncoding pri fajl-operacijama, bez „PChar-trikova“ bez jasnog konteksta.
Korak 3: Uvesti „granice enkodiranja“ kao tehnički sloj
Praktičan arhitektonski pristup je uvođenje malih adaptera/helper-a koji precizno određuju kako vanjski podaci ulaze i izlaze. Primjeri:
- CSV-reader/-writer: uvijek s TEncoding.UTF8 (ili definiranim codepage-om) i jasnim pravilima o separatorima.
- REST-klijent/server: JSON uvijek kao UTF-8 bajtovi, headeri pravilno postavljeni, body ne streamovati „string-based“.
- Windows-API-wrapper: centralne funkcije koje Wide/Ansi čisto enkapsuliraju.
Time sprječavate da se „odlučivanja o encodingu“ razliju po cijeloj bazi koda.
Tipične kod-pandreke i kako ih uredno popraviti
Length, SizeOf, ByteLength: kada se broj znakova i broj bajtova razilaze
U ANSI-vremenima se Length(s) često zloupotrebljavao kao broj bajtova. U UTF-16 je to netačno. Ako trebate bajt-niz, eksplicitno konvertujte:
- Za UTF-8: TEncoding.UTF8.GetBytes(s)
- Za definiranu ANSI-codepage: TEncoding.GetEncoding(1252).GetBytes(s) (samo ako je strogo ispravno iz domene)
Za veličine buffera kod API-poziva provjerite očekuje li funkcija jedinice znakova ili bajtova. Mnogi Wide-API-ji očekuju broj znakova, ne bajtova. Dokumentacija i potpis funkcije odlučuju, a ne intuicija.
PAnsiChar vs. PWideChar: DLL-importi i eksterni protokoli
Prilikom DLL-importa postoji visok rizik da potpisi u Delphi-kodu više ne odgovaraju. Odredite što DLL očekuje:
- Očekuje li DLL UTF-8? Tada je uobičajeno proslijediti PAnsiChar(UTF8String), ali morate kontrolisati životni vijek i null-terminaciju.
- Očekuje li UTF-16? Tada koristite PWideChar i Wide-stringove.
U svakom slučaju import-e držite u zasebnoj unitu, da se politika stringova ne rasprši po cijelom projektu.
Formatiranje, promjena veličine slova, poređenje: lokalitet i normalizacija
Unicode donosi i semantičke teme: upper/lowercase nije trivijalno u svim jezicima, a znakovi mogu imati različite normalne forme. U tipičnim enterprise-aplikacijama to je manje kritično nego u obradi tekstova za korisnike, ali pogađa:
- sortiranje i filtriranje (npr. u gridovima ili pretragama),
- case-insensitive usporedbe za ključne vrijednosti,
- generisanje imena fajlova ili identifikatora.
Važno je imati jasnu politiku: šta su „ključevi“ (npr. šifre artikala, kodovi kupaca) koji bi trebali ostati ASCII-niski, a šta su „teksti“ koji moraju biti u potpunosti Unicode-kompatibilni? Ta podjela smanjuje kasnije greške.
GUI/Reporting: fontovi, štampa, PDF i ponašanje komponenti
VCL je od Unicode-verzija principijelno Unicode-spreman, ali praksa ovisi o komponentama i izlaznim putem. Rizici nastaju kod:
- starijih report-engine-a ili PDF-generatora koji prihvataju ANSI,
- barcode/label-štampe koja zahtijeva određene codepage-e,
- hardcodiranih fontova ili setova znakova.
Planirajte rano testove s realnim primjerima podataka (imena, mjesta, posebni znakovi, ne-latinična pisma ako su relevantna). Vrijednost je manje u „može Unicode“, a više u dokazivanju: „Ovaj izlaz je u našem kontekstu ispravan.“
Podaci i persistencija: Unicode ne završava u kodu
Ispravno definirati charset-e i collation-e u bazama
Unicode-migracija je stabilna samo ako su baze podataka i drajveri pravilno konfigurirani. Primjeri:
- Za PostgreSQL je UTF-8 obično standard; ipak treba provjeriti client-encoding i ponašanje drajvera.
- Za SQL Server je razlika između VARCHAR i NVARCHAR relevantna; krivi tip kolone može dovesti do gubitka znakova.
- Za MariaDB/MySQL su charset/collation (npr. utf8mb4) presudni da 4-bajtni znakovi ne budu odrezani.
U Delphi-kodu koristite parametre i tipove polja tako da se Unicode ne „vrati“ u neku konverziju na putu. FireDAC obično nudi bolju kontrolu od vrlo starih pristupnih slojeva.
Legacy-fajlformati: pravila migracije umjesto tihih konverzija
Ako vaša aplikacija godinama proizvodi fajlove (export formati, arhivske datoteke, proprietarne strukture), morate definirati:
- Koje postojeće fajlove ostavljate „kako jesu“ i kako će se pri čitanju ispravno interpretirati?
- Koje formate podižete na UTF-8?
- Postoje li polja/hederi verzije da se novi i stari fajlovi jasno razlikuju?
Tiha konverzija bez oznake je rizična jer se greške najčešće pokažu kasno. Bolje: verzionirati, jasno detektovati i ciljano migrirati.
Osiguranje kvalitete: testovi koji zaista nalaze Unicode-probleme
Unicode-greške su često ovisne o podacima. Zato „happy path“ testovi nisu dovoljni. Korisno je testset koji pokriva problematična mjesta:
- Roundtrip-testovi: import → obrada → export, nakon toga bajt-na-bajt poređenje (kod definiranih formata).
- DB-roundtrip: zapis/čitanje tekstova s umlautima, akcentima i po potrebi ne-latiničnim znakovima; provjera jednakosti.
- Interfejs-testovi: REST-requesti kao UTF-8, headeri, JSON-escaping, logging.
- Regresija: reproducirati stare podatke i tipične korisničke scenarije, posebno pri pretraživanju, filtriranju, sortiranju.
Za B2B-sisteme je također važno da su greške uočljive: logging ne smije uništavati kodiranje. Ako logove zapisujete kao ANSI, u slučaju greške izgubite upravo informacije koje su vam potrebne.
Planiranje i napor: šta zaista povećava složenost
Napor Unicode-migracije starih Delphi-projekata manje zavisi od „broja linija koda“, a više od sprega i vanjskih ovisnosti:
- Mnoštvo integracija (DLL-i, COM, uređaji, ERP/DMS/CRM) povećava opseg provjera jer je na svakoj granici važno provjeriti encoding.
- Historijski formati (stari exporti, klijentski CSV-ovi) zahtijevaju pravila migracije i strategije kompatibilnosti.
- Pomiješane Delphi-verzije ili više proizvoda iz istog kodnog stabla povećavaju koordinacijski trošak.
- Stari slojevi za pristup podacima (npr. BDE) mogu indirektno blokirati Unicode i upućuju na potrebu modernizacije.
U praksi se pokazao pristup koji prvo stabilizira Unicode u jezgru i u kritičnim tokovima podataka. Nakon toga se modularno nadograđuju ostali dijelovi. To smanjuje rizik i izbjegava duge „big bang“ faze bez releasa.
Usklađivanje s modernizacijskim putevima: REST, servisi, multiplatforma
Unicode je često temelj kad se postojeći softver želi modernizirati. Tipična pitanja koja slijede su:
- REST-server ili REST-API dodati (JSON/UTF-8 pravilno tretirati).
- Stabilno upravljanje Windows-servisima ili Linux-servisima (logging, konfiguracijski fajlovi, protokoli).
- Postepena modernizacija UI-ja u VCL, kasnije eventualno multiplatform klijenti.
Bitan je redoslijed: kad gradite nove interfejse, pravila o encodingu trebaju biti unaprijed definirana. Unicode-migracija „usput“ tokom razvoja interfejsa stvara teško testabilne greške jer se uzrok i posljedica pomiješaju.
Za internu poveznicu u magazinu prikladno je postaviti povezane teme kao što su Delphi-modernizacija, FireDAC-pristup podacima ili arhitektura REST-servera kao produbljujuće članke, tako da čitaoci mogu direktno nastaviti na sljedeći tehnički korak.
Zaključak: Unicode-migracija je pitanje rizika – uz pravu metodu postaje planabilna
Unicode-migracija starih Delphi-projekata nije kozmetički update, nego ispravka temeljnih pretpostavki o tekstu, bajtovima i interfejsima. Onaj koji postupa strukturirano ipak dobije više od „ponovno rade umlauti“: tokovi podataka postaju jasniji, integracije robusnije, a kasnija modernizacija (npr. REST-serveri, servisi, čišćenje baza) jednostavnija, jer se kodiranja više ne odvijaju implicitno „negdje“.
Ako za vašu Delphi-aplikaciju trebate konkretan plan migracije, analizu rizika hotspota ili podršku pri implementaciji, najbrži sljedeći korak je tehnički inicijalni razgovor o vašim okvirima i ovisnostima: Kontakt aufnehmen.
U stručnom kontekstu Delphi Unicode Migration i Delphi Ansi Zu Unicode također igraju važnu ulogu kad integracije, tokovi podataka i dalji razvoj trebaju funkcionisati zajedno.
Projekt oder Modernisierungsvorhaben mit Net-Base besprechen.