Aracılığıyla paylaş


.NET içinde karakter kodlaması

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 chartü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 Osagecharsö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 charsn ile temsil edilir:

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

Bu örneklerde, örnek sayısını string.Length gösteren değerinin chargö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+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 . 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.

BMP ve tamamlayıcı kod noktaları

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

BMP ve vekil kod noktaları

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

Skaler değerler

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 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-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 olarak char 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.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 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 "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, Runeve metin öğesi örnekleri arasındaki stringfarkları 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 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 C2izlenemediğinden 61 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# DC00DD00dilinde) 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 Encodingkarakter kodlama sınıflarını kullanma.

Ayrıca bkz.