Net-Base Žurnāls

19.04.2026

Unicode migrācija veciem Delphi projektiem: klupšanas akmeņi, stratēģija un tīra īstenošana

Daudzas Delphi esošās lietojumprogrammas joprojām izmanto ANSI virknes. Unicode migrācija tāpēc ir vairāk nekā tikai kompilatora slēdzis — tā skar datu piekļuvi, saskarnes, atskaites, trešo pušu bibliotēkas un testēšanu. Šajā rakstā parādīts praktiski izmantojams migrācijas ceļš — iesk...

19.04.2026

Unicode migrācija vecajos Delphi-projektos ir daudzos uzņēmumos nepieciešams solis, jo esošās lietojumprogrammas citā starptautisku datu, modernu operētājsistēmu, integrāciju un jaunu saskarnu vidē citādi arvien vairāk sasniedz robežas. Praktiskā izpildē tas reti ir „pārsakompilēt un gatavs”. Delphi kopš Unicode ieviešanas (kopš Delphi 2009) ir veikusi fundamentālas izmaiņas standarta virkņu tipos. Tas pārbīda pieņēmumus par rakstzīmju kodējumu, atmiņas izkārtojumu un API parakstiem. Kas šo novērtē par zemu, rada lēni attīstās datu kļūdas, bojātus eksportus, neskaidrus atbalsta gadījumus un drošības riskus.

Šis raksts sniedz tehniski pamatotu darba gaitu: kā analizēt esošo kodu, saprātīgi sadalīt apjomu, samazināt riskus karstajos punktos (datubāzes, faili, Windows-API, COM, REST-servisi) un nodrošināt migrāciju tā, lai ekspluatācija un turpmāka izstrāde varētu notikt paralēli. Fokusā ir Delphi-tipiskas ķecerības VCL lietojumprogrammās, servisos un saskarnēs — ar redzējumu par modernizācijas ceļiem, kuros vēlāk var integrēt tādas tēmas kā BDE-nomaiņa ar natīvu pieslēgumu, REST-serveri vai multiplatformu risinājumus.

Kāpēc Unicode pāreja Delphi bieži ir „lielāka nekā gaidīts”

Klasiskajās Delphi versijās string bija ANSI-virkne (atkarībā no sistēmkodlapas). Kopš Delphi 2009 string pēc noklusējuma ir UnicodeString (UTF-16). Vienlaikus daudzas bibliotēkas un VCL-klases tika pārvietotas uz Wide-API. Tas pamatā ir pozitīvi, jo starptautiskas rakstzīmes tiek atbalstītas robusti. Bet: cilvēciskais legacy kods bieži ir būvēts uz pieņēmumiem „1 rakstzīme = 1 baits”, „PChar ir PAnsiChar” vai „Length() atbilst baitu skaitam”.

Tipiskie iemesli, kāpēc migrācijas kļūst apjomīgākas:

  • Implicitas konversijas var notikt, bet mainīt datus (īpaši failu, saskarnu vai datubāzu BLOB/tekstu laukos).
  • Paita orientēts kods (Streams, buferi, hashing, šifrēšana) kļūst nemanāmi neparezs, ja virkņu saturu interpretē kā baitus.
  • Trešās puses komponentes dažkārt ir tikai ANSI vai izmanto savus virkņu tipus un callback’us.
  • Ārējā vide (Windows-API, COM, drukāšana/raporti, EDI, CSV, XML/JSON) sagaida konkrētas kodēšanas.

Tāpēc mērķim nevajadzētu būt „izmainīt pēc iespējas mazāk”, bet gan mērķtiecīgi mainīt tur, kur jādefinē datu plūsmas un kodējumi. Kārtīga Unicode migrācija ir arī iespēja beidzot dokumentēt un testēt neskaidras kodējuma robežas.

Tehniskie pamati: Delphi virkņu tipi, kodējumi un to blaknes

string, UnicodeString, AnsiString, WideString – kas projektā tiešām ir svarīgs

Migrācijā ir izšķiroši, kuri tipi tiek izmantoti saskarnēs un kodola funkcijās:

  • string: kopš Delphi 2009 tas ir UnicodeString (UTF-16, ar reference-counting, Copy-on-Write uzvedība).
  • AnsiString: baitu virkne ar pievienotu kodlapu (atkarībā no Delphi versijas var tikt glabāta kodlapa). Izmantojams, ja ārējā saskarne explicit prasa noteiktu 8-bitu kodējumu.
  • UTF8String: jaunākās Delphi versijās bieži kā alias/AnsiString ar UTF-8 kodlapu; praktiski piemērots REST/JSON un daudzām protokolu implementācijām.
  • WideString: BSTR (COM), atmiņas pārvaldīts ar SysAllocString; šodien parasti nepieciešams tikai specifiskām COM interop situācijām.
  • PChar: kopš Unicode-Delphi tas ir PWideChar. Tas ir viens no biežākajiem šķērsliem ar Windows API izsaukumiem.

Ja šie tipi tiek miksēti, rodas konversijas. Dažas no tām ir pareizas, citas pārsteidzošas: konversija ir „pareiza” tikai tad, ja zināt, kura kodlapa ir avotā un kura tiek sagaidīta mērķī.

Interni UTF-16, eksterneri UTF-8: praktisks vadlīniju modelis

VCL lietojumprogrammās bieži pieņemts iekšēji konsekventi strādāt ar string (UTF-16). Ārā (REST, faili, ziņapmaiņa) realitātē dominē UTF-8. Robusta pieeja ir šāda:

  • Interni: string/UnicodeString kā standarts.
  • Robežas: Ieejā/izejā explicit konvertēt ar TEncoding.UTF8 (vai definētām ANSI kodlapām).
  • Baitu apstrāde: TBytes vietā string.

Tas samazina implicitas konversijas un padara atbildības pārbaudāmas: „Kur no baitiem rodas teksts, un ar kādu kodējumu?”

Inventarizācija: kur Unicode vecajos Delphi projektos parasti salūzt

Pirms ķerties pie koda, ir vērts veikt strukturētu inventarizāciju. Unicode migrācijā kļūdu avoti parasti nav vienmērīgi sadalīti, bet sakoncentrējas dažos karstos punktos.

1) Datubāzu piekļuve un lauku tipi (BDE, ADO, FireDAC)

Daudzi vecie projekti joprojām izmanto BDE vai vēl vecākas datu piekļuves kārtis. Šeit bieži sastopamie problēmu gadījumi:

  • Datubāzes rakstzīmju kopu piesaiste Delphi virknei (ANSI vs. Unicode lauki).
  • „Teksts” BLOBos vai Memo laukos bez definēta kodējuma.
  • SQL vaicājumi kā virknes, kas ar treknrakstu/unicode simboliem var tikt interpretēti atšķirīgi.

Ja tāpat tiek plānota modernizācija, Unicode migrāciju ir izdevīgi kombinēt ar datu piekļuves sakārtošanu, piemēram, virzienā uz BDE-Ablosung mit nativer Anbindung un skaidru charset konfigurāciju (piemēram, PostgreSQL vai MariaDB). Svarīgi: migrācija nedrīkst automātiski nozīmēt datubāzes migrāciju, bet saskarne starp DB un Delphi jānosaka viennozīmīgi.

2) Failu un plūsmu I/O: CSV, INI, proprietāri formāti, imports/eksports

Klasika: faili agrāk tika lasīti/rakstīti ar AssignFile/ReadLn, TFileStream vai TStringList.LoadFromFile bez kodējuma norādes. Unicode Delphi tad heuristiski (BOM) vai pēc noklusējuma izvēlas kodējumu. Tas noved pie:

  • nepareizi interpretētiem umlautiem (ä, ö) CSV/log failos,
  • nepareizām garumu norādēm proprietāros formātos,
  • inkompatibilitātēm ar ārējiem partneriem, kas sagaida ISO-8859-1 vai Windows-1252.

Kārtīgs risinājums ir katram failu formātam definēt fiksētu kodējumu un to nostiprināt kodā un dokumentācijā. CSV/JSON gadījumā parasti pareizais standarts ir UTF-8; vecām saskarnēm reizēm Windows-1252. Izšķirošais ir explicititāte.

3) Windows-API, PChar, bufera izmēri un ziņu apstrāde

Daudzas Delphi lietojumprogrammas izsauc WinAPI funkcijas vai strādā ar buferiem. Biežie šķēršļi:

  • PChar lietojums kopā ar funkcijām, kurām ir ANSI vai Wide varianti (…A/…W).
  • Bufera izmēri aprēķināti baitos, bet Char UTF-16 gadījumā ir 2 baiti.
  • Pointer aritmētika un ierakstu izkārtojumi, kas balstīti uz 1-baita char.

Šeit nepieciešams precīzs refaktoring: vai nu konsekventi lietot Wide-API, vai apzināti izsaukt ANSI variantu un strādāt ar AnsiString/kodlapu. „Kaut kā nokompilē” nav kvalitātes kritērijs.

4) COM, ActiveX, Office-Automation un trešās puses bibliotēkas

COM interfeisi bieži strādā ar BSTR (WideString). Vecākās Delphi versijas bija ar citiem noklusējuma string tipiem, tāpēc kods „gadījuma pēc” darbojās. Unicode-Delphi vidē bieži rodas dubultas konversijas vai nepareizi tipu pieņēmumi wrapper’os. Trešo pušu bibliotēkas arī ir kritiskas: dažas piegādā callback’us kā PAnsiChar, citas sagaida null-terminētus baitu virknes.

Šeit ir vērts klasificēt atkarības: kura bibliotēka ir Unicode-ready, kura nav un kura var tikt aizvietota vai kapsulēta? Kapsulēšana bieži ir ātrākais veids, kā migrācijas parazītus novirzīt uz skaidri definētu zonu.

Stratēģija: Unicode migrācija veciem Delphi projektiem kā kontrolēts modernizācijas programmas elements

Visrisku migrācijas pieeju nodrošina daudzpakāpju programma, kas agrīni padara riskus redzamus un saglabā lietojumprogrammas darbošanos.

Solis 1: definēt apjomu un prioritizēt koda karstos punktus

Nevajag visam avota kodam uzreiz pielāgoties. Prioritizējiet pēc datu plūsmas un riska:

  • Saskarnes uz āru (REST-API, TCP/IP, faili, e-pasts, drukāšana/raporti).
  • Datu piekļuve (SQL, ORM/Datamodule, BDE/FireDAC slāņi).
  • Ar virkni saistītas utilītu funkcijas (parseri, formatētāji, encoder/decoder).
  • Integrācijas (COM, DLL-Imports, aparatūras pieslēgumi).

Rezultātam jābūt sarakstam ar vietām, kur „kodējums ir specifikācija”. Šīs vietas vēlāk tiks izveidotas kā testējamas.

Solis 2: kompilatora/projekta opcijas un brīdinājumi skaidri aktivizēt

Daudzos projektos brīdinājumi gadu gaitā tika atslēgti. Unicode migrācijā tas ir kontraproduktīvi. Iesakām brīdinājumus ieslēgt un konversiju brīdinājumus uztvert nopietni. Papildus ir jēga projektā noteikt līmeņus, piemēram: nav implicitu AnsiString konversiju I/O robežās, TEncoding lietošana failu operācijās, nav “PChar triku” bez skaidra konteksta.

Solis 3: ieviest “kodējuma robežas” kā tehnisku slāni

Praktisks arhitektūras paņēmiens ir mazu adapteru/helper’u ieviešana, kas precīzi definē, kā ārējie dati ieplūst un izplūst. Piemēri:

  • CSV lasītājs/ierakstītājs: vienmēr ar TEncoding.UTF8 (vai definēta kodlapa) un skaidrām separatoru politikām.
  • REST klients/serveris: JSON vienmēr kā UTF-8 baitu plūsma, pareiza header uzstādīšana, body neslēgt kā ‘‘stringbāzētu’’ plūsmu.
  • Windows-API wrapperis: centrālas funkcijas, kas Wide/Ansi tīri kapsulē.

Tā jūs novēršat, ka „kodējuma lēmumi” tiek izkaisīti pa visu koda bāzi.

Tipiskas koda slazdi un kā tos sakārtot

Length, SizeOf, ByteLength: kad rakstzīmju garums un baitu izmērs nesakrīt

ANSI laikos Length(s) bieži tika ļaunprātīgi lietots kā baitu skaits. UTF-16 tas ir nepareizi. Ja nepieciešami baitu masīvi, konvertējiet explicit:

  • UTF-8 gadījumā: TEncoding.UTF8.GetBytes(s)
  • Definētas ANSI kodlapes gadījumā: TEncoding.GetEncoding(1252).GetBytes(s) (tikai ja tas ir lietišķi pamatoti)

API izsaukumiem attiecībā uz bufera izmēriem: pārbaudiet, vai funkcija sagaida rakstzīmes vai baitus. Daudzas Wide-API gaida rakstzīmju skaitu, nevis baitus. Dokumentācija un paraksts nosaka, nevis intuīcija.

PAnsiChar vs. PWideChar: DLL-Imports un ārēji protokoli

DLL importos pastāv liels risks, ka paraksti Delphi kodā vairs nesakrīt. Nosakiet, ko DLL sagaida:

  • Ja DLL sagaida UTF-8, tad parasti nodošana kā PAnsiChar(UTF8String), bet jākontrolē dzīves ilgums un null-terminācija.
  • Ja tā sagaida UTF-16, tad lietojiet PWideChar un Wide-virknes.

Importus ieteicams kapsulēt atsevišķā unitā, lai virkņu politika neizplūstu pa visu projektu.

Formatēšana, lielumu maiņa, salīdzināšana: lokalizācija un normalizācija

Unicode nes arī semantiskas tēmas: lielo/mazo burtu pārveidošana nav vienkārša visās valodās, un rakstzīmes var eksistēt dažādās normalizācijas formās. Tipiskās uzņēmuma lietojumprogrammās tas ir mazāk kritiski nekā patērētāju tekstapstrādē, bet tas ietekmē:

  • kārtošanu un filtrāciju (piem., Gridos vai meklēšanā),
  • case-insensitive salīdzinājumus atslēgvērtībām,
  • failu nosaukumu vai identifikatoru ģenerēšanu.

Svarīgi noteikt skaidru politiku: kas ir „atslēgas” (piem., artikula numuri, klientu kodi), kas drīkst palikt ASCII tuvumā, un kas ir „teksti”, kas jāpadara pilnībā Unicode-spējīgi? Šī šķirošana samazina turpmākās kļūdas.

GUI/raporti: fonti, drukāšana, PDF un komponenšu uzvedība

VCL kopš Unicode versijām vispārēji atbalsta Unicode, taču prakse ir atkarīga no komponentēm un izvadceļiem. Riska avoti:

  • vecākas report-engines vai PDF ģeneratori, kas pieņem ANSI,
  • svītrkodu/etikešu drukāšana, kas prasa noteiktas kodlapes,
  • cieti kodēti fonti vai rakstzīmju kopas.

Plānojiet agrīnas pārbaudes ar reāliem piemēra datiem (vārdi, vietas, speciālās zīmes, nelatīņu rakstības, ja tās ir relevantas). Svarīgākais nav tikai tas, ka „var Unicode”, bet pierādījums: „Šis izvada pareizi mūsu kontekstā.”

Dati un persistēšana: Unicode nebeidzas ar kodu

Datubāzu charsets un collations pareizi noteikt

Unicode migrācija ir stabila tikai tad, ja datubāzes un draiveri ir pareizi konfigurēti. Piemēri:

  • Pie PostgreSQL UTF-8 parasti ir noklusējums; tomēr klienta-encoding un draivera uzvedību jāpārbauda.
  • Pie SQL Server atšķirība starp VARCHAR un NVARCHAR ir būtiska; nepareiza kolonnu izvēle var izraisīt rakstzīmju zudumu.
  • Pie MariaDB/MySQL charset/collation (piem., utf8mb4) ir izšķirošs, lai 4-baitu rakstzīmes netiktu nogrieztas.

Delphi kodā parametrus un lauku tipus jālieto tā, lai Unicode netiktu netīši „atpakaļkonvertēts“. FireDAC parasti nodrošina labāku kontroli nekā ļoti vecas piekļuves slāņi.

Legacy failu formāti: migrācijas noteikumi, nevis klusā konversija

Ja jūsu lietojumprogramma gadu gaitā ir radījusi failus (eksporti, arhīvi, proprietāras struktūras), jums jādefinē:

  • kuri esošie faili paliek „kā līdz šim“ un tiks lasīti ar pareizu interpretāciju?
  • kuri formāti tiks pacelti uz UTF-8?
  • vai ir versijas lauki/headeri, lai jaunus un vecus failus varētu viennozīmīgi atšķirt?

Klusā konvertācija bez marķēšanas ir riskanta, jo kļūdas bieži atklājas tikai vēlāk. Labāk: versionēt, skaidri atpazīt un mērķtiecīgi migrēt.

Kvalitātes nodrošināšana: testi, kas patiesi atrod Unicode problēmas

Unicode kļūdas bieži ir datu atkarīgas. Tāpēc „happy path“ testi nav pietiekami. Lietderīgs testa komplekts aptver problemātiskās vietas:

  • Roundtrip testi: importēšana → apstrāde → eksports, pēc tam baitu-precīza salīdzināšana (ja formāts ir definēts).
  • DB-Roundtrip: rakstīt/lasīt tekstus ar umlautiem, akcentiem un, nepieciešamības gadījumā, nelatīņu rakstzīmēm; pārbaudīt ekvivalenci.
  • Saskarnes testi: REST requesti kā UTF-8, headeri, JSON-escaping, logging.
  • Regresijas: vecie dati un tipiski lietotāju gadījumi, īpaši meklēšana, filtrēšana, kārtošana.

B2B sistēmām ir svarīgi, lai kļūdas būtu novērojamas: logging nedrīkst iznīcināt kodējumu. Ja žurnāli tiek rakstīti ANSI, tie kļūst bezvērtīgi, kad vajadzīga diagnostika.

Plānošana un apjoms: kas patiesībā palielina sarežģītību

Unicode migrācijas apjoms vecos Delphi projektos mazāk ir atkarīgs no koda rindiņu skaita, vairāk no sasaistes un ārējām atkarībām:

  • Daudzas integrācijas (DLLs, COM, ierīces, ERP/DMS/CRM) palielina pārbaudīšanas apjomu, jo kodējumi ir nozīmīgi katrā robežā.
  • Vēsturiskie formāti (vecie eksporta formāti, klientu specifiski CSV) prasa migrācijas noteikumus un saderības stratēģijas.
  • Jaukta Delphi versiju vide vai vairāki produkti no viena koda bāzes palielina koordinācijas nepieciešamību.
  • Vecie datu piekļuves slāņi (piem., BDE) var netieši bloķēt Unicode un ieteikt modernizāciju.

Praksē der pieeja, kur Unicode vispirms stabilizē kodolā un kritiskākajās datu plūsmās. Pēc tam pakāpeniski migrē pārējos moduļus. Tas samazina risku un izvairās no ilgām „Big Bang“ fāzēm bez release.

Iekļaušana modernizācijas ceļos: REST-API, servisi, multiplatform

Unicode bieži ir pamatpriekšnoteikums, ja esošā programmatūra jāmodernizē. Tipiskie nākamie soļi:

  • REST-servera vai REST-API izveide (JSON/UTF-8 pareiza apstrāde).
  • Windows-servisu vai Linux-servisu stabila ekspluatācija (logging, konfigurācijas faili, protokoli).
  • Pakāpeniska UI modernizācija VCL, vēlāk iespējami multiplatform klienti.

Svarīga ir kārtība: ja veidojat jaunas saskarnes, kodējuma noteikumi jānosedz pirms tam. Unicode migrācija „pa ceļam” saskarnes izstrādes laikā radīs grūti pārbaudāmas kļūdas, jo cēlonis un sekas tiks sajauktas.

Iekšējai saitei magazīnā ir ieteicams sasaistīt līdzīgas tēmas kā Delphi modernizācija, FireDAC datu piekļuve vai REST serveru arhitektūra kā padziļinātas lasāmvielas, lai lasītājs varētu mērķtiecīgi turpināt tehnisko soli.

Sekojums: Unicode migrācija ir riska tēma — ar pareizu metodi to var padarīt plānojamu

Unicode migrācija vecos Delphi projektos nav kosmētisks uzlabojums, bet korekcija fundamentāliem pieņēmumiem par tekstu, baitu apstrādi un saskarnēm. Strukturēti rīkojoties, iegūstat vairāk nekā „umlauti atkal strādā“: datu plūsmas kļūst viennozīmīgākas, integrācijas robustākas, un turpmāka modernizācija (piem., REST serveri, servisi, datubāzes sakārtošana) kļūst vienkāršāka, jo kodējumi vairs nenotiek implicitā veidā „kur nu kurais“.

Ja jums nepieciešams konkrēts migrācijas plāns jūsu Delphi lietojumprogrammai, risku analīze karstajos punktos vai atbalsts ieviešanā, ātrākais nākamais solis ir tehniska sākotnējā saruna par jūsu vides apstākļiem un atkarībām: sazinieties ar mums.

Fachlich kontekstā spēlē lomu arī Delphi Unicode Migration un Delphi Ansi Zu Unicode, ja integrācijas, datu plūsmas un turpmākā izstrāde ir jāsasniedz kopā.

Projektu vai modernizācijas plānu apspriest ar Net-Base.

Kopīgot ierakstu

Kopīgot šo ierakstu tieši

LinkedIn, X, XING, Facebook, WhatsApp un e-pasts ir uzreiz pieejami. Instagramam saiti un īsu tekstu sagatavosim nekavējoties.

E-pasts

Instagram atveras jaunā cilnē. Saite un īss teksts tiek iepriekš nokopēti starpliktuvē.