.NET içinde karakter kodlaması
Bu makalede.NET tarafından kullanılan acter kodlama sistemlerine chargiriş bilgileri sağlanmaktadır. Makalede, , Char, Runeve StringInfo türlerinin StringUnicode, UTF-16 ve UTF-8 ile nasıl çalıştığı açıklanmaktadır.
Acter terimichar burada okuyucunun tek bir görüntü öğesi olarak algıladıkça genel anlamda kullanılır. Yaygın örnekler arasında "a" harfi, "@" simgesi ve "🐂" emojisi yer alır. Bazen tek bir chareyleme 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 string
örnek sayısını char
döndürür.
Aşağıdaki örnek işlev, içindeki string
tüm örneklerin onaltılık gösterimindeki char
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 chareylem oluşturucu 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 chareylemcinin çıkışı aşağıda verilmiştir:
PrintChars("你好");
"你好".Length = 2
s[0] = '你' ('\u4f60')
s[1] = '好' ('\u597d')
Ancak, bazı diller ve bazı semboller ve emojiler için tek charbir eylemi temsil etmek için iki char
örnek gerekir. Örneğin, Osage dilinde Osage anlamına gelen sözcükteki eylemcileri ve char
örnekleri karşılaştırınchar:
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 chareylem oluşturucu 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ı char
gösteren değerinin string.Length
görüntülenen chareylemcilerin sayısını belirtmemesi gerekir. Tek char
bir örnek tek başına bir chareylemi temsil etmez.
Tek char
charbir eyleme 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 bir satıra ilerleme gibi metin veya chareylemcilerin nasıl görüntüleneceğini denetleyen eylemlere atanır. Birçok kod noktası henüz atanmadı.
Burada, göründükleri Unicode chart'lere bağlantılar içeren kod noktası atamalarına bazı örnekler verilmiştir:
Ondalık | Onaltılık | Örnek | Açıklama |
---|---|---|---|
10 | U+000A |
Yok | HAT 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 |
𐱃 | OLD TURKIC LETTER ORKHON 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
U+0000..U+FFFF
Temel Çok Dilli Düzlem (BMP) . Bu 16 bitlik aralık, dünyanın yazma sistemlerinin çoğunu kapsayacak kadar 65.536 kod noktası sağlar. - aralığındaki
U+10000..U+10FFFF
tamamlayıcı kod noktaları. 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üşüm Biçimi (UTF-16), Unicode kod noktalarını temsil etmek için 16 bit kod birimleri kullanan bir chareylemci 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
U+DFFF
vekil kod noktaları olarak adlandırılan ö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 vekilkod noktası ()U+D800..U+DBFF
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 chareylemciye atanan veya gelecekte bir eylemci atanabilen herhangi bir charkod noktasıdır. Buradaki "Karakter", bir kod noktasına atanabilen her şeyi ifade eder ve metin veya chareylem oluşturucuların nasıl görüntüleneceğini denetleyen eylemler gibi öğeler içerir.
Aşağıdaki diyagramda skaler değer kod noktaları gösterilmektedir.
Rune Skaler değer olarak tür
.NET Core 3.0 sürümünden System.Text.Rune başlayarak, tür bir Unicode skaler değerini temsil eder. Rune
.NET Core 2.x veya .NET Framework 4.x'te kullanılamaz.
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 stringher char birini çağıran Char.ToUpperInvariant 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, U+D801
her vekil kod noktasında ve U+DC49
üzerinde ayrı olarak çağrılarchar.ToUpperInvariant
. 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-yinelemesi
char
char
yerine girişi string çağırınString.ToUpperInvariant.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
char
örnekler olarakRune
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.EncodeToUtf16 yöntemini kullanınRune.ToString.
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
örneği temsil etmek için kaç char
örnek gerektiğini görmek için kullanınRune.Utf16SequenceLength.
.NET Rune
türü hakkında daha fazla bilgi için bkz Rune
. API başvurusu.
Grapheme kümeleri
Tek charbir eylemci birden çok kod noktası birleşiminden kaynaklanabilir, bu nedenle genellikle "character" 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 "acter" veya "chargrapheme 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 string
, Rune
ve metin öğesi örnekleri arasındaki char
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
Bu kodu .NET Framework veya .NET Core 3.1 veya önceki sürümlerinde çalıştırırsanız, emoji için metin öğesi sayısı gösterilir 4
. Bunun nedeni StringInfo
sınıfında .NET 5'te düzeltildi.
Ö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 stringher 10 chareylemciye satır sonu 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 char
örnekleri (skaler değerler) numaralandırırsanız Rune
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 && textElementCount > 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ürleriyle ilgili makalenin "stringdeğişmez değerler" bölümüne bakın.
Endianness
.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 UTF-16 string
kodunu bir dizi Unicode skaler değere geri çözer, ardından bu skaler değerleri UTF-8'e yeniden kodlar ve sonuçta elde edilen diziyi bir byte
diziye 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ından61
izlenemediğindenC2
kötü biçimlendirilmiş olur.UTF-16'da, düşük vekili başka bir düşük vekil
DD00
DC00
tarafından izlenemediğinden sıra[ DC00 DD00 ]
(veya C# string"\udc00\udd00"
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 bir altstring :
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 kötü biçimlendirilmiş dizileri algılar ve çıkışı oluştururken acter değişimi gerçekleştirir char. Ö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 string
örnekte ile U+FFFD REPLACEMENT CHARACTER ('�')
değiştirir. Daha fazla bilgi için bkz . Unicode Standart, Bölüm 5.22 ve 3.9.
Yerleşik sınıflar, kötü biçimlendirilmiş diziler görüldüğünde Encoding
eylem temelli değiştirme gerçekleştirmek charyerine bir özel durum oluşturacak şekilde de yapılandırılabilir. Bu yaklaşım genellikle, eylemcisi değiştirmenin kabul edilemeyebilir olduğu char, 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
acter kodlama sınıflarını kullanmachar.