Not
Bu sayfaya erişim yetkilendirme gerektiriyor. Oturum açmayı veya dizinleri değiştirmeyi deneyebilirsiniz.
Bu sayfaya erişim yetkilendirme gerektiriyor. Dizinleri değiştirmeyi deneyebilirsiniz.
Bu makalede .NET tarafından kullanılan karakter kodlama sistemlerine giriş bilgileri sağlanmaktadır. Makalede, , String, Charve Rune türlerinin StringInfoUnicode, UTF-16 ve UTF-8 ile nasıl çalıştığı açıklanmaktadır.
Karakter terimi burada bir okuyucunun tek bir görüntü öğesi olarak algıladığı genel anlamda kullanılır. Yaygın örnekler arasında "a" harfi, "@" simgesi ve "🐂" emojisi yer alır. Bazen tek bir karaktere benzeyen şey, grapheme kümelerindeki bölümde açıklandığı gibi birden çok bağımsız görüntü öğesinden oluşur.
string ve char türleri
Sınıfın string bir örneği bazı metinleri temsil eder. A string
mantıksal olarak 16 bit değerlerden oluşan bir dizidir ve bunların her biri yapının bir örneğidir char . .string Length özelliği örnekteki char
örnek sayısını string
döndürür.
Aşağıdaki örnek işlev, içindeki char
tüm örneklerin onaltılık gösterimindeki string
değerleri yazdırır:
void PrintChars(string s)
{
Console.WriteLine($"\"{s}\".Length = {s.Length}");
for (int i = 0; i < s.Length; i++)
{
Console.WriteLine($"s[{i}] = '{s[i]}' ('\\u{(int)s[i]:x4}')");
}
Console.WriteLine();
}
string "Hello" işlevini bu işleve geçirdiğinizde aşağıdaki çıkışı alırsınız:
PrintChars("Hello");
"Hello".Length = 5
s[0] = 'H' ('\u0048')
s[1] = 'e' ('\u0065')
s[2] = 'l' ('\u006c')
s[3] = 'l' ('\u006c')
s[4] = 'o' ('\u006f')
Her karakter tek char
bir değerle temsil edilir. Bu düzen, dünyanın çoğu dili için geçerlidir. Örneğin, nǐ hǎo ve ortalama Hello gibi görünen iki Çince karakterin çıkışı aşağıda verilmiştır:
PrintChars("你好");
"你好".Length = 2
s[0] = '你' ('\u4f60')
s[1] = '好' ('\u597d')
Ancak, bazı diller ve bazı semboller ve emojiler için tek bir karakteri temsil etmek için iki char
örnek gerekir. Örneğin, Osage dilinde Osagechar
sözcükteki karakterleri ve örnekleri karşılaştırın:
PrintChars("𐓏𐓘𐓻𐓘𐓻𐓟 𐒻𐓟");
"𐓏𐓘𐓻𐓘𐓻𐓟 𐒻𐓟".Length = 17
s[0] = '�' ('\ud801')
s[1] = '�' ('\udccf')
s[2] = '�' ('\ud801')
s[3] = '�' ('\udcd8')
s[4] = '�' ('\ud801')
s[5] = '�' ('\udcfb')
s[6] = '�' ('\ud801')
s[7] = '�' ('\udcd8')
s[8] = '�' ('\ud801')
s[9] = '�' ('\udcfb')
s[10] = '�' ('\ud801')
s[11] = '�' ('\udcdf')
s[12] = ' ' ('\u0020')
s[13] = '�' ('\ud801')
s[14] = '�' ('\udcbb')
s[15] = '�' ('\ud801')
s[16] = '�' ('\udcdf')
Yukarıdaki örnekte, boşluk dışındaki her karakter iki char
örnekle temsil edilir.
Aşağıdaki örnekte görüldüğü gibi bir öküz emojisini gösteren tek bir Unicode emojisi de iki char
sn ile temsil edilir:
"🐂".Length = 2
s[0] = '�' ('\ud83d')
s[1] = '�' ('\udc02')
Bu örneklerde, örnek sayısını string.Length
gösteren değerinin char
görüntülenen karakter sayısını belirtmesi gerekmeyebilir. Tek char
bir örnek tek başına bir karakteri temsil etmez.
Tek char
bir karaktere eşleyen çiftlere vekil çiftler denir. Bunların nasıl çalıştığını anlamak için Unicode ve UTF-16 kodlamasını anlamanız gerekir.
Unicode kod noktaları
Unicode, çeşitli platformlarda ve çeşitli diller ve betiklerle kullanılmak üzere uluslararası bir kodlama standardıdır.
Unicode Standardı 1,1 milyondan fazla kod noktası tanımlar. Kod noktası, 0 U+10FFFF
ile (ondalık 1.114.111) arasında bir tamsayı değeridir. Bazı kod noktaları harflere, simgelere veya emojilere atanır. Diğerleri, yeni satıra ilerleme gibi metin veya karakterlerin nasıl görüntüleneceğini denetleyebilen eylemlere atanır. Birçok kod noktası henüz atanmadı.
Burada, göründükleri Unicode grafiklerin bağlantılarını içeren kod noktası atamalarına bazı örnekler verilmiştir:
Ondalık | Onaltılık | Örnek | Açıklama |
---|---|---|---|
10 | U+000A |
Yok | SATIR BESLEME |
97 | U+0061 |
a | LATIN KÜÇÜK A HARFI |
562 | U+0232 |
Ȳ | MACRON IÇEREN LATIN BÜYÜK Y HARFI |
68,675 | U+10C43 |
𐱃 | ESKİ TÜRK HARFİ ORHUN AT |
127,801 | U+1F339 |
🌹 | GÜL emojisi |
Kod noktalarına genellikle söz dizimi U+xxxx
kullanılarak başvurulur; burada xxxx
onaltılık kodlanmış tamsayı değeridir.
Kod noktalarının tam aralığı içinde iki alt yer vardır:
- aralığındaki . Bu 16 bitlik aralık, dünyanın yazma sistemlerinin çoğunu kapsayacak kadar 65.536 kod noktası sağlar.
- . Bu 21 bitlik aralık, daha az bilinen diller ve emojiler gibi diğer amaçlar için kullanılabilecek bir milyondan fazla ek kod noktası sağlar.
Aşağıdaki diyagramda BMP ile ek kod noktaları arasındaki ilişki gösterilmektedir.
UTF-16 kod birimleri
16 bit Unicode Dönüştürme Biçimi (UTF-16), Unicode kod noktalarını temsil etmek için 16 bit kod birimleri kullanan bir karakter kodlama sistemidir. .NET, içindeki string
metni kodlamak için UTF-16 kullanır. Örnek char
, 16 bit kod birimini temsil eder.
Tek bir 16 bit kod birimi, Temel Çok Dilli Düzlem'in 16 bit aralığındaki herhangi bir kod noktasını temsil edebilir. Ancak ek aralıktaki bir kod noktası için iki char
örnek gerekir.
Vekil çiftler
İki 16 bit değerin tek bir 21 bit değere çevirisi, U+D800
vekil kod noktalarıU+DFFF
özel bir aralıkla (ondalık 55.296 ile 57.343 arasında) (dahil) kolaylaştırılır.
Aşağıdaki diyagramda BMP ile vekil kod noktaları arasındaki ilişki gösterilmektedir.
Yüksek vekil kod noktası () hemen ardından düşük vekilU+D800..U+DBFF
kod noktası ()U+DC00..U+DFFF
geldiğinde, çift aşağıdaki formül kullanılarak tamamlayıcı kod noktası olarak yorumlanır:
code point = 0x10000 +
((high surrogate code point - 0xD800) * 0x0400) +
(low surrogate code point - 0xDC00)
Ondalık gösterimi kullanan formül şu şekildedir:
code point = 65,536 +
((high surrogate code point - 55,296) * 1,024) +
(low surrogate code point - 56,320)
Yüksek vekil kod noktası, düşük vekil kod noktasından daha yüksek bir sayı değerine sahip değildir. 20 bit kod noktası aralığının daha yüksek sıralı 10 bitini hesaplamak için kullanıldığından, yüksek vekil kod noktası "yüksek" olarak adlandırılır. Düşük vekil kod noktası, alt sıralı 10 bitleri hesaplamak için kullanılır.
Örneğin, vekil çifte 0xD83C
karşılık gelen ve 0xDF39
aşağıdaki gibi hesaplanan gerçek kod noktası:
actual = 0x10000 + ((0xD83C - 0xD800) * 0x0400) + (0xDF39 - 0xDC00)
= 0x10000 + ( 0x003C * 0x0400) + 0x0339
= 0x10000 + 0xF000 + 0x0339
= 0x1F339
Ondalık gösterimi kullanan aynı hesaplama aşağıdadır:
actual = 65,536 + ((55,356 - 55,296) * 1,024) + (57,145 - 56320)
= 65,536 + ( 60 * 1,024) + 825
= 65,536 + 61,440 + 825
= 127,801
Yukarıdaki örnekte, "\ud83c\udf39"
daha önce bahsedilen kod noktasının UTF-16 kodlaması U+1F339 ROSE ('🌹')
gösterilmektedir.
Unicode skaler değerleri
Unicode skaler değeri terimi, vekil kod noktaları dışındaki tüm kod noktalarına başvurur. Başka bir deyişle, skaler değer, bir karakter atanmış veya gelecekte bir karakter atanabilecek herhangi bir kod noktasıdır. Buradaki "Karakter", metin veya karakterlerin nasıl görüntüleneceğini denetleyen eylemler gibi öğeleri içeren bir kod noktasına atanabilen her şeyi ifade eder.
Aşağıdaki diyagramda skaler değer kod noktaları gösterilmektedir.
Rune Skaler değer olarak tür
Önemli
Türü Rune
.NET Framework'te kullanılamaz.
.NET'te tür, System.Text.Rune Unicode skaler değerini temsil eder.
Oluşturucular Rune
, sonuçta elde edilen örneğin geçerli bir Unicode skaler değeri olduğunu doğrular, aksi takdirde bir özel durum oluştururlar. Aşağıdaki örnekte, giriş geçerli skaler değerleri temsil ettiğinden örnekleri başarıyla oluşturan Rune
kod gösterilmektedir:
Rune a = new Rune('a');
Rune b = new Rune(0x0061);
Rune c = new Rune('\u0061');
Rune d = new Rune(0x10421);
Rune e = new Rune('\ud801', '\udc21');
Aşağıdaki örnek, kod noktası vekil aralıkta olduğundan ve vekil çiftin parçası olmadığından bir özel durum oluşturur:
Rune f = new Rune('\ud801');
Aşağıdaki örnek, kod noktası tamamlayıcı aralığın ötesinde olduğundan bir özel durum oluşturur:
Rune g = new Rune(0x12345678);
Rune kullanım örneği: harf servis talebini değiştirme
alan char
ve skaler değer olan bir kod noktasıyla çalıştığını varsayan bir API, vekil çiftten geliyorsa char
düzgün çalışmaz. Örneğin, içindeki Char.ToUpperInvarianther char birini çağıran string aşağıdaki yöntemi göz önünde bulundurun:
// THE FOLLOWING METHOD SHOWS INCORRECT CODE.
// DO NOT DO THIS IN A PRODUCTION APPLICATION.
static string ConvertToUpperBadExample(string input)
{
StringBuilder builder = new StringBuilder(input.Length);
for (int i = 0; i < input.Length; i++) /* or 'foreach' */
{
builder.Append(char.ToUpperInvariant(input[i]));
}
return builder.ToString();
}
input
string küçük harf Deseret ()er
𐑉
içeriyorsa, bu kod büyük harfe (𐐡
) dönüştürmez. Kod, char.ToUpperInvariant
her vekil kod noktasında ve U+D801
üzerinde ayrı olarak çağrılarU+DC49
. Ancak U+D801
, küçük harf olarak tanımlamak için tek başına yeterli bilgiye sahip değildir, bu nedenle char.ToUpperInvariant
onu yalnız bırakır. Ve aynı şekilde işler U+DC49
. Sonuç, içindeki input
string küçük harfli '𐑉' büyük harfe dönüştürülmezse '𐑉' olur.
A'yi büyük harfe doğru dönüştürmeye string yönelik iki seçenek şunlardır:
-by-yinelemesiString.ToUpperInvariantstring yerine girişi
char
çağırınchar
.string.ToUpperInvariant
yöntemi, her vekil çiftin her iki bölümüne de erişebilir, bu nedenle tüm Unicode kod noktalarını doğru şekilde işleyebilir.Aşağıdaki örnekte gösterildiği gibi Unicode skaler değerlerini örnekler yerine
Rune
örnekler olarakchar
yineleyebilirsiniz. ÖrnekRune
geçerli bir Unicode skaler değeri olduğundan, skaler değer üzerinde çalışması beklenen API'lere geçirilebilir. Örneğin, aşağıdaki örnekte gösterildiği gibi çağırma Rune.ToUpperInvariant doğru sonuçlar verir:static string ConvertToUpper(string input) { StringBuilder builder = new StringBuilder(input.Length); foreach (Rune rune in input.EnumerateRunes()) { builder.Append(Rune.ToUpperInvariant(rune)); } return builder.ToString(); }
Diğer Rune API'ler
Türü, Rune
API'lerin birçoğunun char
analoglarını ortaya çıkarır. Örneğin, aşağıdaki yöntemler türündeki char
statik API'leri yansıtır:
Bir Rune
örnekten ham skaler değeri almak için özelliğini kullanın Rune.Value .
Bir Rune
örneği bir diziye char
geri dönüştürmek için veya Rune.ToString yöntemini kullanınRune.EncodeToUtf16.
Herhangi bir Unicode skaler değeri tek char
bir veya vekil çift tarafından temsil edilebilir olduğundan, herhangi bir Rune
örnek en fazla 2 char
örnekle temsil edilebilir. Bir Rune.Utf16SequenceLength örneği temsil etmek için kaç char
örnek gerektiğini görmek için kullanınRune
.
.NET Rune
türü hakkında daha fazla bilgi için bkz Rune
. API başvurusu.
Grapheme kümeleri
Bir karaktere benzeyen şey birden çok kod noktası birleşiminden kaynaklanabilir, bu nedenle genellikle "karakter" yerine kullanılan daha açıklayıcı bir terim grapheme kümesidir. .NET'teki eşdeğer terim metin öğesidir.
string
"a", "á", "á" ve "👩🏽🚒
" örneklerini göz önünde bulundurun. İşletim sisteminiz bunları Unicode standardı tarafından belirtilen şekilde işlerse, bu string
örneklerin her biri tek bir metin öğesi veya grapheme kümesi olarak görünür. Ancak son ikisi birden fazla skaler değer kod noktasıyla temsil edilir.
string "a" bir skaler değerle temsil edilir ve bir
char
örnek içerir.U+0061 LATIN SMALL LETTER A
string "á" bir skaler değerle temsil edilir ve bir
char
örnek içerir.U+00E1 LATIN SMALL LETTER A WITH ACUTE
"á", string "á" ile aynı görünür, ancak iki skaler değerle temsil edilir ve iki
char
örnek içerir.U+0061 LATIN SMALL LETTER A
U+0301 COMBINING ACUTE ACCENT
Son olarak, string "
👩🏽🚒
" dört skaler değerle temsil edilir ve yedichar
örnek içerir.-
U+1F469 WOMAN
(ek aralık, vekil çift gerektirir) -
U+1F3FD EMOJI MODIFIER FITZPATRICK TYPE-4
(ek aralık, vekil çift gerektirir) U+200D ZERO WIDTH JOINER
-
U+1F692 FIRE ENGINE
(ek aralık, vekil çift gerektirir)
-
Önceki örneklerden bazılarında (örneğin, birleşen vurgu değiştirici veya dış görünüm tonu değiştiricisi) kod noktası ekranda tek başına bir öğe olarak görüntülenmez. Bunun yerine, ondan önce gelen bir metin öğesinin görünümünü değiştirmeye hizmet eder. Bu örnekler, tek bir "karakter" veya "grapheme kümesi" olarak düşündüğümüz şeyi oluşturmak için birden çok skaler değerin gerekebileceğini göstermektedir.
bir string
öğesinin grapheme kümelerini listelemek için aşağıdaki örnekte gösterildiği gibi sınıfını kullanın StringInfo . Swift'i biliyorsanız .NET StringInfo
türü kavramsal olarak Swift'in character
türüne benzer.
Örnek: count char, Rune, ve text öğesi örnekleri
.NET API'lerinde grapheme kümesine metin öğesi adı verilir. Aşağıdaki yöntem, içindeki char
, Rune
ve metin öğesi örnekleri arasındaki string
farkları gösterir:
static void PrintTextElementCount(string s)
{
Console.WriteLine(s);
Console.WriteLine($"Number of chars: {s.Length}");
Console.WriteLine($"Number of runes: {s.EnumerateRunes().Count()}");
TextElementEnumerator enumerator = StringInfo.GetTextElementEnumerator(s);
int textElementCount = 0;
while (enumerator.MoveNext())
{
textElementCount++;
}
Console.WriteLine($"Number of text elements: {textElementCount}");
}
PrintTextElementCount("a");
// Number of chars: 1
// Number of runes: 1
// Number of text elements: 1
PrintTextElementCount("á");
// Number of chars: 2
// Number of runes: 2
// Number of text elements: 1
PrintTextElementCount("👩🏽🚒");
// Number of chars: 7
// Number of runes: 4
// Number of text elements: 1
Örnek: örnekleri bölme string
Örnekleri bölerken string
vekil çiftleri ve grapheme kümelerini bölmekten kaçının. aşağıdaki hatalı kod örneğini düşünün. Bu örnek, içindeki her 10 karakterde bir stringsatır sonları eklemeyi amaçlıyor:
// THE FOLLOWING METHOD SHOWS INCORRECT CODE.
// DO NOT DO THIS IN A PRODUCTION APPLICATION.
static string InsertNewlinesEveryTencharsBadExample(string input)
{
StringBuilder builder = new StringBuilder();
// First, append chunks in multiples of 10 chars
// followed by a newline.
int i = 0;
for (; i < input.Length - 10; i += 10)
{
builder.Append(input, i, 10);
builder.AppendLine(); // newline
}
// Then append any leftover data followed by
// a final newline.
builder.Append(input, i, input.Length - i);
builder.AppendLine(); // newline
return builder.ToString();
}
Bu kod örnekleri numaralandırdığından char
, bir 10char
sınırında bir araya gelen bir vekil çift bölünür ve bunların arasına yeni bir satır eklenir. Yedek kod noktaları yalnızca çiftler olarak anlamlı olduğundan bu ekleme veri bozulmasına neden olur.
Örnekler yerine Rune
örnekleri (skaler değerler) numaralandırırsanız char
veri bozulması olasılığı ortadan kaldırılamaz. Bir örnek kümesi Rune
, 10char
sınırına sahip bir grapheme kümesi oluşturur. Grapheme kümesi bölünmüşse, doğru yorumlanamaz.
Daha iyi bir yaklaşım, aşağıdaki örnekte olduğu gibi grafeme kümelerini veya metin öğelerini sayarak bölmektir string :
static string InsertNewlinesEveryTenTextElements(string input)
{
StringBuilder builder = new StringBuilder();
// Append chunks in multiples of 10 chars
TextElementEnumerator enumerator = StringInfo.GetTextElementEnumerator(input);
int textElementCount = 1;
while (enumerator.MoveNext())
{
builder.Append(enumerator.Current);
if (textElementCount % 10 == 0)
{
builder.AppendLine(); // newline
}
textElementCount++;
}
// Add a final newline.
builder.AppendLine(); // newline
return builder.ToString();
}
Daha önce belirtildiği gibi, .NET 5'in StringInfo
öncesinde sınıfta bazı grapheme kümelerinin yanlış işlenmesine neden olan bir hata vardı.
UTF-8 ve UTF-32
Yukarıdaki bölümler UTF-16'ya odaklanmıştır çünkü .NET örnekleri kodlamak string
için bunu kullanır. Unicode - UTF-8 ve UTF-32 için başka kodlama sistemleri de vardır. Bu kodlamalar sırasıyla 8 bit kod birimlerini ve 32 bit kod birimlerini kullanır.
UTF-16 gibi UTF-8 de bazı Unicode skaler değerleri temsil etmek için birden çok kod birimi gerektirir. UTF-32, tek bir 32 bit kod birimindeki herhangi bir skaler değeri temsil edebilir.
Bu üç Unicode kodlama sisteminin her birinde aynı Unicode kod noktasının nasıl gösterildiğini gösteren bazı örnekler aşağıda verilmiştir:
Scalar: U+0061 LATIN SMALL LETTER A ('a')
UTF-8 : [ 61 ] (1x 8-bit code unit = 8 bits total)
UTF-16: [ 0061 ] (1x 16-bit code unit = 16 bits total)
UTF-32: [ 00000061 ] (1x 32-bit code unit = 32 bits total)
Scalar: U+0429 CYRILLIC CAPITAL LETTER SHCHA ('Щ')
UTF-8 : [ D0 A9 ] (2x 8-bit code units = 16 bits total)
UTF-16: [ 0429 ] (1x 16-bit code unit = 16 bits total)
UTF-32: [ 00000429 ] (1x 32-bit code unit = 32 bits total)
Scalar: U+A992 JAVANESE LETTER GA ('ꦒ')
UTF-8 : [ EA A6 92 ] (3x 8-bit code units = 24 bits total)
UTF-16: [ A992 ] (1x 16-bit code unit = 16 bits total)
UTF-32: [ 0000A992 ] (1x 32-bit code unit = 32 bits total)
Scalar: U+104CC OSAGE CAPITAL LETTER TSHA ('𐓌')
UTF-8 : [ F0 90 93 8C ] (4x 8-bit code units = 32 bits total)
UTF-16: [ D801 DCCC ] (2x 16-bit code units = 32 bits total)
UTF-32: [ 000104CC ] (1x 32-bit code unit = 32 bits total)
Daha önce belirtildiği gibi, vekil çiftten alınan tek bir UTF-16 kod birimi tek başına anlamsızdır. Aynı şekilde, tek bir UTF-8 kod birimi, skaler değeri hesaplamak için kullanılan iki, üç veya dört bir dizideyse tek başına anlamsızdır.
Not
C# 11 ile başlayarak, bir değişmez değer üzerinde "u8 string " sonekini kullanarak UTF-8 değişmez değerlerini stringtemsil edebilirsiniz. UTF-8 string değişmez değerleri hakkında daha fazla bilgi için C# Kılavuzu'ndaki yerleşik başvuru türleriylestringmakalenin "değişmez değerler" bölümüne bakın.
Bayt Sırası
.NET'te, bir string öğesinin UTF-16 kod birimleri, 16 bit tamsayıların (char
örnekler) dizisi olarak bitişik bellekte depolanır. Tek tek kod birimlerinin bitleri, geçerli mimarinin son hali doğrultusunda düzenlenir.
Küçük bir endian mimaride string UTF-16 kod noktalarından [ D801 DCCC ]
oluşan, bellekte bayt [ 0x01, 0xD8, 0xCC, 0xDC ]
olarak düzenlenir. Aynı değerin string bellekte bayt [ 0xD8, 0x01, 0xDC, 0xCC ]
olarak yerleştirileceği büyük endian mimaride.
Birbirleriyle iletişim kuran bilgisayar sistemleri, verilerin kablodan geçen temsili konusunda anlaşmalıdır. Çoğu ağ protokolü, metin aktarırken standart olarak UTF-8 kullanır ve kısmen küçük bir endian makineyle iletişim kurabilen büyük endian bir makineden kaynaklanan sorunlardan kaçınmak için kullanılır.
string UTF-8 kod noktalarından oluşan her [ F0 90 93 8C ]
zaman sonianstan bağımsız olarak bayt [ 0xF0, 0x90, 0x93, 0x8C ]
olarak temsil edilir.
UtF-8'i metin iletiminde kullanmak için .NET uygulamaları genellikle aşağıdaki örneğe benzer bir kod kullanır:
string stringToWrite = GetString();
byte[] stringAsUtf8Bytes = Encoding.UTF8.GetBytes(stringToWrite);
await outputStream.WriteAsync(stringAsUtf8Bytes, 0, stringAsUtf8Bytes.Length);
Yukarıdaki örnekte Encoding.UTF8.GetBytes yöntemi yerleştirir. Encoding.UTF8.GetString yöntemi ters dönüştürme gerçekleştirir ve utf-8 byte
dizisini UTF-16'ya string
dönüştürür.
Uyarı
UTF-8 İnternet'te yaygın olduğundan, kablodan ham baytları okumak ve verileri UTF-8 gibi işlemek cazip olabilir. Ancak, gerçekten iyi biçimlendirilmiş olduğunu doğrulamanız gerekir. Kötü amaçlı bir istemci, hizmetinize kötü biçimlendirilmiş UTF-8 gönderebilir. Bu veriler üzerinde iyi biçimlendirilmiş gibi çalışırsanız, uygulamanızda hatalara veya güvenlik açıklarına neden olabilir. UTF-8 verilerini doğrulamak için, gelen verileri öğesine dönüştürürken doğrulama gerçekleştiren gibi Encoding.UTF8.GetString
bir string
yöntem kullanabilirsiniz.
İyi biçimlendirilmiş kodlama
İyi biçimlendirilmiş Unicode kodlaması, string kesin olmayan ve hatasız olarak unicode skaler değerler dizisine çözülebilen kod birimlerinden oluşan bir kod birimidir. İyi biçimlendirilmiş veriler UTF-8, UTF-16 ve UTF-32 arasında serbestçe kodlanabilir.
Kodlama dizisinin iyi biçimlendirilmiş olup olmadığı sorusu, bir makinenin mimarisinin son durumuyla ilişkili değildir. Kötü biçimlendirilmiş UTF-8 dizisi hem büyük hem de küçük endian makinelerde aynı şekilde şekilsizdir.
Aşağıda, kötü biçimlendirilmiş kodlama örnekleri verilmiştir:
UTF-8'de sıra
[ 6C C2 61 ]
, tarafındanC2
izlenemediğinden61
kötü biçimlendirilmiş olur.UTF-16'da, düşük vekili başka bir düşük vekil
[ DC00 DD00 ]
string tarafından izlenemediğinden sıra"\udc00\udd00"
(veya C#DC00
DD00
dilinde) kötü biçimlendirilmiş olur.UTF-32'de sıra
[ 0011ABCD ]
, Unicode skaler değerler aralığının dışında olduğundan kötü biçimlendirilmiş0011ABCD
olur.
.NET'te string
örnekler neredeyse her zaman iyi biçimlendirilmiş UTF-16 verileri içerir, ancak bu garanti değildir. Aşağıdaki örneklerde örneklerde string
kötü biçimlendirilmiş UTF-16 verileri oluşturan geçerli C# kodu gösterilmektedir.
Kötü biçimlendirilmiş bir değişmez değer:
const string s = "\ud800";
Vekil çifti bölen alt dize:
string x = "\ud83e\udd70"; // "🥰" string y = x.Substring(1, 1); // "\udd70" standalone low surrogate
Gibi Encoding.UTF8.GetString
API'ler hiçbir zaman kötü biçimlendirilmiş string
örnekler döndürmez.
Encoding.GetString
ve Encoding.GetBytes
yöntemleri girişteki hatalı biçimlendirilmiş dizileri algılar ve çıkışı oluştururken karakter değişimi gerçekleştirir. Örneğin, Encoding.ASCII.GetString(byte[])
girişte ASCII olmayan bir bayt görürse (U+0000..U+007F aralığının dışında), döndürülen string
örneğe bir '?' ekler.
Encoding.UTF8.GetString(byte[])
hatalı biçimlendirilmiş UTF-8 dizilerini döndürülen U+FFFD REPLACEMENT CHARACTER ('�')
örnekte ile string
değiştirir. Daha fazla bilgi için bkz . Unicode Standart, Bölüm 5.22 ve 3.9.
Yerleşik sınıflar, hatalı biçimlendirilmiş diziler görüldüğünde Encoding
karakter değiştirme gerçekleştirmek yerine bir özel durum oluşturacak şekilde de yapılandırılabilir. Bu yaklaşım genellikle karakter değişiminin kabul edilemeyebilir olduğu, güvenlik duyarlı uygulamalarda kullanılır.
byte[] utf8Bytes = ReadFromNetwork();
UTF8Encoding encoding = new UTF8Encoding(encoderShouldEmitUTF8Identifier: false, throwOnInvalidBytes: true);
string asString = encoding.GetString(utf8Bytes); // will throw if 'utf8Bytes' is ill-formed
Yerleşik sınıfları kullanma hakkında bilgi için bkz. .NET'te Encoding
karakter kodlama sınıflarını kullanma.