Den Unicode-migrasjonen av gamle Delphi-prosjekta er i mange verksemder eit nødvendig grep, fordi eksisterande applikasjonar elles kjem til kort ved internasjonale data, moderne operativsystem, integrasjonar og nye grensesnitt. I praksis er det sjeldan eit «recompile og ferdig». Delphi har med Unicode-versjonane (frå Delphi 2009) gjort fundamentale endringar i standard string-typar. Det endrar føresetnader for teiknkoding, minnelayout og API-signaturar. Den som undervurderer dette, skapar snikande datafeil, øydelagde eksportar, uklåre supporttilfelle og tryggleiksrisikoar.
Denne artikkelen gir ei fagleg forankra framgangsmåte: Korleis du analyserer eksisterande kode, avgrensar scope fornuftig, reduserer risiko ved hot-spot (databasar, filer, Windows-API-ar, COM, REST-tenester) og sikrar migrasjonen slik at drift og vidareutvikling kan halde fram parallelt. Fokus er på Delphi-typiske fallgruver i VCL-applikasjonar, tenester og grensesnitt – med blikk mot moderniseringsvegar der tema som BDE-avløysing med nativer binding, REST-server eller multiplattform seinare kan plasserast.
Kvifor Unicode-omstillinga i Delphi så ofte er «større enn venta»
I klassiske Delphi-versjonar var string ein ANSI-string (avhengig av systemcodepage). Sidan Delphi 2009 er string som standard ein UnicodeString (UTF-16). Samstundes vart mange bibliotek og VCL-klassar bytte til Wide-API-ar. Det er grunnleggjande positivt, fordi det gir robust støtte for internasjonale teikn. Men: Legacy-kode er ofte bygd opp over år kring føresetnader som «1 teikn = 1 byte», «PChar er PAnsiChar» eller «Length() svarer til byte-tal».
Typiske årsaker til at migrasjonar blir meir arbeidskrevjande:
- Implisitte konverteringar går gjerne gjennom, men endrar data (særleg ved filer, grensesnitt eller database-blob/text-felt).
- Byte-orientert kode (streams, buffer, hashing, kryptering) blir utan å merke det feil når string-innhald blir tolka som rå byte.
- Tredjepartskomponentar er delvis ANSI-only, eller brukar eigne string-typar og callbacks.
- Eksternt miljø (Windows-API-ar, COM, utskrift/reporting, EDI, CSV, XML/JSON) forventar bestemte encodings.
Målet bør difor ikkje vere «så lite som mogleg endra», men målretta endringar der dataflyt og encodingar må definerast. Ein ryddig Unicode-migrasjon er også ein sjanse til endeleg å dokumentere og teste uklare kodingsgrensar.
Tekniske grunnprinsipp: Delphi-stringtypar, encodingar og sideverknader
string, UnicodeString, AnsiString, WideString – kva som faktisk tel i prosjektet
For migrasjonen er det avgjerande kva typar som blir brukt på grensesnitt og i kjernefunksjonar:
- string: Sidan Delphi 2009 ein UnicodeString (UTF-16, reference-counted, immutable-semantikk via Copy-on-Write).
- AnsiString: Byte-string med tilordnet codepage (avhengig av Delphi-versjon kan ein codepage vere lagra). Eigna når ei ekstern grensesnitt eksplisitt krev ei bestemt 8-bit-kodning.
- UTF8String: I nyare Delphi-versjonar ofte alias/AnsiString med UTF-8-codepage; praktisk for REST/JSON og mange protokollar.
- WideString: BSTR (COM), minnehandsama via SysAllocString; i dag som oftast berre naudsynt for bestemte COM-interops.
- PChar: I Unicode-Delphi er dette PWideChar. Dette er ein av dei vanlegaste brotflata ved Windows-API-kall.
Dersom desse typane blir blanda, oppstår konverteringar. Nokre er riktige, andre overraskande: Ein konvertering er berre «riktig» når du veit kva codepage kjelda har og kva målet forventar.
UTF-16 internt, UTF-8 eksternt: eit praktisk retningslinje
I Delphi-VCL-applikasjonar er det ofte hensiktsmessig å jobbe konsekvent internt med string (UTF-16). Eksternt (REST, filer, messaging) dominerer i praksis UTF-8. Ei robust retningslinje er derfor:
- Internt: string/UnicodeString som standard.
- Grenser: Ved inn-/utgang konverterast eksplisitt via TEncoding.UTF8 (eller definerte ANSI-codepage).
- Byte-basert handsaming: TBytes i staden for strings.
Dette reduserer implisitte konverteringar og gjer ansvarsforhold testerbare: «Kor blir bytes til tekst, og med kva encoding?»
Bestandsoppteljing: Kor Unicode i gamle Delphi-prosjekt typisk bryt
Før du rører koden, lønner det seg med ei strukturert inventur. I Unicode-migrasjon av gamle Delphi-prosjekt er feilkjeldene oftast ikkje jamt fordelt, men konsentrerte rundt enkelte hot-spot.
1) Database-tilgang og felttypar (BDE, ADO, FireDAC)
Mange gamle prosjekt brukar framleis BDE eller eldre datatilgangslag. Her oppstår ofte desse problema:
- Kartlegging av database-charsets til Delphi-strings (ANSI vs. Unicode-felttypar).
- «Tekst» i BLOBs eller Memo-felt utan definert koding.
- SQL-statement som strings, der umlaut/Unicode-teikn blir tolka ulikt.
Dersom modernisering ligg i korta, kan ein Unicode-migrasjon godt kombinerast med rydding i datatilgangen, t.d. mot BDE-Ablosung mit nativer Anbindung og tydeleg charset-konfigurasjon (som ved PostgreSQL eller MariaDB). Viktig: Ein migrasjon bør ikkje automatisk tvinge ein database-migrasjon, men grensesnittet mellom DB og Delphi må vere eintydig.
2) Fil- og stream-I/O: CSV, INI, proprietære format, import/eksport
Eit klassisk tilfelle: Tidlegare vart filer lese/skrive med AssignFile/ReadLn, TFileStream eller TStringList.LoadFromFile utan å setje encoding. I Unicode-Delphi avgjer då miljøet heuristisk (BOM) eller brukar default-encodingar. Det fører til:
- feiltolka umlaut (ä, ö) i CSV/loggfiler,
- feil i lengdeoppgivingar i proprietære format,
- inkompatibilitetar mot eksterne partnarar som forventar ISO-8859-1 eller Windows-1252.
Ei ryddig løysing er å definere eit fast encoding per filformat og forankre dette i kode og dokumentasjon. For CSV/JSON er UTF-8 som oftast rett standard, for gamle grensesnitt kan Windows-1252 vere naudsynt. Det avgjerande er eksplisittheit.
3) Windows-API, PChar, buffertstorleikar og meldinghandsaming
Mange Delphi-applikasjonar kallar WinAPI-funksjonar eller jobbar med bufferar. Vanlege brotpunkt:
- Bruk av PChar saman med funksjonar som har ANSI- eller Wide-variasjonar (…A/…W).
- Buffertstorleikar rekna i byte, men Char i UTF-16 er 2 byte.
- Pointer-aritmetikk og record-layout som byggjer på 1-byte-chars.
Her krevst eit presist refaktorering: anten konsekvent bruka Wide-API-ar eller medvite kalle ANSI-varianten og handsame med AnsiString/codepage. «Det kompilerer på ein eller annan måte» er ikkje eit kvalitetskriterium.
4) COM, ActiveX, Office-automatisering og tredjepartsbibliotek
COM-interface brukar ofte BSTR (WideString). Gamle Delphi-versjonar hadde andre default-strings, slik at kode «tilfeldigvis» passa. I Unicode-Delphi oppstår ofte doble konverteringar eller feil typantaking i wrapper-ar. Tredjepartsbibliotek er også kritiske: Nokre leverer callbacks som PAnsiChar, andre forventar nullterminerte byte-strings.
Her lønner det seg å klassifisere avhengigheiter: Kva bibliotek er Unicode-ready, kva er ikkje, og kva kan erstattast eller kapslast inn? Ein innpakking (kapsling) er ofte den raskaste vegen for å avgrense Unicode-legacy til eit klart avgrensa område.
Strategi: Unicode-migrasjon av gamle Delphi-prosjekt som eit kontrollert moderniseringsprogram
Den mest migrationssikre tilnærminga er eit fleirtrinns program som gjer risiko synleg tidleg og held applikasjonen køyrehaldig.
Steg 1: Definer scope og prioriter kode-hotspots
Ikkje all kjeldekode treng umiddelbar endring. Prioriter etter dataflyt og risiko:
- Grensesnitt mot omverda (REST-API, TCP/IP, filer, e-post, utskrift/reporting).
- Datatilgang (SQL, ORM/Datamodule, BDE/FireDAC-lag).
- String-naudelege utility-funksjonar (parserar, formatterar, encoder/decoder).
- Integrasjonar (COM, DLL-importar, maskinvarebindingar).
Resultatet bør vere ei liste over stadar der «encoding er ei spesifikasjon». Desse stadene blir gjort testbare seinare.
Steg 2: Sett compiler-/prosjektval og åtvaringar skarpt
I mange prosjekt har åtvaringar vore slått av i årevis. For ei Unicode-migrasjon er det kontraproduktivt. Aktiver åtvaringar igjen og ta konverteringsåtvaringar på alvor. I tillegg er det nyttig å etablere prosjektomfattande reglar, t.d.: ingen implisitte AnsiString-konverteringar ved I/O-grensar, bruk av TEncoding ved filoperasjonar, ingen «PChar-triks» utan klar kontekst.
Steg 3: Trekke inn «encoding-grensar» som teknisk lag
Eit praktisk arkitekturgrep er å innføre små adapterar/strategi-helper som presist definerer korleis ekstern data kjem inn og går ut. Døme:
- CSV-lesar/-skrivar: alltid med TEncoding.UTF8 (eller definert codepage) og tydelege separator-reglar.
- REST-klient/server: JSON alltid som UTF-8-byte, set header riktig, stream ikkje kroppen «string-basert».
- Windows-API-wrapper: sentrale funksjonar som nøye kapslar Wide/Ansi.
Slik hindrar du at «encoding-val» spreier seg på tvers av kodebasen.
Typiske kodefeller og korleis retta dei på ein rein måte
Length, SizeOf, ByteLength: når teiknlengd og byte-storleik skil seg
I ANSI-tider vart Length(s) ofte misbrukt som byte-tal. I UTF-16 er det feil. Når du treng byte-arrays, konverter eksplisitt:
- For UTF-8: TEncoding.UTF8.GetBytes(s)
- For definert ANSI-codepage: TEncoding.GetEncoding(1252).GetBytes(s) (berre når det fagleg er korrekt)
For bufferstørrelsar ved API-kall gjeld: Sjekk om funksjonen forventar teikn- eller byte-einingar. Mange Wide-API-ar forventar tal i teikn, ikkje byte. Dokumentasjon og signatur avgjer, ikkje intuisjon.
PAnsiChar vs. PWideChar: DLL-importar og eksterne protokollar
Ved DLL-import er faren stor for at signaturar i Delphi-koden ikkje lenger passar. Avklar kva DLL-en forventar:
- Forventar DLL-en UTF-8? Då er passing som PAnsiChar(UTF8String) vanleg, men du må kontrollere levetid og nullterminering.
- Forventar ho UTF-16? Då brukar du PWideChar og wide-strings.
I alle tilfelle bør importane kapslast i ei separat unit, slik at string-politikken ikkje spreier seg i heile prosjektet.
Formatering, case-omforming, samanlikning: lokalitet og normalisering
Unicode fører òg med seg semantiske tema: stor/liten bokstav er ikkje triviell i alle språk, og teikn kan ha ulike normalformer. I typiske bedriftsapplikasjonar er dette mindre kritisk enn i forbrukar-teksthandsaming, men det rører ved:
- sortering og filtrering (t.d. i grids eller søk),
- case-insensitive samanlikningar for nøkkelverdiar,
- generering av filnamn eller identifikatorar.
Viktig er ein klar regel: Kva er «nøklar» (t.d. artikkelnummer, kundekodar) som bør halde seg ASCII-nært, og kva er «tekstar» som må vere fullt Unicode-vennlege? Denne separasjonen reduserer følgefeil.
GUI/Reporting: fontar, utskrift, PDF og komponentåtferd
VCL har sidan Unicode-versjonane grunnleggande Unicode-støtte, men praksis avheng av komponentar og utdata. Risiko oppstår ved:
- eldre report-engines eller PDF-generatorar som antar ANSI,
- barcode-/label-utskrift som krev bestemte codepages,
- hardkodar fontar eller teiknsett.
Planlegg tidlege testar med realistiske eksempeldata (namn, stader, spesialteikn, ikkje-latinske skriftsett der relevant). Verdien ligg mindre i «kan Unicode», og meir i dokumentert: «Denne output-en er korrekt i vår kontekst.»
Data og persistens: Unicode stoppar ikkje ved koden
Set database-charsets og collations korrekt
Ein Unicode-migrasjon er først stabil når databasar og drivarar er korrekt konfigurerte. Døme:
- For PostgreSQL er UTF-8 som regel standard; likevel må client-encoding og drivaratferd kontrollerast.
- For SQL Server er skiljet mellom VARCHAR og NVARCHAR relevant; feil kolonneval kan tappe teikn.
- For MariaDB/MySQL er charset/collation (t.d. utf8mb4) avgjerande så 4-byte-teikn ikkje blir avkorta.
I Delphi-koden bør parameterar og felttypar nyttast slik at Unicode ikkje blir «tilbaka-konvertert» på vegen. FireDAC gir her som oftast betre kontroll enn svært gamle tilgangslag.
Legacy-filformat: migrasjonsreglar i staden for stille konvertering
Dersom applikasjonen over år har produsert filer (eksportformat, arkivfiler, proprietære strukturar), må du definere:
- Kva eksisterande filer skal vere «som dei er» og bli lesne korrekt?
- Kva format skal oppgraderast til UTF-8?
- Postar det versjonsfelt/header for å unngå tvetydig tolking av nye og gamle filer?
Stille konvertering utan merking er risikabelt, fordi feil ofte dukkar opp seint. Betre: versjoner, gjenkjenne tydeleg, migrere målretta.
Kvalitetssikring: testar som verkeleg finn Unicode-problem
Unicode-feil er ofte data-avhengige. Difor er ikkje «happy path»-testar nok. Nyttige testar bør dekkje dei problematiske stadene:
- Roundtrip-testar: Import → Handsaming → Eksport, deretter byte-nøyaktig samanlikning (ved definerte format).
- DB-roundtrip: Skrive/lese tekst med umlaut, aksentar og eventuelt ikkje-latinske teikn; sjekk likskapen.
- Grensesnitt-testar: REST-requestar som UTF-8, header, JSON-escaping, logging.
- Regresjon: Reproduser gamle data og typiske brukarflukter, særleg ved søk, filtrering, sortering.
For B2B-system er det òg relevant at feil blir observerte: Logging må ikkje øydeleggje encodings. Den som skriv loggar som ANSI, mistar i feilsituasjon nett den informasjonen ein treng.
Planlegging og arbeidsmengd: Kva som verkeleg driv kompleksiteten
Arbeidsmengda for Unicode-migrasjon av gamle Delphi-prosjekt avheng mindre av «linjer med kode» og meir av koplingar og eksterne avhengigheiter:
- Mange integrasjonar (DLL-ar, COM, utstyr, ERP/DMS/CRM) aukar testomfanget, fordi encodingar er relevante ved kvar grense.
- Historiske format (gamle eksportar, kundespesifikke CSV-ar) krev migrasjonsreglar og kompatibilitetsstrategiar.
- Blanda Delphi-versjonar eller fleire produkt frå ein felles kodebase aukar koordinasjonsbehovet.
- Gamle datatilgangslag (t.d. BDE) kan indirekte blokkere Unicode og tilseie modernisering.
I praksis har ein framgangsmåte vist seg: stabiliser Unicode fyrst i kjernen og dei mest kritiske dataflytane. Deretter kan moduler trekkast etter stegvis. Det reduserer risiko og unngår lange «big bang»-fasar utan release.
Plassering i moderniseringsvegar: REST, tenester, multiplattform
Unicode er ofte ein grunnmur når legacy-programvare skal moderniserast. Typiske oppfølgingstema er:
- REST-server eller REST-API for ettermontering (handter JSON/UTF-8 korrekt).
- Windows-tenester eller Linux-tenester for stabil drift (logging, konfigfiler, protokollar).
- Trinnvis UI-modernisering i VCL, eventuelt seinare multiplattform-klientar.
Viktig er rekkefølgja: Dersom du byggjer nye grensesnitt, bør encoding-reglar vere på plass først. Ein Unicode-migrasjon «på sidelinja» under grensesnittutvikling fører lett til vanskeleg testar fordi årsak og verknad blander seg.
For intern lenking i magasinet passar det å plassere nærliggande tema som Delphi-modernisering, FireDAC-datatilgang eller arkitektur for REST-serverar som fordjupande artiklar, slik at lesarane målretta kan gå vidare til neste tekniske steg.
Konklusjon: Unicode-migrasjon er eit risikotema – med rett metode blir det planleggjande
Unicode-migrasjonen av gamle Delphi-prosjekt er ikkje eit kosmetisk oppgradering, men ei korrigering av grunnleggjande føresetnader om tekst, byte og grensesnitt. Den som gjer dette strukturert, vinn meir enn «umlaute fungerer att»: Dataflyt blir eintydigare, integrasjonar meir robuste, og seinare modernisering (t.d. REST-server, tenester, database-rydding) blir enklare fordi encodingar ikkje lenger skjer implisitt «ein eller annan stad».
Treng du ein konkret migrasjonsplan for di Delphi-applikasjon, ei risikoanalyse av hot-spot eller hjelp til gjennomføring, er det raskaste neste steget ein teknisk innleiande samtale om rammevilkår og avhengigheiter: Ta kontakt.
I fagleg samanheng spelar også Delphi Unicode Migration og Delphi Ansi Zu Unicode ei viktig rolle når integrasjonar, dataflyt og vidareutvikling må spele godt saman.