.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 stringtü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 charsn ile temsil edilir:

"🐂".Length = 2
s[0] = '�' ('\ud83d')
s[1] = '�' ('\udc02')

Bu örneklerde, örnek sayısını char gösteren değerinin string.Lengthgörüntülenen chareylemcilerin sayısını belirtmemesi gerekir. Tek char bir örnek tek başına bir chareylemi temsil etmez.

Tek charcharbir 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+xxxxkullanı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+FFFFTemel Ç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+10FFFFtamamlayı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.

BMP ve tamamlayıcı kod noktaları

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 stringmetni 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+D800U+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.

BMP ve vekil kod noktaları

Yüksek vekil kod noktası () hemen ardından düşük vekilkod noktası ()U+D800..U+DBFFU+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.

Skaler değerler

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();
}

inputstring 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 inputstring 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-yinelemesicharchar 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 olarak Rune yineleyebilirsiniz. Örnek Rune 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 chargeri 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 yedi char ö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, Runeve metin öğesi örnekleri arasındaki charfarkları 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 stringdö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.GetStringbir stringyö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ından 61izlenemediğinden C2 kötü biçimlendirilmiş olur.

  • UTF-16'da, düşük vekili başka bir düşük vekil DD00DC00 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 Encodingacter kodlama sınıflarını kullanmachar.

Ayrıca bkz.