ASCII nedir ?
Karakter Kodlama (Character Encoding)
Programcılık daha doğrusu yazılım açısından mutlaka öğrenmemiz gereken çok önemli bir konu var. Karakter kodlama önemli konulardan bir tanesidir.
Karakter dizilerinde encode() adlı bir metod vardır. Aynı şekilde, dosyaların da encoding adlı bir parametresi var. Encoding, metin düzenleyici ayarlarında karşımıza çıkıyor. Orada, yazdığımız programlarda özellikle Türkçe karakterlerin düzgün görünebilmesi için, kullandığımız metin düzenleyicinin dil kodlaması (encoding) ayarlarını düzgün yapmamız gerekiyor. Bu encoding konusunu bütün ayrıntılarıyla ele alıp incelersek, yazdığımız programlarda Türkçe karakterleri kullanırken ne tür sorunlarla karşılaştığımızı, bunların temelinde neyin yattığını görmüş olacağız.
Giriş
Bilgisayar, üzerinden elektrik geçen devrelerden oluşan bir sistemdir. Eğer bir devrede elektrik yoksa o devrenin değeri 0 volt iken, o devreden elektrik geçtiğinde devrenin değeri yaklaşık +5 volttur.
Bu durumda iki farklı değer vardır: 0 volt ve +5 volt. İkili (binary) sayma sisteminde de iki değer bulunur: 0 ve 1. İşte bundan dolayı 0 volt’u ikili sistemde 0 ile, +5 volt’u ise 1 ile temsil eder. Devreden elektrik geçtiğinde o devrenin değeri 1 olacak, elektrik geçmediğinde ise 0 olacaktır. Tabii bilgisayar açısından bakıldığında devrede elektrik vardır veya yoktur. Bu ikili durumu daha kolay bir şekilde anlamak için farklı voltaj durumlarından her birine sırasıyla 0 ve 1 gibi bir değer veririz. Yani iki farklı voltaj değerini iki farklı sayı halinde kodluyoruz. Bilgisayarlarda da 0 volt ve +5 volt değerleri sırasıyla ikili sayma sistemindeki 0 ve 1 sayıları halinde kodlanabilir.
İlk başta yalnızca iki farklı elektrik sinyali vardır. Elbette bu elektrik sinyalleri ile doğrudan herhangi bir işlem yapamayız. Mesela elektrik sinyallerini birbiriyle toplayıp, birbirinden çıkaramayız. Ama bu sinyalleri bir sayma sistemi ile temsil edersek (yani bu sinyalleri o sayma sisteminde kodlarsak), bunları kullanarak, örneğin, aritmetik işlemleri rahatlıkla gerçekleştirebiliriz. Mesela 0 volt ile +5 voltu birbiriyle toplayamayız, ama 0 voltu ikili sistemdeki 0 sayısıyla, +5 voltu ise ikili sistemdeki 1 sayısıyla kodladıktan sonra bu ikili sayılar arasında her türlü aritmetik işlemi gerçekleştirebiliriz.
Bilgisayarlar yalnızca iki farklı voltaj durumundan anladığı ve bu iki farklı voltaj durumu da ikili sayma sistemindeki iki farklı sayı ile kolayca temsil edilebildiği için, ilk bilgisayarlar çoğunlukla sadece hesap işlemlerinde kullanılıyordu. Karakterlerin/harflerin bilgisayar dünyasındaki işlevi bir hayli kısıtlıydı. Metin oluşturma işi o zamanlarda daktilo ve benzeri araçların görevi olarak görülüyordu.
Birtakım elektrik sinyallerini, birtakım aritmetik işlemleri gerçekleştirebilmek amacıyla nasıl birtakım sayılar halinde kodlayabiliyorsak; birtakım sayıları da, birtakım metin işlemlerini gerçekleştirebilmek amacıyla birtakım karakterler halinde kodlayabiliriz.
Bilgisayarlar da yalnızca elektrik sinyallerini görür. Bilgisayarlarda da hangi elektrik sinyalinin hangi sayıya; hangi sayının da hangi karaktere karşılık geleceğini belirleyebiliriz. Daha doğrusu, bilgisayarların gördüğü bu elektrik sinyallerini sayılara ve karakterlere dönüştürebiliriz. Dışarıdan girilen karakterleri de, bilgisayarların anlayabilmesi için tam aksi istikamette sayıya, oradan da elektrik sinyallerine çevirebiliriz. İşte bu dönüştürme işlemine karakter kodlama (character encoding) adı verilir.
Buradan yola çıkarak sayıları karakterlere, karakterleri de sayılara dönüştüreceğiz. Ama peki hangi sayıları hangi karakterlere, hangi karakterleri de hangi sayılara dönüştüreceğiz? Yani mesela ikili sistemdeki 0 sayısı hangi karaktere, 1 sayısı hangi karaktere, 10 sayısı hangi karaktere karşılık gelecek?
Hangi sayıların hangi karakterlere karşılık geleceğini, sayılarla karakterlerin eşleştirildiği birtakım tablolar yardımıyla rahatlıkla belirleyebiliriz.
1960’lı yılların ilk yarısına kadar her bilgisayar üreticisi, sayılarla karakterlerin eşleştirildiği, birbirinden çok farklı tablolar kullanıyordu. Yani her bilgisayar üreticisi farklı karakterleri farklı sayılarla eşleştiriyordu. Örneğin bir bilgisayarda 10 sayısı ‘a’ harfine karşılık geliyorsa, başka bir bilgisayarda 10 sayısı ‘b’ harfine karşılık gelebiliyordu. Bu durumun doğal sonucu olarak, iki bilgisayar arasında güvenilir bir veri aktarımı gerçekleştirmek mümkün olmuyordu. Hatta daha da vahimi, aynı firma içinde bile birden fazla karakter eşleştirme tablosunun kullanıldığı olabiliyordu…
Peki bu sorunun çözümü ne olabilir?
Cevap elbette standartlaşma.
Standartlaşma ilerleme ve uygarlık açısından çok önemli bir kavramdır. Standartlaşma olmadan ilerleme ve uygarlık düşünülemez. Eğer standartlaşma diye bir şey olmasaydı, mesela A4 piller boy ve en olarak standart bir ölçüye sahip olmasaydı, evde kullandığınız küçük aletlerin pili bittiğinde uygun pili satın almakta büyük zorluk çekerdiniz. Banyo-mutfak musluklarındaki plastik contanın belli bir standardı olmasaydı, conta eskidiğinde yenisini alabilmek için eskisinin ölçülerini inceden inceye hesaplayıp bu ölçülere göre yeni bir conta arayışına çıkmanız gerekirdi. Herhangi bir yerden bulduğunuz contayı herhangi bir muslukta kullanamazdınız. İşte bu durumun aynısı bilgisayarlar için de geçerlidir. Eğer bugün karakterlerle sayıları eşleştirme işlemi belli bir standart üzerinden yürütülüyor olmasaydı, kendi bilgisayarınızda oluşturduğunuz bir metni başka bir bilgisayarda açtığınızda aynı metni göremezdiniz. İşte 1960’lı yıllara kadar bilgisayar dünyasında da aynen buna benzer bir sorun vardı. Yani o dönemde, hangi sayıların hangi karakterlerle eşleşeceği konusunda uzlaşma olmadığı için, farklı bilgisayarlar arasında metin değiş tokuşu pek mümkün değildi.
1960’lı yılların başında IBM şirketinde çalışan Bob Bemer adlı bir bilim adamı bu kargaşanın sona ermesi gerektiğine karar verip, herkes tarafından benimsenecek ortak bir karakter kodlama sistemi üzerinde ilk çalışmaları başlattı. İşte ASCII (‘aski’ okunur) böylece hayatımıza girmiş oldu.
ASCII
Bilgisayarların iki farklı elektrik sinyali ile çalıştığını, bu iki farklı sinyalin de 0 ve 1 sayıları ile temsil edildiğini, bilgisayarla metin işlemleri yapabilmek için ise bu sayıların belli karakterlerle eşleştirilmesi gerekiyor.
Yukarıda da bahsettiğimiz gibi, uygarlık ve ilerleme açısından standartlaşma önemli bir basamaktır. Biz bilgisayarların çalışma prensibinde iki farklı elektrik sinyali olduğunu biliyoruz. İşlerimizi daha kolay yapabilmek için, bu sinyalleri daha somut birer araç olan 0 ve 1 sayıları atanmıştır. Eğer devrede elektrik yoksa bu durumu 0 ile, eğer devrede elektrik varsa bu durumu 1 ile temsil ediliyor. Esasında bu da bir uzlaşma gerektirir. Devrede elektrik yoksa bu durumu pekala 0 yerine 1 ile de temsil edebilirdik… Eğer elektrik sinyallerinin temsili üzerinde böyle bir uzlaşmazlık olsaydı, her şeyden önce hangi sinyalin hangi sayıya karşılık geleceği konusunda da ortak bir karara varmamız gerekirdi.
Elektriğin var olmadığı durumu 0 yerine 1 ile temsil etmek akla pek yatkın olmadığı için uzlaşmada bir problem çıkmıyor. Ama karakterler böyle değildir. Onlarca (hatta yüzlerce ve binlerce) karakterin sayılarla eşleştirilmesi gereken bir durumda, ortak bir eşleştirme düzeni üzerinde uzlaşma sağlamak hiç de kolay bir iş değildir. Zaten 1960’lı yılların başına kadar da böyle bir uzlaşma sağlanabilmiş değildi. Dediğimiz gibi, her bilgisayar üreticisi sayıları farklı karakterlerle eşleştiriyor, yani birbirlerinden tamamen farklı karakter kodlama sistemleri kullanıyordu.
İşte bu kargaşayı ortadan kaldırmak gayesiyle, Bob Bemer ve ekibi hangi sayıların hangi karakterlere karşılık geleceğini belli bir standarda bağlayan bir tablo oluşturdu. Bu standarda ise American Standard Code for Information Interchange, yani ‘Bilgi Alışverişi için Standart Amerikan Kodu’ veya kısaca ‘ASCII’ adı verildi.
7 Bitlik bir Sistem
ASCII adı verilen sistem, birtakım sayıların birtakım karakterlerle eşleştirildiği basit bir tablodan ibarettir
ASCII tablosunda toplam 128 karakterin sayılarla eşleştirilmiş durumda olduğunu görüyoruz. 128 adet sayı 7 bite karşılık gelir (2⁷=128). Yani 7 bit ile gösterilebilecek son sayı 127‘dir. Dolayısıyla ASCII 7 bitlik bir sistemdir.
ASCII tablosunu şöyle bir incelediğimizde ilk 32 öğenin göze ilk başta anlamsız görünen birtakım karakterlerden oluştuğunu görüyoruz:
Aslında bu karakter salatası arasında bizim tanıdığımız birkaç karakter de yok değil. Mesela 9. sıradaki \t öğesinin sekme oluşturan kaçış dizisi olduğunu söyledik. Aynı şekilde, 10. sıradaki \n öğesinin satır başına geçiren kaçış dizisi olduğunu, 13. sıradaki \r öğesinin ise satırı başa alan kaçış dizisi olduğunu da biliyoruz. Bu tür karakterler ‘basılamayan’ (non-printing) karakterlerdir. Yani mesela ekranda görüntülenebilen ‘a’, ‘b’, ‘c’, ‘!’, ‘?’, ‘=’gibi karakterlerden farklı olarak bu ilk 32 karakter ekranda görünmez. Bunlara aynı zamanda ‘kontrol karakterleri’ (control characters) adı da verilir. Çünkü bu karakterler ekranda görüntülenmek yerine, metnin akışını kontrol eder. Bu karakterlerin ne işe yaradığını şu tabloyla tek tek gösterebiliriz :
SayıKarakterSayıKarakter0boş16veri bağlantısından çık1başlık başlangıcı17aygıt denetimi 12metin başlangıcı18aygıt denetimi 23metin sonu19aygıt denetimi 34aktarım sonu20aygıt denetimi 45sorgu21olumsuz bildirim6bildirim22zaman uyumlu boşta kalma7zil23aktarım bloğu sonu8geri al24iptal9yatay sekme25ortam sonu10satır besleme/yeni satır26değiştir11dikey sekme27çık12form besleme/yeni sayfa28dosya ayırıcısı13satır başı29grup ayırıcısı14dışarı kaydır30kayıt ayırıcısı15içeri kaydır31birim ayırıcısı
Gördüğünüz gibi, bunlar birer harf, sayı veya noktalama işareti değil. O yüzden bu karakterler ekranda görünmez. Ama bir metindeki veri, satır ve paragraf düzeninin nasıl olacağını, metnin nerede başlayıp nerede biteceğini ve nasıl görüneceğini kontrol ettikleri için önemlidirler.
Geri kalan sayılar ise doğrudan karakterlere, sayılara ve noktalama işaretlerine tahsis edilmiştir:
İşte 32 ile 127 arası sayılarla eşleştirilen yukarıdaki karakterler yardımıyla metin ihtiyaçlarımızın büyük bölümünü karşılayabiliriz. Yani ASCII adı verilen bu eşleştirme tablosu sayesinde bilgisayarların sayılarla birlikte karakterleri de işleyebilmesini sağlayabiliriz.
1960’lı yıllara gelindiğinde, bilgisayarlar 8 bit uzunluğundaki verileri işleyebiliyordu. Yani, ASCII sisteminin gerçeklendiği (yani hayata geçirildiği) bilgisayarlar 8 bitlik bir kapasiteye sahipti. Bu 8 bitin 7 biti karakterle ayrılmıştı. Dolayısıyla mevcut bütün karakterler 7 bitlik bir alana sığdırılmıştı. Boşta kalan 8. bit ise, veri aktarımının düzgün gerçekleştirilip gerçekleştirilmediğini denetlemek amacıyla ‘doğruluk kontrolü’ için kullanılıyordu. Bu kontrole teknik olarak ‘eşlik denetimi’ (parity check), bu eşlik denetimini yapmamızı sağlayan bit’e ise ‘eşlik biti’ (parity bit) adı verildiğini biliyorsunuz.
Adından da anlaşılacağı gibi, ASCII bir Amerikan standardıdır. Dolayısıyla hazırlanışında İngilizce temel alınmıştır. Zaten ASCII tablosunu incelediğinizde, bu tabloda Türkçeye özgü harflerin bulunmadığını göreceksiniz. Bu sebepten, bu standart ile mesela Türkçeye özgü karakterleri gösteremeyiz. Çünkü ASCII standardında ‘ş’, ‘ç’, ‘ğ’ gibi harfler kodlanmamıştır. Özellikle Python’ın 2.x serisini kullanmış olanlar, ASCII’nin bu yetersizliğinin nelere sebep olduğunu gayet iyi bilir. Python’ın 2.x serisinde mesela doğrudan şöyle bir kod yazamayız.
“Merhaba Şirin Baba!’’ adlı karakter dizisinde geçen ‘Ş’ harfi ASCII dışı bir karakterdir. Yani bu harf ASCII ile temsil edilemez. O yüzden böyle bir kod yazıp bu kodu çalıştırdığımızda Python bize bir hata mesajı gösterecektir.
ASCII’nin her ne kadar yukarıda bahsettiğimiz eksiklikleri olsa da bu standart son derece yaygındır ve piyasada bulunan pek çok sistemde kullanılmaya devam etmektedir. Örneğin kullanıcı adı ve parola soran hemen hemen bütün sistemler bu ASCII tablosunu temel alır veya bu tablodan etkilenmiştir. O yüzden çoğu yerde kullanıcı adı ve/veya parola belirlerken Türkçe karakterleri kullanamayız. Hatta pek çok yazı tipinde yalnızca ASCII tablosunda yer alan karakterlerin karşılığı bulunur. Bu yüzden, mesela blogunuzda kullanmak üzere seçip beğendiğiniz çoğu yazı tipi ‘ş’, ‘ç’, ‘ğ’, ‘ö’ gibi harfleri göstermeyebilir. Yukarıda ‘Merhaba Şirin Baba!’ örneğinde de gösterdiğimiz gibi, Python’ın 2.x serisinde de öntanımlı olarak ASCII kodlama biçimi kullanılıyordu. O yüzden Python’ın 2.x sürümlerinde Türkçe karakterleri gösterebilmek için daha fazla ilave işlem yapmak zorunda kalıyorduk.
Sözün özü, eğer yazdığımız veya kendimiz yazmamış da olsakda herhangi bir sebeple kullanmakta olduğunuz bir programda Türkçe karakterlere ilişkin bir hata alabiliriz, bu durumun en muhtemel sebebi, kullandığınız programın veya sistemin, doğrudan ASCII’yi veya ASCII’ye benzer başka bir sistemi temel alarak çalışıyor olmasıdır. ASCII tablosunda görünen 128 karakter dışında kalan hiçbir karakter ASCII ile kodlanamayacağı için, özellikle farklı dillerin kullanıldığı bilgisayarlarda çalışan programlar kaçınılmaz olarak karakterlere ilişkin pek çok hata verecektir. Örneğin, karakter kodlamalarına ilişkin olarak yukarıda bahsettiğimiz ayrıntılardan habersiz bir Amerikalı programcının yazdığı bir programa Türkçe veri girdiğinizde bu program bir anda tuhaf görünen hatalar verip çökecektir…
Genişletilmiş ASCII
ASCII 7 bitlik bir karakter kümesidir. Bu standardın ilk çıktığı dönemde 8. bitin hata kontrolü için kullanılmıştır. Sonraki yıllarda 8. bitin hata kontrolü için kullanılmasından vazgeçildi. Böylece 8. bit yine boşa düşmüş oldu. Bu bitin boşa düşmesi ile elimizde yine toplam 128 karakterlik bir boşluk olmuş oldu. Dediğimiz gibi 7 bit ile toplam 128 sayı-karakter eşleştirilebilirken, 8 bit ile toplam 256 sayı-karakter eşleştirilebilir.
İşte bu fazla bit, farklı kişi, kurum ve organizasyonlar tarafından, İngilizcede bulunmayan ama başka dillerde bulunan karakterleri temsil etmek için kullanıldı. Ancak elbette bu fazladan bitin sağladığı 128 karakter de dünyadaki bütün karakterlerin temsil edilmesine yetmez. Bu yüzden 8. bitin sunduğu boşluk, birbirinden farklı karakterleri gösteren çeşitli tabloların ortaya çıkmasına sebep oldu. Bu birbirinden farklı tablolara genel olarak ‘kod sayfası’ adı verilir. Örneğin Microsoft şirketinin Türkiye’ye gönderdiği bilgisayarlarda tanımlı ‘cp857’ adlı kod sayfasında 128 ile 256 aralığında Türkçe karakterlere de yer verilmişti
Bu tabloya baktığınızda baştan 128’e kadar olan karakterlerin standart ASCII tablosu ile aynı olduğunu göreceksiniz. 128. karakterden itibaren ise Türkçeye özgü harfler tanımlanır. Mesela bu tabloda 128. karakter Türkçedeki büyük ‘ç’ harfi iken, 159. karakter küçük ‘ş’ harfidir. Bu arada bu sayıların onaltılı sayma düzenine göre olduğunu biliyorsunuz.
Burada karakter dizilerinin encode() adlı metodunu kullandığımıza dikkat etmeliyiz. Bu metot yardımıyla herhangi bir karakteri herhangi bir karakter kodlama sistemine göre kodlayabiliriz.
cp857 numaralı kod sayfasında ‘Ç’ ve ‘ş’ harfleri yer aldığı için, biz bu harfleri o kod sayfasına göre kodlayabiliyoruz. Ama mesela ASCII kodlama sisteminde bu harfler bulunmaz. O yüzden bu harfleri ASCII sistemine göre kodlayamayız.
Gerçekten de onlu sistemde 199 sayısına karşılık gelen bu onaltılı ‘\xc7’sayısı ASCII’nin kapsadığı sayı aralığının dışında kalmakta, bu yüzden de ASCII kod çözücüsü ile kodlanamamaktadır.
Genişletilmiş ASCII sisteminde 128 ile 256 aralığı için pek çok farklı karakter eşleştirme tabloları kullanılıyordu. Mesela Microsoft şirketi bu aralık için kendine özgü birtakım kod sayfaları tasarlamıştı. Bu kod sayfalarına örnek olarak yukarıda cp857 ve cp708 numaralı kod sayfalarını örnek vermiştim.
Elbette 128 ile 256 aralığını dolduran, yalnızca Microsoft’a ait kod sayfaları yoktu piyasada. Aynı aralığı farklı karakterlerle dolduran pek çok başka eşleştirme tablosu da dolaşıyordu etrafta. Örneğin özellikle Batı Avrupa dillerindeki karakterleri temsil edebilmek için oluşturulmuş ‘latin1’ (öbür adıyla ISO-8859–1) adlı karakter kümesi bugün de yaygın olarak kullanılan sistemlerinden biridir. Almancada olup da ASCII sistemi ile temsil edilemeyen ‘ö’, ‘ß’, ‘ü’ gibi harfler ve Fransızcada olup da yine ASCII sistemi ile temsil edilemeyen ‘ç’ ve ‘é’ gibi harfler bu karakter kümesinde temsil edilebiliyordu
Yalnız burada önemli bir ayrıntıyı not düşmek gerekiyor. ‘Genişletilmiş ASCII’, standart ASCII gibi genel kabul görmüş tek bir sistem değildir. Genişletilmiş ASCII dediğimizde zaten tek bir karakter kümesi akla gelmiyor. Dolayısıyla ASCII dendiğinde anlamamız gereken şey 128 karakterlik bir sayı-karakter eşleştirme tablosudur. ASCII hiçbir zaman bu 128 karakterin ötesine geçip de 256 karakterlik bir aralığı temsil etmiş değildir. Dolayısıyla 127. sayının ötesindeki karakterleri kapsayan sistem ASCII değildir. ‘Genişletilmiş ASCII’ kavramı, temel ASCII sisteminde temsil edilen sayı-karakter çiftlerinin pek çok farklı kurum ve kuruluş tarafından birbirinden farklı biçimlerde ‘genişletilmesiyle’ oluşturulmuş, ancak ASCII’nin kendisi kadar standartlaşamamış bir sistemler bütünüdür. Bu sistem içinde pek çok farklı kod sayfası (veya karakter kümesi) yer alır. Tek başına ‘Genişletilmiş ASCII’ ifadesi açıklayıcı olmayıp; ASCII’nin hangi karakter kümesine göre genişletildiğinin de belirtilmesi gerekir.
ASCII bilgisayarlar arasında güvenli bir şekilde veri aktarımını sağlamak için atılmış en önemli ve en başarılı adımlardan bir tanesidir. Bu güçlü standart sayesinde uzun yıllar bilgisayarlar arası temel iletişim başarıyla sağlandı. Ancak bu standardın zayıf kaldığı nokta 7 bitlik olması ve boşta kalan 8. bitin tek başına dünyadaki bütün dilleri temsil etmeye yeterli olmamasıdır.
ASCII standardı, her karakterin 1 bayt ile temsil edilebileceği varsayımı üzerine kurulmuştur. Bildiğiniz gibi, 1 bayt (geleneksel olarak) 8 bit’e karşılık gelir. Peki 1 bayt’ın 8 bit’e karşılık gelmesinin nedeni nedir? Aslında bunun özel bir nedeni yok. 1 destede neden 10 öğe, 1 düzinede de 12 öğe varsa, 1 bayt’ta da 8 bit vardır… Yani biz insanlar öyle olmasına karar verdiğimiz için 1 destede 10 öğe, 1 düzinede 12 öğe, 1 bayt’ta ise 8 bit vardır.
Dediğimiz gibi ASCII standardı 7 bitlik bir sistemdir. Yani bu standartta en büyük sayı olan 127 yalnızca 7 bit ile gösterilebilir.
127 sayısı 7 bit ile gösterilebilecek son sayıdır.
8 bitlik bir sistem olan Genişletilmiş ASCII ise 0 ile 255 arası sayıları temsil edebilir.
255 sayısı 8 bit ile gösterilebilecek son sayıdır.
Dolayısıyla ASCII’de ve Genişletilmiş ASCII’de 1 baytlık alana toplam 256 karakter sığdırılabilir. Eğer daha fazla karakteri temsil etmek isterseniz 1 bayttan fazla bir alana ihtiyaç duyarız.