Eski Delphi projelerinin Unicode geçişi, birçok şirkette gerekli bir adım haline gelmiştir; aksi takdirde mevcut uygulamalar uluslararası veriler, modern işletim sistemleri, entegrasyonlar ve yeni arayüzlerle giderek daha fazla sınıra takılır. Pratikte bu nadiren “yeniden derle ve bitti” şeklindedir. Delphi 2009 ve sonraki Unicode sürümlerinden itibaren standart string türlerinde temel değişiklikler yaptı. Bu, karakter kodlaması, bellek düzeni ve API imzaları ile ilgili varsayımları kaydırır. Bunu hafife alanlar, zamanla ortaya çıkan veri hataları, bozuk dışa aktarmalar, muğlak destek vakaları ve güvenlik riskleri üretir.
Bu yazı teknik olarak dayanılabilir bir yaklaşım sunar: Mevcut durumu nasıl analiz edeceğiniz, kapsamı nasıl makul şekilde keseceğiniz, riskleri veri tabanları, dosyalar, Windows-API’leri, COM, REST-servisleri gibi sıcak noktalarda nasıl azaltacağınız ve geçişi işletme ile devam eden geliştirmeyi paralel tutacak şekilde nasıl güvenceye alacağınız. Odak, VCL uygulamalarında, servislerde ve arayüzlerde sık görülen Delphi özel tuzaklar üzerinedir — daha sonra BDE-kaldırma ile yerel bağlama, REST-sunucular veya çoklu platform konularının da dahil edilebileceği modernizasyon yollarına bakışı içerir.
Neden Delphi’de Unicode geçişi çoğu zaman “düşünüldüğünden daha büyük” olur
Klasik Delphi sürümlerinde string bir ANSI-string (sistem kod sayfasına bağlı olarak) idi. Delphi 2009’dan itibaren string varsayılan olarak bir UnicodeString (UTF-16) oldu. Aynı zamanda birçok kütüphane ve VCL sınıfı Wide-API’lere taşındı. Bu temelde olumlu; çünkü uluslararası karakterleri sağlam şekilde destekliyor. Ancak: Legacy kod yıllar içinde “1 karakter = 1 byte”, “PChar = PAnsiChar” veya “Length() byte sayısına eşittir” gibi varsayımlar üzerine inşa edilmiş olabilir.
Geçişlerin daha maliyetli olmasının tipik nedenleri:
- Örtük dönüştürmeler çalışsa da verileri değiştirir (özellikle dosyalar, arayüzler veya veritabanı BLOB/Memo alanları söz konusuysa).
- Byte-odaklı kod (stream’ler, buffer’lar, hashing, şifreleme) string içerikleri byte olarak yorumladığında fark edilmeden hatalı çalışır.
- Üçüncü taraf bileşenler kısmen yalnızca ANSI destekleyebilir veya kendi string türlerini ve callback’lerini kullanabilir.
- Harici çevre (Windows-API’leri, COM, yazdırma/raporlama, EDI, CSV, XML/JSON) belirli kodlamalar bekleyebilir.
Hedef, “mümkün olduğunca az değiştirmek” değil; veri akışlarının ve kodlamaların tanımlanması gereken yerlerde hedefli değişiklik yapmaktır. Temiz bir Unicode geçişi, kodlama sınırlarını nihayet belgelemek ve test etmek için bir fırsattır.
Teknik temel: Delphi string türleri, kodlamalar ve yan etkileri
string, UnicodeString, AnsiString, WideString – projede gerçekten hangi türler önemlidir
Geçiş için önemli olan, arayüzlerde ve temel fonksiyonlarda hangi tiplerin kullanıldığıdır:
- string: Delphi 2009’dan beri bir UnicodeString (UTF-16, reference-counted, Copy-on-Write üzerinde immutable benzeri davranış).
- AnsiString: Belirli bir codepage’e bağlı byte-string (Delphi sürümüne göre bir codepage taşınabilir). Dış arayüzün açıkça belirli bir 8-bit kodlama istediği durumlarda uygundur.
- UTF8String: Yeni Delphi sürümlerinde genellikle UTF-8 codepage’ine sahip bir Alias/AnsiString olarak bulunur; REST/JSON ve birçok protokol için pratiktir.
- WideString: BSTR (COM), SysAllocString ile yönetilir; bugün çoğunlukla belirli COM interoperability durumları için gereklidir.
- PChar: Unicode Delphi ile birlikte PWideChar oldu. Bu, Windows-API çağrılarında en sık kırılma noktalarından biridir.
Bu tipler karıştığında dönüştürmeler oluşur. Bazıları doğru, bazıları şaşırtıcı olabilir: Bir dönüştürme yalnızca kaynağın hangi codepage’e sahip olduğunu ve hedefin ne beklediğini bildiğinizde “doğru” kabul edilebilir.
Dahili UTF-16, harici UTF-8: pratik bir rehber
Delphi-VCL uygulamalarında içsel olarak tutarlı şekilde string (UTF-16) ile çalışmak sıkça mantıklıdır. Dış dünyada (REST, dosyalar, messaging) gerçekte UTF-8 hakimdir. Güçlü ve pratik bir kural şöyledir:
- İçeride: string/UnicodeString standart olarak kullanılır.
- Sınırlar: Girdi/çıktıda açıkça TEncoding.UTF8 (veya tanımlı ANSI-codepage’ler) üzerinden dönüştürme yapılır.
- Byte-temelli işlem: TBytes kullanın, string yerine.
Bu, örtük dönüştürmeleri azaltır ve sorumlulukları denetlenebilir kılar: “Bytes nerede metne dönüşüyor ve hangi kodlama ile?”
Envanter: Eski Delphi projelerinde Unicode’un tipik olarak nerede kırıldığı
Koda dokunmadan önce yapısal bir envanter yapmak faydalıdır. Eski projelerde hata kaynakları genellikle eşit dağılmaz, bazı sıcak noktalarda toplanır.
1) Veritabanı erişimi ve alan tipleri (BDE, ADO, FireDAC)
Birçok eski proje hâlâ BDE veya daha eski veri erişim katmanlarını kullanır. Buradaki yaygın sorunlar:
- Veritabanı charset’lerinin Delphi string’lerine (ANSI vs. Unicode alan tipleri) eşlenmesi.
- BELİRSİZ kodlamaya sahip BLOB veya Memo alanlarında saklanan “metin”.
- Umlaut/Unicode karakterleri içeren SQL ifadelerinin farklı yorumlanması.
Zaten modernizasyon planı varsa, Unicode geçişi veri erişiminin temizlenmesiyle kombine edilebilir; örneğin BDE-Ablosung mit nativer Anbindung yönünde ve açık charset konfigürasyonu ile (PostgreSQL veya MariaDB gibi). Önemli: Bir migrasyon otomatik olarak veritabanı migrasyonunu zorlamamalı, ancak DB ile Delphi arasındaki arayüz net olmalıdır.
2) Dosya ve Stream I/O: CSV, INI, özel formatlar, import/export
Klasik bir örnek: Dosyalar eskiden AssignFile/ReadLn, TFileStream veya TStringList.LoadFromFile ile kodlama belirtilmeden okunup yazılıyordu. Unicode Delphi sürümlerinde runtime heuristik olarak BOM’u kullanır veya varsayılan kodlama uygular. Sonuç:
- CSV/log dosyalarında yanlış yorumlanan umlaut’lar (ä, ö),
- özel formatlarda hatalı uzunluk bildirimleri,
- ISO-8859-1 veya Windows-1252 bekleyen harici ortaklarla uyumsuzluk.
Temiz çözüm, her dosya formatı için sabit bir kodlama tanımlamak ve bunu kodda ve belgelerde bağlayıcı kılmaktır. CSV/JSON için genellikle UTF-8 doğru standarttır; eski arayüzler için bazen Windows-1252 gerekli olabilir. Önemli olan açık seçikliliktir.
3) Windows-API, PChar, buffer boyutları ve mesaj işleme
Birçok Delphi uygulaması WinAPI fonksiyonlarını çağırır veya buffer’larla çalışır. Yaygın kırılma noktaları:
- PChar kullanımının ANSI veya Wide varyantları olan fonksiyonlarla birlikte olması (…A/…W).
- Buffer boyutlarının byte cinsinden hesaplanması, oysa Char UTF-16’de 2 byte’tır.
- Pointer aritmetiği ve 1-byta dayalı record düzenleri.
Burada kesinlikle dikkatli refaktör gereklidir: ya tutarlı şekilde Wide-API’leri kullanın ya da bilinçli olarak ANSI varyantını çağırıp AnsiString/codepage ile çalışın. “Biri nasıl olsa derleniyor” kalite kriteri değildir.
4) COM, ActiveX, Office-Otomasyon ve üçüncü taraf kütüphaneler
COM arayüzleri sıklıkla BSTR (WideString) ile çalışır. Eski Delphi sürümlerinde farklı varsayılan string’ler yüzünden kod “tesadüfen” doğru çalışıyor olabilir. Unicode Delphi ile çift dönüştürmeler veya wrapper’larda hatalı tip varsayımları ortaya çıkar. Üçüncü taraf kütüphaneler de kritik olabilir: Bazıları callback’leri PAnsiChar olarak verir, bazıları null-terminated byte-string bekler.
Bağımlılıkları sınıflandırmak burada değerlidir: Hangi kütüphane Unicode-ready, hangisi değil, hangisi değiştirilebilir veya kapsüllenebilir? Kapsülleme genellikle Unicode mirasını net sınırlı bir alana yerleştirmenin en hızlı yoludur.
Strateji: Eski Delphi projelerinin Unicode geçişini kontrollü bir modernizasyon programı olarak yürütmek
En risksiz yaklaşım, riskleri erken görünür kılan ve uygulamayı çalışır tutan çok aşamalı bir programdır.
Adım 1: Kapsam belirleme ve kod sıcak noktalarını önceliklendirme
Her kaynak kod hemen değiştirilmek zorunda değildir. Veri akışı ve risk temelinde önceliklendirin:
- Dış arayüzler (REST-API, TCP/IP, dosyalar, e-posta, yazdırma/raporlama).
- Veri erişimi (SQL, ORM/Datamodule, BDE/FireDAC katmanları).
- String’e yakın yardımcı fonksiyonlar (parser, formatter, encoder/decoder).
- Entegrasyonlar (COM, DLL-importlar, donanım bağlantıları).
Çıktı, “kodlamanın bir spesifikasyon olduğu” yerlerin bir listesi olmalıdır. Bu noktalar sonradan test edilebilir hale getirilecektir.
Adım 2: Derleyici/proje seçenekleri ve uyarıları bilerek sıkılaştırma
Birçok projede uyarılar yıllarca kapatılmıştır. Unicode geçişinde bu ters etki verir. Uyarıları yeniden açmak ve dönüştürme uyarılarını ciddiye almak uygundur. Ayrıca proje genelinde kurallar belirlemek fayda sağlar; örneğin: I/O sınırlarında örtük AnsiString dönüştürmelerine izin verme, dosya işlemlerinde TEncoding kullanımı, bağlamı belli olmayan “PChar hilelerinden” kaçınma.
Adım 3: “Kodlama-sınırları”nı teknik bir katman olarak çekmek
Pratik bir mimari önlem, harici verinin nasıl içeri girip çıktığını kesin biçimde tanımlayan küçük adapter/helper’lar eklemektir. Örnekler:
- CSV-Reader/-Writer: her zaman TEncoding.UTF8 (veya tanımlı codepage) ile ve net ayırıcı kurallarıyla.
- REST-Client/Server: JSON her zaman UTF-8 byte’ları olarak, header doğru ayarlı, body “string tabanlı” olarak değil stream şeklinde iletilmeli.
- Windows-API-wrapper: Wide/Ansi’nin temizce kapsüllenmiş merkezi fonksiyonları.
Böylece “kodlama kararlarının” kod tabanı boyunca dağılmasını engellersiniz.
Tipik kod tuzakları ve temiz düzeltme yöntemleri
Length, SizeOf, ByteLength: karakter uzunluğu ile byte büyüklüğü ayrı düştüğünde
ANSI zamanlarında Length(s) sıklıkla byte sayısı yerine kullanıldı. UTF-16’de bu yanlıştır. Byte-array gerektiğinde açık dönüştürme yapın:
- UTF-8 için: TEncoding.UTF8.GetBytes(s)
- Belirli bir ANSI-codepage için: TEncoding.GetEncoding(1252).GetBytes(s) (sadece iş gereği doğruysa)
API çağrılarında buffer boyutları için: Fonksiyonun karakter mi yoksa byte birimi mi beklediğini kontrol edin. Birçok Wide-API karakter sayısı bekler, byte değil. Belirleyici olan dokümantasyon ve imzadır, sezgi değil.
PAnsiChar vs. PWideChar: DLL-importlar ve dış protokoller
DLL-importlarda, imzaların Delphi kodunda artık uymaması riski büyüktür. DLL’in ne beklediğini netleştirin:
- DLL UTF-8 mü bekliyor? O zaman genellikle PAnsiChar(UTF8String) ile geçiş yapılır, ancak yaşam süresi ve null-terminasyon kontrol edilmelidir.
- UTF-16 mı bekliyor? O zaman PWideChar ve wide-string’ler kullanılmalıdır.
Her durumda importları ayrı bir unit’te kapsüllemek iyi bir uygulamadır; böylece string politikası tüm projeye yayılmaz.
Formatlama, büyük-küçük dönüşümü, karşılaştırma: locale ve normalizasyon
Unicode semantik konuları da getirir: büyük/küçük harf dönüşümleri tüm dillerde basit değildir ve karakterler farklı normal formlara sahip olabilir. Tipik kurumsal uygulamalarda bu tüketici metin işleme kadar kritik olmayabilir, ancak etkiler:
- Grid’lerde veya aramalarda sıralama ve filtreleme,
- Anahtar değerler için case-insensitive karşılaştırmalar,
- Dosya adları veya identifier oluşturma.
Açık bir kural şart: Hangi değerlerin “anahtar” olduğu (ör. makale numarası, müşteri kodları) ve ASCII’ye yakın tutulmaları gerektiği, hangilerinin ise tam Unicode desteğine ihtiyaç duyduğu net olmalıdır. Bu ayrım sonraki hataları azaltır.
GUI/Raporlama: fontlar, yazdırma, PDF ve bileşen davranışı
VCL Unicode yeteneğine sahip olsa da pratikte davranış bileşenlere ve çıktı yollarına bağlıdır. Riskler şu alanlarda ortaya çıkar:
- ANSI bekleyen eski rapor motorları veya PDF üreticiler,
- Bazı barkod/etiket yazıcılarının belirli codepage’ler gerektirmesi,
- Sabit kodlanmış fontlar veya karakter setleri.
Gerçek örnek verilerle (isimler, yerler, özel karakterler, gerekiyorsa Latin olmayan yazılar) erken testler planlayın. Önemli olan “Unicode destekleniyor” demek değil; “bu çıktının bizim bağlamda doğru olduğunun kanıtı”dır.
Veri ve kalıcılık: Unicode kodu ile bitmez
Veritabanı charset ve collation’larını doğru belirleme
Unicode geçişi yalnızca kod tarafında istikrarlı ise kalıcıdır; veritabanları ve sürücüler doğru yapılandırılmalıdır. Örnekler:
- PostgreSQL’de genellikle UTF-8 standarttır; yine de client-encoding ve sürücü davranışı kontrol edilmelidir.
- SQL Server’da VARCHAR ile NVARCHAR ayrımı önemlidir; yanlış sütun seçimi karakter kaybına yol açar.
- MariaDB/MySQL’de utf8mb4 gibi charset/collation seçimi 4-byte karakterlerin kesilmemesi için kritiktir.
Delphi kodunda parametre ve alan tipleri, Unicode’un dönüş yolunda “geri dönüştürülmesini” engelleyecek şekilde kullanılmalıdır. FireDAC genellikle çok eski erişim katmanlarına göre daha iyi kontrol sağlar.
Legacy dosya formatları: sessiz dönüştürme yerine geçiş kuralları
Uygulamanız yıllardır dosya üretiyorsa (export formatları, arşiv dosyaları, özel yapılar), şunları tanımlamanız gerekir:
- Hangi mevcut dosyalar “olduğu gibi” kalacak ve okunurken doğru yorumlanacak?
- Hangi formatlar UTF-8’e yükseltilecek?
- Yeni ve eski dosyaları kesin ayırt etmek için sürüm alanları/header’lar olacak mı?
İşaretlenmemiş sessiz dönüştürme risklidir çünkü hatalar genellikle geç ortaya çıkar. Daha iyi yaklaşım: versiyonlama, net tanıma ve hedefli migrasyon.
Kalite güvence: Unicode hatalarını gerçekten bulacak testler
Unicode hataları sıklıkla veriye bağımlıdır. Bu nedenle sadece “happy path” testleri yeterli değildir. Sorunlu noktaları kapsayan bir test seti uygundur:
- Roundtrip-testleri: Import → işleme → export ve ardından byte-bazlı karşılaştırma (tanımlı formatlarda).
- DB-roundtrip: Umlaut’lar, aksanlı karakterler ve gerekirse Latin olmayan karakterlerle yazma/okuma; eşitlik kontrolü.
- Arayüz-testleri: REST-istekleri UTF-8 olarak, header, JSON-escaping, logging.
- Regresyon: Eski veriler ve tipik kullanıcı senaryolarını yeniden üretme, özellikle arama, filtre, sıralama alanlarında.
B2B sistemler için ayrıca hataların gözlemlenebilir olması önemlidir: Logging kodlamayı bozuyorsa hata durumunda ihtiyacınız olan bilgi kaybolur. Log’ları ANSI yazmak, hatada tam olarak ihtiyaç duyulan bilgiyi yitirmeye neden olur.
Planlama ve çaba: Kompleksliği gerçekten ne tetikliyor
Eski Delphi projelerinin Unicode geçişindeki çaba, “kod satırı sayısından” çok bağlantılar ve harici bağımlılıklara bağlıdır:
- Çok sayıda entegrasyon (DLL’ler, COM, cihazlar, ERP/DMS/CRM) her sınırda kodlamanın önemli olması nedeniyle kontrol maliyetini artırır.
- Tarihsel formatlar (eski export’lar, müşteri-özel CSV’ler) geçiş kuralları ve uyumluluk stratejileri gerektirir.
- Karışık Delphi sürümleri veya tek bir kod tabanından çıkan birden fazla ürün koordinasyon ihtiyacını artırır.
- Eski veri erişim katmanları (ör. BDE) Unicode’u dolaylı olarak engelleyebilir ve modernizasyonu gerekli kılabilir.
Pratikte etkili bir yol, önce çekirdekte ve en kritik veri akışlarında Unicode’u stabil hale getirmektir. Ardından modüller adım adım uyumlu hale getirilebilir. Bu, riski azaltır ve uzun “Big Bang” fazlarından kaçınarak sürüm çıkışlarını mümkün kılar.
Modernizasyon yollarına yerleştirme: REST-lar, servisler, çoklu platform
Unicode genellikle mevcut yazılım modernize edilirken temel bir gerekliliktir. Tipik takip soruları şunlardır:
- REST-sunucu veya REST-API ekleme (JSON/UTF-8 doğru şekilde ele alınmalı).
- Windows-servisleri veya Linux-servisleri stabil işletme (logging, konfig dosyaları, protokoller).
- VCL içinde kademeli UI modernizasyonu ve ileride gerekirse çoklu platform istemciler.
Sıralama önemlidir: Yeni arayüzler inşa ediyorsanız, kodlama kuralları önceden belirlenmelidir. Arayüz geliştirme sırasında eşzamanlı bir Unicode geçişi yapmak, neden-sonuç ilişkilerini karıştırarak test edilmesi zor hata görünümlerine yol açar.
Magazin içi dahili bağlantılar için, bitişik konular olarak Delphi-modernizasyonu, FireDAC-veri erişimi veya REST-sunucu mimarisi gibi derinleştirici makaleler sunmak uygundur; böylece okuyucular bir sonraki teknik adımı hedefleyebilir.
Sonuç: Unicode geçişi bir risk konusudur — doğru yöntemle planlanabilir
Eski Delphi projelerinin Unicode geçişi kozmetik bir yükseltme değil; metin, byte ve arayüzlere dair temel varsayımların düzeltilmesidir. Yapısal olarak ilerlerseniz, yalnızca “umlaut’lar tekrar çalışsın”tan daha fazlasını kazanırsınız: Veri akışları netleşir, entegrasyonlar daha sağlam olur ve sonraki modernizasyon (ör. REST-sunucular, servisler, veritabanı temizliği) kolaylaşır çünkü kodlamalar artık örtük şekilde “bir yerde” gerçekleşmez.
Delphi uygulamanız için somut bir geçiş planı, sıcak noktaların risk analizi veya uygulama desteğine ihtiyacınız varsa, en hızlı sonraki adım çerçeve şartlarınızı ve bağımlılıklarınızı kapsayan teknik bir ilk görüşmedir: İletişime geçin.
Uzmanlık alanında Delphi Unicode Geçişi ve Delphi Ansi’den Unicode’a dönüşüm de önemli bir rol oynar; entegrasyonlar, veri akışları ve devam eden geliştirme düzgün bir şekilde birlikte çalışmalı.
Projekt oder Modernisierungsvorhaben mit Net-Base besprechen.