Net-Base Magazine

19.04.2026

Migration vers Unicode d'anciens projets Delphi : écueils, stratégie et mise en œuvre soignée

De nombreuses Delphi-applications existantes fonctionnent encore avec des chaînes ANSI. Une migration vers Unicode n'est alors pas un simple réglage du compilateur : elle concerne l'accès aux données, les interfaces, les rapports, les bibliothèques tierces et les tests. Cet article présente un parcours de migration pragmatique — incl...

19.04.2026

La migration vers Unicode des anciens projets Delphi est, dans de nombreuses entreprises, une étape nécessaire : sans elle, les applications existantes atteignent progressivement leurs limites face aux jeux de données internationaux, aux systèmes d’exploitation modernes, aux intégrations et aux nouvelles interfaces. En pratique, il s’agit rarement d’un « recompile et c’est fini ». Delphi a introduit, depuis les versions Unicode (à partir de Delphi 2009), des changements fondamentaux des types de chaîne standards. Cela modifie des hypothèses sur l’encodage des caractères, le layout mémoire et les signatures d’API. Qui sous-estime cela risque de produire des erreurs de données insidieuses, des exports corrompus, des cas de support peu clairs et des risques de sécurité.

Cet article fournit une approche techniquement robuste : comment analyser l’existant, délimiter le périmètre de manière sensée, réduire les risques aux points chauds (bases de données, fichiers, Windows-API, COM, services REST) et sécuriser la migration de sorte que l’exploitation et le développement puissent continuer en parallèle. L’accent est mis sur les pièges typiques de Delphi dans les applications VCL, les services et les interfaces — avec une perspective sur des trajectoires de modernisation dans lesquelles des sujets comme le remplacement de BDE avec une liaison native, des serveurs REST ou le multiplateforme peuvent être intégrés ultérieurement.

Pourquoi la bascule vers Unicode dans Delphi est souvent « plus importante que prévu »

Dans les versions classiques de Delphi, string était un ANSI-String (selon la codepage système). Depuis Delphi 2009, string est par défaut un UnicodeString (UTF-16). Parallèlement, de nombreuses bibliothèques et classes VCL ont été adaptées aux APIs Wide. C’est positif en soi, car cela prend en charge de manière robuste les caractères internationaux. Mais le code legacy a souvent été développé pendant des années autour des hypothèses « 1 caractère = 1 octet », « PChar est PAnsiChar » ou « Length() correspond au nombre d’octets ».

Les causes typiques qui rendent les migrations plus coûteuses :

  • Les conversions implicites fonctionnent certes, mais altèrent les données (particulièrement pour les fichiers, les interfaces ou les champs BLOB/textes en base).
  • Le code orienté octets (streams, buffers, hashing, chiffrement) devient incorrect à l’insu de tous dès lors que le contenu des chaînes est interprété comme des octets.
  • Les composants tiers sont parfois ANSI-only ou utilisent leurs propres types de chaîne et callbacks.
  • L’environnement externe (Windows-API, COM, impression/reporting, EDI, CSV, XML/JSON) attend des encodages précis.

L’objectif ne devrait donc pas être de « modifier le moins possible », mais de modifier de manière ciblée là où les flux de données et les encodages doivent être explicitement définis. Une migration Unicode propre est aussi une opportunité pour documenter et tester enfin des frontières d’encodage floues.

Fondamentaux techniques : types de chaînes dans Delphi, encodages et effets secondaires

string, UnicodeString, AnsiString, WideString – ce qui compte réellement dans le projet

Pour la migration, il est décisif de savoir quels types sont utilisés aux interfaces et dans les fonctions cœur :

  • string : depuis Delphi 2009 un UnicodeString (UTF-16, comptage de références, sémantique immuable via Copy-on-Write).
  • AnsiString : chaîne d’octets avec codepage associée (selon la version de Delphi une codepage peut être portée). Utile quand une interface externe exige explicitement un encodage 8 bits particulier.
  • UTF8String : dans des versions récentes de Delphi souvent alias/AnsiString avec codepage UTF-8 ; pratique pour REST/JSON et de nombreux protocoles.
  • WideString : BSTR (COM), géré en mémoire via SysAllocString ; aujourd’hui nécessaire surtout pour certains interops COM.
  • PChar : depuis les versions Unicode de Delphi PWideChar. C’est un des points de rupture les plus fréquents dans les appels d’API Windows.

Lorsque ces types sont mélangés, des conversions apparaissent. Certaines sont correctes, d’autres surprenantes : une conversion n’est « juste » que si l’on connaît la codepage à la source et celle attendue à la destination.

UTF-16 en interne, UTF-8 en externe : une règle pragmatique

Dans les applications VCL Delphi, il est souvent pertinent de travailler en interne de manière cohérente avec string (UTF-16). À l’extérieur (REST, fichiers, messaging), le plus courant dans la pratique est le UTF-8. Une ligne de conduite robuste est donc :

  • Interne : string/UnicodeString comme standard.
  • Frontières : convertir explicitement à l’entrée/sortie via TEncoding.UTF8 (ou des codepages ANSI définies).
  • Traitement basé octet : TBytes plutôt que des Strings.

Cela réduit les conversions implicites et rend les responsabilités vérifiables : « où les octets deviennent-ils du texte, et avec quel encodage ? »

Inventaire : où l’Unicode casse typiquement dans les anciens projets Delphi

Avant de toucher au code, une inventaire structuré est utile. Dans la migration Unicode d’anciens projets Delphi, les sources d’erreurs ne sont généralement pas réparties uniformément mais concentrées sur quelques points chauds.

1) Accès base de données et types de champs (BDE, ADO, FireDAC)

Beaucoup de projets legacy utilisent encore BDE ou des couches d’accès anciennes. Les problèmes fréquents sont :

  • Mapping des charsets de la base vers les chaînes Delphi (ANSI vs types de champs Unicode).
  • « Texte » dans des BLOBs ou champs Memo sans encodage défini.
  • Instructions SQL comme Strings, interprétées différemment pour les caractères accentués/Unicode.

Si une modernisation est prévue, une migration Unicode se combine bien avec un nettoyage de l’accès aux données, par exemple en direction de BDE-Ablosung mit nativer Anbindung et d’une configuration claire des charsets (comme pour PostgreSQL ou MariaDB). Important : une migration ne doit pas automatiquement forcer une migration de la base, mais l’interface entre la DB et Delphi doit être sans ambiguïté.

2) I/O fichiers et streams : CSV, INI, formats propriétaires, import/export

Classique : les fichiers étaient souvent lus/écrits via AssignFile/ReadLn, TFileStream ou TStringList.LoadFromFile sans encodage explicite. En Delphi Unicode, le comportement devient heuristique (BOM) ou utilise des encodages par défaut. Cela entraîne :

  • interprétations erronées des caractères accentués (ä, ö) dans CSV/logfiles,
  • valeurs de longueur erronées dans des formats propriétaires,
  • incompatibilités avec des partenaires externes qui attendent ISO-8859-1 ou Windows-1252.

Une solution propre consiste à définir un encodage fixe par format de fichier et à l’ancrer dans le code et la documentation. Pour CSV/JSON, UTF-8 est le plus souvent le standard approprié ; pour d’anciennes interfaces, il s’agit parfois de Windows-1252. L’essentiel est l’explicitation.

3) API Windows, PChar, tailles de buffer et gestion de messages

Beaucoup d’applications Delphi appellent des fonctions WinAPI ou manipulent des buffers. Points de rupture fréquents :

  • Utilisation de PChar avec des fonctions disposant de variantes ANSI ou Wide (…A/…W).
  • Les tailles de buffer sont comptées en octets, alors que Char en UTF-16 occupe 2 octets.
  • Arithmetic de pointeurs et layouts de Record basés sur des Char 1 octet.

Ici, un refactoring précis est nécessaire : soit utiliser systématiquement les Wide-APIs, soit appeler sciemment la variante ANSI et travailler avec AnsiString/codepage. « Ça compile d’une manière ou d’une autre » n’est pas un critère de qualité.

4) COM, ActiveX, automatisation Office et bibliothèques tierces

Les interfaces COM travaillent souvent avec BSTR (WideString). Les anciennes versions de Delphi avaient d’autres strings par défaut, si bien que le code « fonctionnait par hasard ». En Delphi Unicode, on observe souvent des conversions doubles ou des hypothèses de types erronées dans les wrappers. Les bibliothèques tierces sont également critiques : certaines fournissent des callbacks en PAnsiChar, d’autres attendent des chaînes d’octets terminées par NULL.

Il vaut donc la peine de classifier les dépendances : quelle bibliothèque est Unicode-ready, laquelle ne l’est pas, et laquelle peut être remplacée ou encapsulée ? L’encapsulation est souvent le moyen le plus rapide pour confiner les dettes Unicode dans un périmètre bien circonscrit.

Stratégie : aborder la migration Unicode des anciens projets Delphi comme un programme de modernisation contrôlé

L’approche la plus sûre consiste en un programme en plusieurs étapes qui rend les risques visibles tôt et maintient l’application opérationnelle.

Étape 1 : définir le périmètre et prioriser les hotspots du code

Tout le code source ne nécessite pas d’être modifié immédiatement. Priorisez selon les flux de données et le risque :

  • Interfaces vers l’extérieur (REST-API, TCP/IP, fichiers, e‑mail, impression/reporting).
  • Accès aux données (SQL, ORM/Datamodule, BDE/FireDAC-couches).
  • Fonctions utilitaires proches des chaînes (parser, formatter, encodeur/décodeur).
  • Intégrations (COM, imports DLL, liaisons matérielles).

Le résultat doit être une liste d’endroits où « l’encodage est une spécification ». Ces points seront ensuite rendus testables.

Étape 2 : affiner volontairement les options du compilateur et les warnings

Dans de nombreux projets, les warnings ont été désactivés pendant des années. Pour une migration Unicode, c’est contre‑productif. Il est pertinent de réactiver les warnings et de prendre au sérieux les alertes de conversion. Il est également utile d’établir des règles de projet, par exemple : pas de conversions AnsiString implicites aux frontières I/O, utilisation de TEncoding pour les opérations fichiers, pas de « PChar‑tricks » sans contexte clair.

Étape 3 : introduire des « frontières d’encodage » comme couche technique

Un dispositif d’architecture pragmatique consiste à introduire de petits adaptateurs/helpers qui définissent précisément comment les données externes entrent et sortent. Exemples :

  • CSV-Reader/-Writer : toujours avec TEncoding.UTF8 (ou codepage définie) et règles de séparateur explicites.
  • REST-Client/Server : JSON toujours sous forme d’octets UTF-8, headers positionnés correctement, Body streamé sans le traiter comme un „string“.
  • Windows-API-Wrapper : fonctions centrales qui encapsulent proprement Wide/Ansi.

Ainsi, vous évitez que des « décisions d’encodage » se dispersent dans toute la base de code.

Pièges de code typiques et comment les corriger proprement

Length, SizeOf, ByteLength : quand longueur en caractères et taille en octets divergent

À l’époque ANSI, Length(s) était souvent utilisé abusivement comme nombre d’octets. En UTF-16, c’est faux. Si vous avez besoin de tableaux d’octets, convertissez explicitement :

  • Pour UTF-8 : TEncoding.UTF8.GetBytes(s)
  • Pour une codepage ANSI définie : TEncoding.GetEncoding(1252).GetBytes(s) (uniquement si c’est métierlement correct)

Pour les tailles de buffer lors d’appels API, vérifiez si la fonction attend des unités en caractères ou en octets. Beaucoup d’APIs Wide attendent le nombre de caractères, pas d’octets. La documentation et la signature décident, pas l’intuition.

PAnsiChar vs. PWideChar : imports DLL et protocoles externes

Pour les imports DLL, le risque est élevé que les signatures dans le code Delphi ne correspondent plus. Définissez ce que la DLL attend :

  • La DLL attend‑elle UTF-8 ? Alors le passage en PAnsiChar(UTF8String) est courant, mais il faut contrôler la durée de vie et la terminaison NUL.
  • Attendez‑elle UTF-16 ? Alors utilisez PWideChar et des Wide-Strings.

Dans tous les cas, les imports doivent être encapsulés dans une unité séparée, afin que la politique de gestion des chaînes ne se propage pas à l’ensemble du projet.

Formatage, changement de casse, comparaison : locale et normalisation

Unicode introduit aussi des enjeux sémantiques : la majuscule/minuscule n’est pas triviale dans toutes les langues, et les caractères peuvent exister sous différentes formes de normalisation. Dans des applications d’entreprise, c’est en général moins critique que dans un traitement de texte grand public, mais cela concerne :

  • le tri et le filtrage (par ex. dans des Grids ou des fonctions de recherche),
  • les comparaisons insensibles à la casse pour des valeurs clés,
  • la génération de noms de fichiers ou d’identifiants.

Il est important d’avoir une règle claire : qu’est‑ce qui constitue des « clés » (par ex. numéros d’article, codes client) qui doivent rester proches de l’ASCII, et qu’est‑ce qui est du « texte » qui doit être pleinement Unicode ? Cette séparation réduit les erreurs ultérieures.

GUI/Reporting : polices, impression, PDF et comportement des composants

La VCL est, depuis les versions Unicode, fondamentalement Unicode‑capable, mais la réalité dépend des composants et des voies de sortie. Des risques apparaissent avec :

  • des moteurs de reporting ou générateurs PDF anciens qui supposent de l’ANSI,
  • l’impression de codes-barres/étiquettes nécessitant des codepages particulières,
  • des polices ou jeux de caractères codés en dur.

Planifiez tôt des tests avec des jeux de données réalistes (noms, localités, caractères spéciaux, écritures non latines si pertinentes). L’intérêt n’est pas seulement de « pouvoir faire du Unicode », mais de démontrer : « cette sortie est correcte dans notre contexte. »

Données et persistance : Unicode ne s’arrête pas au code

Définir proprement charsets et collations en base

Une migration Unicode n’est stable que si les bases de données et les pilotes sont configurés correctement. Exemples :

  • Pour PostgreSQL, UTF-8 est en règle générale standard ; il faut malgré tout vérifier le client‑encoding et le comportement du pilote.
  • Pour SQL Server, la distinction entre VARCHAR et NVARCHAR est pertinente ; un mauvais choix de colonne peut entraîner la perte de caractères.
  • Pour MariaDB/MySQL, charset/collation (par ex. utf8mb4) sont critiques pour que des caractères sur 4 octets ne soient pas tronqués.

Dans le code Delphi, les paramètres et les types de champs doivent être utilisés de manière à éviter que l’Unicode soit « reconverti » à la baisse sur le chemin. FireDAC offre généralement plus de contrôle que des couches d’accès très anciennes.

Formats de fichiers legacy : règles de migration plutôt que conversion silencieuse

Si votre application a généré des fichiers pendant des années (formats d’export, archives, structures propriétaires), vous devez définir :

  • Quels fichiers existants restent « tels quels » et sont lus avec la bonne interprétation ?
  • Quels formats seront migrés vers UTF-8 ?
  • Y a‑t‑il des champs de version/header pour distinguer de manière fiable fichiers anciens et nouveaux ?

La conversion silencieuse sans marquage est risquée car les erreurs apparaissent souvent tardivement. Mieux vaut versionner, détecter clairement et migrer de manière ciblée.

Assurance qualité : tests qui détectent réellement les problèmes Unicode

Les erreurs Unicode dépendent souvent des données. Les tests « happy path » ne suffisent donc pas. Un ensemble de tests pertinent couvre les zones problématiques :

  • Tests roundtrip : import → traitement → export, puis comparaison octet à octet (pour les formats définis).
  • Roundtrip DB : écriture/lecture de textes avec accents, diacritiques et éventuellement caractères non latins ; vérification d’égalité.
  • Tests d’interface : requêtes REST en UTF-8, headers, échappement JSON, logging.
  • Régression : reproduire des données anciennes et des cas utilisateur typiques, notamment recherche, filtrage, tri.

Pour des systèmes B2B, il est aussi important que les erreurs deviennent observables : le logging ne doit pas détruire les encodages. Si les logs sont écrits en ANSI, on perd au diagnostic précisément l’information qui est nécessaire.

Planification et effort : ce qui fait réellement monter la complexité

L’effort d’une migration Unicode d’anciens projets Delphi dépend moins du « nombre de lignes » que des couplages et des dépendances externes :

  • Beaucoup d’intégrations (DLLs, COM, équipements, ERP/DMS/CRM) augmentent la charge de vérification, car chaque frontière implique des encodages.
  • Formats historiques (anciens exports, CSVs spécifiques client) nécessitent des règles de migration et des stratégies de compatibilité.
  • Versions Delphi mixtes ou plusieurs produits issus d’un même code‑base augmentent le besoin de coordination.
  • Couches d’accès aux données anciennes (par ex. BDE) peuvent indirectement bloquer l’Unicode et rendre une modernisation nécessaire.

Dans la pratique, une approche éprouvée consiste à stabiliser d’abord l’Unicode au cœur et sur les flux de données critiques. Ensuite, on rattrape module par module. Cela réduit les risques et évite de longues phases « big bang » sans livraison.

Intégration dans des trajectoires de modernisation : REST, services, multiplateforme

Unicode est souvent une base nécessaire lorsque l’on veut moderniser du legacy. Questions d’interface typiques :

  • Mettre en place un serveur REST ou une API REST (traiter JSON/UTF-8 proprement).
  • Exploiter des services Windows ou des services Linux de manière stable (logging, fichiers de config, protocoles).
  • Modernisation progressive de l’UI en VCL, puis éventuellement des clients multiplateformes.

L’ordre est important : si vous développez de nouvelles interfaces, les règles d’encodage doivent être établies en amont. Une migration Unicode « en parallèle » pendant le développement d’interfaces génère des schémas d’erreurs difficiles à tester, car cause et effet se mêlent.

Pour l’intégration interne au magazine, il est pertinent de lier des sujets voisins comme la modernisation Delphi, l’accès aux données via FireDAC ou l’architecture de serveurs REST en tant qu’articles approfondis, afin que le lecteur puisse passer précisément à l’étape technique suivante.

Conclusion : la migration Unicode est un sujet de risque — avec la bonne méthode, il devient planifiable

La migration Unicode des anciens projets Delphi n’est pas une mise à jour cosmétique, mais une correction d’hypothèses fondamentales sur le texte, les octets et les interfaces. Une démarche structurée apporte cependant plus que la simple prise en charge des accents : les flux de données deviennent plus explicites, les intégrations plus robustes et la modernisation future (par ex. serveurs REST, services, nettoyage en base) devient plus simple, puisque les encodages ne se produisent plus implicitement « quelque part ».

Si vous avez besoin d’un plan de migration concret pour votre application Delphi, d’une analyse de risques des hotspots ou d’un accompagnement à la mise en œuvre, l’étape suivante la plus rapide est un entretien technique initial sur vos contraintes et dépendances : prenez contact.

Dans le contexte métier, la migration Unicode Delphi et la conversion Delphi Ansi vers Unicode jouent un rôle important lorsque intégrations, flux de données et évolution doivent fonctionner de façon cohérente.

Discuter du projet ou de la modernisation avec Net-Base.

Partager l'article

Partager directement cette publication

LinkedIn, X, XING, Facebook, WhatsApp et e-mail sont immédiatement disponibles. Pour Instagram, nous préparons directement le lien et un court texte.

Courriel

Instagram s'ouvre dans un nouvel onglet. Le lien et le court texte sont préalablement copiés dans le presse-papiers.