.NET'te karakter kodlama sınıflarını kullanma

Bu makalede, .NET'in çeşitli kodlama düzenlerini kullanarak metin kodlama ve kod çözme için sağladığı sınıfların nasıl kullanılacağı açıklanmaktadır. Yönergelerde .NET'te karakter kodlamaya giriş'i okuduğunuz varsayılır.

Kodlayıcılar ve kod çözücüler

.NET, çeşitli kodlama sistemlerini kullanarak metin kodlayan ve kodunu çözen kodlama sınıfları sağlar. Örneğin, UTF8Encoding sınıfı UTF-8 için kodlama ve kodunu çözme kurallarını açıklar. .NET, örnekler için string UTF-16 kodlamasını UnicodeEncoding (sınıf tarafından temsil edilir) kullanır. Kodlayıcılar ve kod çözücüler diğer kodlama düzenleri için kullanılabilir.

Kodlama ve kod çözme aynı zamanda doğrulamayı da içerebilir. Örneğin, UnicodeEncoding sınıfı geçerli vekil çiftlerde olduklarından emin olmak için vekil aralıktaki tüm char örnekleri denetler. Geri dönüş stratejisi, kodlayıcının geçersiz karakterleri nasıl işlediğini veya kod çözücülerin geçersiz baytları nasıl işlediğini belirler.

Uyarı

.NET kodlama sınıfları, karakter verilerini depolamak ve dönüştürmek için bir yol sağlar. İkili verileri dize biçiminde depolamak için kullanılmamaları gerekir. Kullanılan kodlamaya bağlı olarak, kodlama sınıflarıyla ikili veriyi dize biçimine dönüştürmek beklenmedik davranışa sebep olabilir ve doğru olmayan ya da bozuk veriler üretebilir. İkili verileri bir dize biçimine dönüştürmek için, Convert.ToBase64String yöntemini kullanın.

.NET'teki tüm karakter kodlama sınıfları, tüm karakter kodlamaları için ortak işlevselliği tanımlayan soyut bir sınıf olan sınıfından devralır System.Text.Encoding . .NET'te uygulanan tek tek kodlama nesnelerine erişmek için aşağıdakileri yapın:

  • .NET'te kullanılabilen standart karakter kodlamalarını (ASCII, UTF-7, UTF-8, UTF-16 ve UTF-32) temsil eden nesneleri döndüren sınıfın statik özelliklerini Encoding kullanın. Örneğin, Encoding.Unicode özelliği bir UnicodeEncoding nesnesini döndürür. Her bir nesne, kodlayamadığı dizeleri ve kodunu çözemediği baytları işlemek için değiştirme geri dönüşünü kullanır. Daha fazla bilgi için bkz . Yedek geri dönüş.

  • Kodlamanın sınıf oluşturucusunu çağırın. ASCII, UTF-7, UTF-8, UTF-16 ve UTF-32 kodlamalarına ait nesneler bu şekilde örneklenebilir. Varsayılan olarak her nesne, kodlayamadığı dizeleri ve kodunu çözemediği baytları işlemek için değiştirme geri dönüşünü kullanır, ancak bunun yerine bir özel durumun oluşturulmasını da belirtebilirsiniz. Daha fazla bilgi için bkz . Değiştirme geri dönüşü ve Özel durum geri dönüşü.

  • Encoding(Int32) oluşturucusunu çağırın ve kodlamayı temsil eden bir tamsayı geçirin. Kodlanamayan dizeleri ve kodu çözülemeyen baytları işlemek için, standart kodlama nesneleri değiştirme geri dönüşünü kullanır ve kod sayfası ile çift bayt karakter kümesi (DBCS) kodlama nesneleri, en uygun geri dönüşü kullanır. Daha fazla bilgi için bkz . En uygun geri dönüş.

  • .NET'te Encoding.GetEncoding kullanılabilen standart, kod sayfası veya DBCS kodlamasını döndüren yöntemini çağırın. Aşırı yüklemeler, hem kodlayıcı hem de kod çözücü için bir geri dönüş nesnesi belirtmenizi sağlar.

yöntemini çağırarak Encoding.GetEncodings .NET'te kullanılabilen tüm kodlamalar hakkında bilgi alabilirsiniz. .NET, aşağıdaki tabloda listelenen karakter kodlama düzenlerini destekler.

Kodlama sınıfı Açıklama
ASCII Bir baytın alt yedi bitini kullanarak sınırlı bir karakter aralığını kodlar. Bu kodlama yalnızca ile karakter U+007Fdeğerlerini desteklediğindenU+0000, çoğu durumda uluslararası uygulamalar için yetersizdir.
UTF-7 Karakterleri 7-bitlik ASCII karakter dizileri olarak temsil eder. ASCII olmayan Unicode karakterleri, ASCII karakterlerinin bir kaçış dizisi ile temsil edilir. UTF-7, e-posta ve haber grubu gibi protokolleri destekler. Ancak, UTF-7 özellikle güvenli veya sağlam değildir. Bazı durumlarda bir biti değiştirmek, bütün bir UTF-7 dizesinin yorumunu tamamen değiştirebilir. Diğer durumlarda, farklı UTF-7 dizeleri aynı metni kodlayabilir. ASCII olmayan karakterleri içeren diziler için UTF-7, UTF-8'den daha fazla alan gerektirir ve kodlama/kod çözme daha yavaştır. Sonuç olarak, mümkünse UTF-7 yerine UTF-8 kullanmanız gerekir.
UTF-8 Her Unicode kod noktasını bir ile dört bayt arası bir dizi olarak temsil eder. UTF-8, 8 bitlik veri boyutlarını destekler ve mevcut çoğu işletim sistemi ile çalışır. ASCII aralığındaki karakterler için, UTF-8 ASCII kodlaması ile aynıdır ve daha geniş bir karakter kümesi sağlar. Ancak, Çince-Japonca-Korece (CJK) betikleri için UTF-8 her karakter için üç bayt gerektirebilir ve UTF-16'dan daha büyük veri boyutlarına neden olabilir. Bazen HTML etiketleri gibi ASCII veri miktarı, CJK aralığının artan boyutunu haklı olarak belirler.
UTF-16 Her Unicode kod noktasını bir veya iki 16 bitlik tamsayı dizisi olarak temsil eder. En yaygın Unicode karakterleri yalnızca bir UTF-16 kod noktası gerektirir, ancak Unicode ek karakterleri (U+10000 ve daha üstü) iki UTF-16 yedek kod noktası gerektirir. Küçük endian ve büyük endian bayt sıralarının her ikisi de desteklenir. UTF-16 kodlaması ortak dil çalışma zamanı tarafından Char ve String değerlerini ve Windows işletim sistemi tarafından WCHAR değerlerini temsil etmek için kullanılır.
UTF-32 Her Unicode kod noktasını bir 32-bit tamsayı olarak temsil eder. Küçük endian ve büyük endian bayt sıralarının her ikisi de desteklenir. UTF-32 kodlama, uygulamalar kodlama alanının çok önemli olduğu işletim sistemlerinde UTF-16 kodlama davranışının yedek kod noktası davranışından kaçınmak istediğinde kullanılır. Görüntü üzerinde işlenen tek simgeler hala birden fazla UTF-32 karakteriyle kodlanabilir.
ANSI/ISO kodlaması Çeşitli kod sayfaları için destek sağlar. Windows işletim sistemlerinde, kod sayfaları belirli bir dili veya dil grubunu desteklemek için kullanılır. .NET tarafından desteklenen kod sayfalarını listeleyen bir tablo için sınıfına Encoding bakın. Encoding.GetEncoding(Int32) yöntemini çağırarak belirli bir kod sayfası için bir kodlama nesnesi alabilirsiniz. Bir kod sayfası 256 kod noktası içerir ve sıfır tabanlıdır. Çoğu kod sayfasında, 0 ile 127 arasındaki kod noktaları ASCII karakter kümesini temsil eder, ve 128 ile 255 arasındaki kod noktaları kod sayfaları arasında önemli ölçüde değişir. Örneğin kod sayfası 1252; İngilizce, Almanca ve Fransızca dahil olmak üzere Latin yazma sistemleri için karakterler sağlar. Kod sayfası 1252'deki son 128 kod noktası vurgu karakterlerini içerir. Kod sayfası 1253, Yunanca yazma sisteminde gerekli olan karakter kodlarını sağlar. Kod sayfası 1253'deki son 128 kod noktası Yunanca karakterleri içerir. Sonuç olarak, ANSI kod sayfalarını temel alan bir uygulama, başvurulan kod sayfasını gösteren bir tanımlayıcı eklemediği sürece aynı metin akışında Yunanca ve Almanca karakterleri depolayamaz.
Çift bayt karakter kümesi (DBCS) kodlamaları 256 karakterden daha fazla karakter içeren Çince, Japonca ve Korece gibi dilleri destekler. DBCS içinde, bir kod noktası çifti (bir çift bayt), her bir karakteri temsil eder. Encoding.IsSingleByte özelliği, DBCS kodlamaları için false'i döndürür. Encoding.GetEncoding(Int32) yöntemini çağırarak belirli bir DBCS için bir kodlama nesnesi alabilirsiniz. Bir uygulama DBCS verilerini işlediğinde, bir DBCS karakterinin (öndeki bayt) ilk baytı, hemen ardından gelen sondaki bayt ile birlikte işlenir. Tek bir çift bayt kod noktası çifti kod sayfasına bağlı olarak farklı karakterleri temsil edebileceğinden, bu düzen yine de Japonca ve Çince gibi iki dilin aynı veri akışında bulunmasına izin vermez.

Bu kodlamalar, hem Unicode karakterleriyle hem de eski uygulamalarda yaygın olarak kullanılan kodlamalarla birlikte çalışmanıza olanak sağlar. Ek olarak, Encoding sınıfından türetilen bir sınıf tanımlayarak ve üyelerini geçersiz kılarak özel bir kodlama oluşturabilirsiniz.

.NET Core kodlama desteği

Varsayılan olarak, .NET Core 28591 kod sayfası ve UTF-8 ve UTF-16 gibi Unicode kodlamaları dışındaki kod sayfası kodlamalarını kullanıma sunmaz. Ancak, .NET'i hedefleyen standart Windows uygulamalarında bulunan kod sayfası kodlamalarını uygulamanıza ekleyebilirsiniz. Daha fazla bilgi için konuya bakın CodePagesEncodingProvider .

Bir Kodlama Sınıfı Seçme

Eğer uygulamanız tarafından kullanılacak kodlamayı seçme olanağınız varsa, bir Unicode kodlamasını, tercihen UTF8Encoding veya UnicodeEncoding'i kullanmanız gerekir. (.NET, üçüncü bir Unicode kodlamayı da destekler. UTF32Encoding.)

Eğer bir ASCII kodlaması (ASCIIEncoding) kullanmayı planlıyorsanız, bunun yerine UTF8Encoding'i seçin. Bu iki kodlama ASCII karakter kümesi için aynıdır, ancak UTF8Encoding aşağıdaki avantajlara sahiptir:

  • ASCIIEncoding, yalnızca U+0000 ve U+007F arasındaki Unicode karakterlerini desteklerken, bu bütün Unicode karakterlerini temsil edebilir.

  • Hata algılama ve daha iyi güvenlik sağlar.

  • Mümkün olduğunca hızlı olacak şekilde ayarlanmıştır ve diğer kodlamalardan daha hızlı olmalıdır. Tamamen ASCII olan içerik için bile, UTF8Encoding ile yapılan işlemler ASCIIEncoding ile yapılan işlemlerden daha hızlıdır.

ASCIIEncoding kodlamasını yalnızca eski uygulamalar için kullanmayı düşünmelisiniz. Ancak, eski uygulamalar için bile, UTF8Encoding aşağıdaki nedenlerden dolayı (varsayılan ayarların olduğunu düşünerek) daha iyi bir seçimdir:

  • Eğer uygulamanız tamamen ASCII olmayan içeriğe sahipse ve bunu ASCIIEncoding ile kodlarsa ASCII olmayan her bir karakter, bir soru işareti (?) olarak kodlanır. Eğer sonra uygulama bu verinin kodunu çözerse, bilgi kaybolur.

  • Eğer uygulamanız tamamen ASCII olmayan içeriğe sahipse ve bunu UTF8Encoding ile kodlarsa, ASCII olarak yorumlandığında sonuç anlamsız görünebilir. Ancak ardından uygulama, bu verinin kodunu çözmek için bir UTF-8 kod çözücü kullanırsa veriler, gidiş dönüşü başarıyla tamamlar.

Bir web uygulamasında, bir web isteğine karşılık olarak istemciye gönderilen karakterler istemcide kullanılan kodlamayı yansıtmalıdır. Çoğu durumda, metni kullanıcının beklediği kodlamayla görüntülemek için HttpResponse.ContentEncoding özelliğini HttpRequest.ContentEncoding özelliği tarafından döndürülen değere ayarlamanız gerekir.

Using an Encoding Object

Bir kodlayıcı, bir karakter dizesini (genellikle Unicode karakterleri) sayısal (bayt) eşdeğerine dönüştürür. Örneğin, Unicode karakterlerini dönüştürmek için bir ASCII kodlayıcısı kullanabilirsiniz ve bu sayede bunların konsolda görüntülenmelerini sağlayabilirsiniz. Dönüşümü gerçekleştirmek için, Encoding.GetBytes yöntemini çağırın. Eğer kodlanmış karakterlerin depolanması için kaç bayt gerektiğini kodlamayı gerçekleştirmeden önce belirlemek istiyorsanız, GetByteCount yöntemini çağırabilirsiniz.

Aşağıdaki örnek, dizeleri iki ayrı işlemde kodlamak için tek bir bayt dizisini kullanır. Bayt dizisinde, sonraki ASCII kodlamalı bayt kümesinin başlangıç konumunu belirten bir dizin tutar. Bayt dizisinin kodlanmış dizeyi tutabilecek kadar büyük olduğundan emin olmak için ASCIIEncoding.GetByteCount(String) yöntemini çağırır. Ardından dizedeki karakterleri kodlamak için ASCIIEncoding.GetBytes(String, Int32, Int32, Byte[], Int32) yöntemini çağırır.

using System;
using System.Text;

public class Example
{
   public static void Main()
   {
      string[] strings= { "This is the first sentence. ",
                          "This is the second sentence. " };
      Encoding asciiEncoding = Encoding.ASCII;

      // Create array of adequate size.
      byte[] bytes = new byte[49];
      // Create index for current position of array.
      int index = 0;

      Console.WriteLine("Strings to encode:");
      foreach (var stringValue in strings) {
         Console.WriteLine("   {0}", stringValue);

         int count = asciiEncoding.GetByteCount(stringValue);
         if (count + index >=  bytes.Length)
            Array.Resize(ref bytes, bytes.Length + 50);

         int written = asciiEncoding.GetBytes(stringValue, 0,
                                              stringValue.Length,
                                              bytes, index);

         index = index + written;
      }
      Console.WriteLine("\nEncoded bytes:");
      Console.WriteLine("{0}", ShowByteValues(bytes, index));
      Console.WriteLine();

      // Decode Unicode byte array to a string.
      string newString = asciiEncoding.GetString(bytes, 0, index);
      Console.WriteLine("Decoded: {0}", newString);
   }

   private static string ShowByteValues(byte[] bytes, int last )
   {
      string returnString = "   ";
      for (int ctr = 0; ctr <= last - 1; ctr++) {
         if (ctr % 20 == 0)
            returnString += "\n   ";
         returnString += String.Format("{0:X2} ", bytes[ctr]);
      }
      return returnString;
   }
}
// The example displays the following output:
//       Strings to encode:
//          This is the first sentence.
//          This is the second sentence.
//
//       Encoded bytes:
//
//          54 68 69 73 20 69 73 20 74 68 65 20 66 69 72 73 74 20 73 65
//          6E 74 65 6E 63 65 2E 20 54 68 69 73 20 69 73 20 74 68 65 20
//          73 65 63 6F 6E 64 20 73 65 6E 74 65 6E 63 65 2E 20
//
//       Decoded: This is the first sentence. This is the second sentence.
Imports System.Text

Module Example
    Public Sub Main()
        Dim strings() As String = {"This is the first sentence. ",
                                    "This is the second sentence. "}
        Dim asciiEncoding As Encoding = Encoding.ASCII

        ' Create array of adequate size.
        Dim bytes(50) As Byte
        ' Create index for current position of array.
        Dim index As Integer = 0

        Console.WriteLine("Strings to encode:")
        For Each stringValue In strings
            Console.WriteLine("   {0}", stringValue)

            Dim count As Integer = asciiEncoding.GetByteCount(stringValue)
            If count + index >= bytes.Length Then
                Array.Resize(bytes, bytes.Length + 50)
            End If
            Dim written As Integer = asciiEncoding.GetBytes(stringValue, 0,
                                                            stringValue.Length,
                                                            bytes, index)

            index = index + written
        Next
        Console.WriteLine()
        Console.WriteLine("Encoded bytes:")
        Console.WriteLine("{0}", ShowByteValues(bytes, index))
        Console.WriteLine()

        ' Decode Unicode byte array to a string.
        Dim newString As String = asciiEncoding.GetString(bytes, 0, index)
        Console.WriteLine("Decoded: {0}", newString)
    End Sub

    Private Function ShowByteValues(bytes As Byte(), last As Integer) As String
        Dim returnString As String = "   "
        For ctr As Integer = 0 To last - 1
            If ctr Mod 20 = 0 Then returnString += vbCrLf + "   "
            returnString += String.Format("{0:X2} ", bytes(ctr))
        Next
        Return returnString
    End Function
End Module
' The example displays the following output:
'       Strings to encode:
'          This is the first sentence.
'          This is the second sentence.
'       
'       Encoded bytes:
'       
'          54 68 69 73 20 69 73 20 74 68 65 20 66 69 72 73 74 20 73 65
'          6E 74 65 6E 63 65 2E 20 54 68 69 73 20 69 73 20 74 68 65 20
'          73 65 63 6F 6E 64 20 73 65 6E 74 65 6E 63 65 2E 20
'       
'       Decoded: This is the first sentence. This is the second sentence.

Bir kod çözücü, belirli bir karakter kodlamasını yansıtan bayt dizisini, bir karakter dizisi veya dize olarak karakter kümesine dönüştürür. Bir bayt dizisinin karakter dizisi olarak kodunu çözmek için Encoding.GetChars yöntemini çağırın. Bir bayt dizisinin dize olarak kodunu çözmek için GetString yöntemini çağırın. Eğer kodu çözülmüş baytların depolanması için kaç karakter gerektiğini kodlamayı gerçekleştirmeden önce belirlemek istiyorsanız, GetCharCount yöntemini çağırabilirsiniz.

Aşağıdaki örnek üç dizeyi kodlar ve ardından tek bir karakter dizisi olarak kodunu çözer. Karakter dizisinde sonraki kodu çözülmüş karakter kümesinin başlangıç konumunu belirten bir dizin tutar. Karakter dizisinin kodu çözülmüş tüm karakterleri tutacak kadar büyük olduğundan emin olmak için GetCharCount yöntemini çağırır. Ardından bayt dizisinin kodunu çözmek için ASCIIEncoding.GetChars(Byte[], Int32, Int32, Char[], Int32) yöntemini çağırır.

using System;
using System.Text;

public class Example
{
   public static void Main()
   {
      string[] strings = { "This is the first sentence. ",
                           "This is the second sentence. ",
                           "This is the third sentence. " };
      Encoding asciiEncoding = Encoding.ASCII;
      // Array to hold encoded bytes.
      byte[] bytes;
      // Array to hold decoded characters.
      char[] chars = new char[50];
      // Create index for current position of character array.
      int index = 0;

      foreach (var stringValue in strings) {
         Console.WriteLine("String to Encode: {0}", stringValue);
         // Encode the string to a byte array.
         bytes = asciiEncoding.GetBytes(stringValue);
         // Display the encoded bytes.
         Console.Write("Encoded bytes: ");
         for (int ctr = 0; ctr < bytes.Length; ctr++)
            Console.Write(" {0}{1:X2}",
                          ctr % 20 == 0 ? Environment.NewLine : "",
                          bytes[ctr]);
         Console.WriteLine();

         // Decode the bytes to a single character array.
         int count = asciiEncoding.GetCharCount(bytes);
         if (count + index >=  chars.Length)
            Array.Resize(ref chars, chars.Length + 50);

         int written = asciiEncoding.GetChars(bytes, 0,
                                              bytes.Length,
                                              chars, index);
         index = index + written;
         Console.WriteLine();
      }

      // Instantiate a single string containing the characters.
      string decodedString = new string(chars, 0, index - 1);
      Console.WriteLine("Decoded string: ");
      Console.WriteLine(decodedString);
   }
}
// The example displays the following output:
//    String to Encode: This is the first sentence.
//    Encoded bytes:
//    54 68 69 73 20 69 73 20 74 68 65 20 66 69 72 73 74 20 73 65
//    6E 74 65 6E 63 65 2E 20
//
//    String to Encode: This is the second sentence.
//    Encoded bytes:
//    54 68 69 73 20 69 73 20 74 68 65 20 73 65 63 6F 6E 64 20 73
//    65 6E 74 65 6E 63 65 2E 20
//
//    String to Encode: This is the third sentence.
//    Encoded bytes:
//    54 68 69 73 20 69 73 20 74 68 65 20 74 68 69 72 64 20 73 65
//    6E 74 65 6E 63 65 2E 20
//
//    Decoded string:
//    This is the first sentence. This is the second sentence. This is the third sentence.
Imports System.Text

Module Example
    Public Sub Main()
        Dim strings() As String = {"This is the first sentence. ",
                                    "This is the second sentence. ",
                                    "This is the third sentence. "}
        Dim asciiEncoding As Encoding = Encoding.ASCII
        ' Array to hold encoded bytes.
        Dim bytes() As Byte
        ' Array to hold decoded characters.
        Dim chars(50) As Char
        ' Create index for current position of character array.
        Dim index As Integer

        For Each stringValue In strings
            Console.WriteLine("String to Encode: {0}", stringValue)
            ' Encode the string to a byte array.
            bytes = asciiEncoding.GetBytes(stringValue)
            ' Display the encoded bytes.
            Console.Write("Encoded bytes: ")
            For ctr As Integer = 0 To bytes.Length - 1
                Console.Write(" {0}{1:X2}", If(ctr Mod 20 = 0, vbCrLf, ""),
                                            bytes(ctr))
            Next
            Console.WriteLine()

            ' Decode the bytes to a single character array.
            Dim count As Integer = asciiEncoding.GetCharCount(bytes)
            If count + index >= chars.Length Then
                Array.Resize(chars, chars.Length + 50)
            End If
            Dim written As Integer = asciiEncoding.GetChars(bytes, 0,
                                                            bytes.Length,
                                                            chars, index)
            index = index + written
            Console.WriteLine()
        Next

        ' Instantiate a single string containing the characters.
        Dim decodedString As New String(chars, 0, index - 1)
        Console.WriteLine("Decoded string: ")
        Console.WriteLine(decodedString)
    End Sub
End Module
' The example displays the following output:
'    String to Encode: This is the first sentence.
'    Encoded bytes:
'    54 68 69 73 20 69 73 20 74 68 65 20 66 69 72 73 74 20 73 65
'    6E 74 65 6E 63 65 2E 20
'    
'    String to Encode: This is the second sentence.
'    Encoded bytes:
'    54 68 69 73 20 69 73 20 74 68 65 20 73 65 63 6F 6E 64 20 73
'    65 6E 74 65 6E 63 65 2E 20
'    
'    String to Encode: This is the third sentence.
'    Encoded bytes:
'    54 68 69 73 20 69 73 20 74 68 65 20 74 68 69 72 64 20 73 65
'    6E 74 65 6E 63 65 2E 20
'    
'    Decoded string:
'    This is the first sentence. This is the second sentence. This is the third sentence.

Encoding sınıfından türetilen bir sınıfın kodlama ve kod çözme yöntemleri, tam bir veri kümesi ile çalışacak şekilde tasarlanmıştır; yani, kodlanacak veya kodu çözülecek tüm veriler tek bir yöntem çağrısında sağlanır. Ancak, bazı durumlarda veriler bir akışta bulunabilir ve kodlanacak ya da kodu çözülecek veriler yalnızca ayrı okuma işlemleri ile kullanılabilir olabilir. Bu, kodlama veya kod çözme işleminin önceki çağrıda kaydedilen durumunu hatırlamasını gerektirir. Encoder ve Decoder sınıflarından türetilen sınıfların yöntemleri, birden çok yöntem çağrısına yayılan kodlama ve kod çözme işlemlerini işleyebilir.

Belirli bir kodlamaya ait bir Encoder nesnesi, o kodlamanın Encoding.GetEncoder özelliğinden kullanılabilir. Belirli bir kodlamaya ait bir Decoder nesnesi, o kodlamanın Encoding.GetDecoder özelliğinden kullanılabilir. Kod çözme işlemleri için, Decoder sınıfından türetilen sınıfların bir Decoder.GetChars yöntemi içerdiğine, ancak Encoding.GetString yöntemine karşılık gelen bir yöntemleri olmadığına dikkat edin.

Aşağıdaki örnek, bir Unicode bayt dizisinin kodunu çözmek için Encoding.GetString ve Decoder.GetChars yöntemlerinin kullanılması arasındaki farkı gösterir. Bu örnek, bazı Unicode karakterleri içeren bir dizeyi dosya içine kodlar ve ardından iki kod çözme yöntemini kullanarak tek seferde on bayt olacak şekilde kodlarını çözer. Onuncu ve on birinci baytlarda bir yedek çifti olduğu için kodu, ayrı yöntem çağrılarında çözülür. Çıktının gösterdiği gibi Encoding.GetString yöntemi, baytların kodunu doğru şekilde çözemez ve bunun yerine onları U+FFFD (DEĞİŞTİRME KARAKTERİ) ile değiştirir. Diğer taraftan Decoder.GetChars yöntemi, bayt dizisinin kodunu başarıyla çözerek özgün dizeye ulaşır.

using System;
using System.IO;
using System.Text;

public class Example
{
   public static void Main()
   {
      // Use default replacement fallback for invalid encoding.
      UnicodeEncoding enc = new UnicodeEncoding(true, false, false);

      // Define a string with various Unicode characters.
      string str1 = "AB YZ 19 \uD800\udc05 \u00e4";
      str1 += "Unicode characters. \u00a9 \u010C s \u0062\u0308";
      Console.WriteLine("Created original string...\n");

      // Convert string to byte array.
      byte[] bytes = enc.GetBytes(str1);

      FileStream fs = File.Create(@".\characters.bin");
      BinaryWriter bw = new BinaryWriter(fs);
      bw.Write(bytes);
      bw.Close();

      // Read bytes from file.
      FileStream fsIn = File.OpenRead(@".\characters.bin");
      BinaryReader br = new BinaryReader(fsIn);

      const int count = 10;            // Number of bytes to read at a time.
      byte[] bytesRead = new byte[10]; // Buffer (byte array).
      int read;                        // Number of bytes actually read.
      string str2 = String.Empty;      // Decoded string.

      // Try using Encoding object for all operations.
      do {
         read = br.Read(bytesRead, 0, count);
         str2 += enc.GetString(bytesRead, 0, read);
      } while (read == count);
      br.Close();
      Console.WriteLine("Decoded string using UnicodeEncoding.GetString()...");
      CompareForEquality(str1, str2);
      Console.WriteLine();

      // Use Decoder for all operations.
      fsIn = File.OpenRead(@".\characters.bin");
      br = new BinaryReader(fsIn);
      Decoder decoder = enc.GetDecoder();
      char[] chars = new char[50];
      int index = 0;                   // Next character to write in array.
      int written = 0;                 // Number of chars written to array.
      do {
         read = br.Read(bytesRead, 0, count);
         if (index + decoder.GetCharCount(bytesRead, 0, read) - 1 >= chars.Length)
            Array.Resize(ref chars, chars.Length + 50);

         written = decoder.GetChars(bytesRead, 0, read, chars, index);
         index += written;
      } while (read == count);
      br.Close();
      // Instantiate a string with the decoded characters.
      string str3 = new String(chars, 0, index);
      Console.WriteLine("Decoded string using UnicodeEncoding.Decoder.GetString()...");
      CompareForEquality(str1, str3);
   }

   private static void CompareForEquality(string original, string decoded)
   {
      bool result = original.Equals(decoded);
      Console.WriteLine("original = decoded: {0}",
                        original.Equals(decoded, StringComparison.Ordinal));
      if (! result) {
         Console.WriteLine("Code points in original string:");
         foreach (var ch in original)
            Console.Write("{0} ", Convert.ToUInt16(ch).ToString("X4"));
         Console.WriteLine();

         Console.WriteLine("Code points in decoded string:");
         foreach (var ch in decoded)
            Console.Write("{0} ", Convert.ToUInt16(ch).ToString("X4"));
         Console.WriteLine();
      }
   }
}
// The example displays the following output:
//    Created original string...
//
//    Decoded string using UnicodeEncoding.GetString()...
//    original = decoded: False
//    Code points in original string:
//    0041 0042 0020 0059 005A 0020 0031 0039 0020 D800 DC05 0020 00E4 0055 006E 0069 0063 006F
//    0064 0065 0020 0063 0068 0061 0072 0061 0063 0074 0065 0072 0073 002E 0020 00A9 0020 010C
//    0020 0073 0020 0062 0308
//    Code points in decoded string:
//    0041 0042 0020 0059 005A 0020 0031 0039 0020 FFFD FFFD 0020 00E4 0055 006E 0069 0063 006F
//    0064 0065 0020 0063 0068 0061 0072 0061 0063 0074 0065 0072 0073 002E 0020 00A9 0020 010C
//    0020 0073 0020 0062 0308
//
//    Decoded string using UnicodeEncoding.Decoder.GetString()...
//    original = decoded: True
Imports System.IO
Imports System.Text

Module Example
    Public Sub Main()
        ' Use default replacement fallback for invalid encoding.
        Dim enc As New UnicodeEncoding(True, False, False)

        ' Define a string with various Unicode characters.
        Dim str1 As String = String.Format("AB YZ 19 {0}{1} {2}",
                                           ChrW(&hD800), ChrW(&hDC05), ChrW(&h00e4))
        str1 += String.Format("Unicode characters. {0} {1} s {2}{3}",
                              ChrW(&h00a9), ChrW(&h010C), ChrW(&h0062), ChrW(&h0308))
        Console.WriteLine("Created original string...")
        Console.WriteLine()

        ' Convert string to byte array.                     
        Dim bytes() As Byte = enc.GetBytes(str1)

        Dim fs As FileStream = File.Create(".\characters.bin")
        Dim bw As New BinaryWriter(fs)
        bw.Write(bytes)
        bw.Close()

        ' Read bytes from file.
        Dim fsIn As FileStream = File.OpenRead(".\characters.bin")
        Dim br As New BinaryReader(fsIn)

        Const count As Integer = 10      ' Number of bytes to read at a time. 
        Dim bytesRead(9) As Byte         ' Buffer (byte array).
        Dim read As Integer              ' Number of bytes actually read. 
        Dim str2 As String = ""          ' Decoded string.

        ' Try using Encoding object for all operations.
        Do
            read = br.Read(bytesRead, 0, count)
            str2 += enc.GetString(bytesRead, 0, read)
        Loop While read = count
        br.Close()
        Console.WriteLine("Decoded string using UnicodeEncoding.GetString()...")
        CompareForEquality(str1, str2)
        Console.WriteLine()

        ' Use Decoder for all operations.
        fsIn = File.OpenRead(".\characters.bin")
        br = New BinaryReader(fsIn)
        Dim decoder As Decoder = enc.GetDecoder()
        Dim chars(50) As Char
        Dim index As Integer = 0         ' Next character to write in array.
        Dim written As Integer = 0       ' Number of chars written to array.
        Do
            read = br.Read(bytesRead, 0, count)
            If index + decoder.GetCharCount(bytesRead, 0, read) - 1 >= chars.Length Then
                Array.Resize(chars, chars.Length + 50)
            End If
            written = decoder.GetChars(bytesRead, 0, read, chars, index)
            index += written
        Loop While read = count
        br.Close()
        ' Instantiate a string with the decoded characters.
        Dim str3 As New String(chars, 0, index)
        Console.WriteLine("Decoded string using UnicodeEncoding.Decoder.GetString()...")
        CompareForEquality(str1, str3)
    End Sub

    Private Sub CompareForEquality(original As String, decoded As String)
        Dim result As Boolean = original.Equals(decoded)
        Console.WriteLine("original = decoded: {0}",
                          original.Equals(decoded, StringComparison.Ordinal))
        If Not result Then
            Console.WriteLine("Code points in original string:")
            For Each ch In original
                Console.Write("{0} ", Convert.ToUInt16(ch).ToString("X4"))
            Next
            Console.WriteLine()

            Console.WriteLine("Code points in decoded string:")
            For Each ch In decoded
                Console.Write("{0} ", Convert.ToUInt16(ch).ToString("X4"))
            Next
            Console.WriteLine()
        End If
    End Sub
End Module
' The example displays the following output:
'    Created original string...
'    
'    Decoded string using UnicodeEncoding.GetString()...
'    original = decoded: False
'    Code points in original string:
'    0041 0042 0020 0059 005A 0020 0031 0039 0020 D800 DC05 0020 00E4 0055 006E 0069 0063 006F
'    0064 0065 0020 0063 0068 0061 0072 0061 0063 0074 0065 0072 0073 002E 0020 00A9 0020 010C
'    0020 0073 0020 0062 0308
'    Code points in decoded string:
'    0041 0042 0020 0059 005A 0020 0031 0039 0020 FFFD FFFD 0020 00E4 0055 006E 0069 0063 006F
'    0064 0065 0020 0063 0068 0061 0072 0061 0063 0074 0065 0072 0073 002E 0020 00A9 0020 010C
'    0020 0073 0020 0062 0308
'    
'    Decoded string using UnicodeEncoding.Decoder.GetString()...
'    original = decoded: True

Choosing a Fallback Strategy

Bir yöntem, bir karakter için kodlamayı veya kod çözmeyi denediğinde ancak hiçbir eşleme bulunmadığında, başarısız olan eşlemenin nasıl işleneceğini belirleyen bir geri dönüş stratejisi uygulanmalıdır. Üç çeşit geri dönüş stratejisi bulunur:

  • En uygun geri dönüş

  • Değiştirme geri dönüşü

  • Özel durum geri dönüşü

Önemli

Kodlama işlemlerindeki en yaygın sorunlar, bir Unicode karakteri belirli bir kod sayfası kodlamasıyla eşlenemediğinde ortaya çıkar. Kod çözme işlemlerindeki en yaygın sorunlar, geçersiz bayt dizileri geçerli Unicode karakterlerine çevrilemediğinde ortaya çıkar. Bu nedenlerden dolayı, belirli bir kodlama nesnesinin hangi geri dönüş stratejisini kullandığını bilmeniz gerekir. Mümkün olduğunda, bir kodlama nesnesinin kullandığı geri dönüş stratejisini nesnenin örneğini oluştururken belirtmeniz gerekir.

En Uygun Geri Dönüş

Bir karakter hedef kodlamada tam bir eşleşmeye sahip olmadığında, kodlayıcı bu karakteri benzer bir karakterle eşlemeyi deneyebilir. (En uygun geri dönüş, kod çözme sorunu yerine çoğunlukla bir kodlamadır. Unicode ile başarıyla eşlenemeyen karakterler içeren çok az kod sayfası vardır.) En uygun geri dönüş, ve aşırı yüklemeleri tarafından Encoding.GetEncoding(Int32)Encoding.GetEncoding(String) alınan kod sayfası ve çift baytlık karakter kümesi kodlamaları için varsayılan değerdir.

Not

Teoride, .NET 'te (UTF8Encoding, UnicodeEncodingve UTF32Encoding) sağlanan Unicode kodlama sınıfları her karakter kümesindeki her karakteri destekler, böylece en uygun geri dönüş sorunlarını ortadan kaldırmak için kullanılabilirler.

En uygun stratejiler farklı kod sayfaları için farklılık gösterir. Örneğin, bazı kod sayfalarında tam genişlikteki Latin karakterler, daha yaygın olan yarım genişlikteki Latin karakterlerle eşlenir. Diğer kod sayfaları için bu eşleme yapılmaz. Agresif bir en uygun stratejide bile, bazı kodlamalardaki bazı karakterler için mümkün olan hiçbir uygun karakter yoktur. Örneğin, bir Çince ideogramın kod sayfası 1252 için hiçbir mantıklı eşlemesi yoktur. Bu durumda, bir değiştirme dizesi kullanılır. Varsayılan olarak bu dize, yalnızca tek bir SORU İŞARETİ (U+003F) karakteridir.

Not

En uygun stratejiler ayrıntılı olarak belgelenmez. Ancak, Unicode Konsorsiyumu'nun web sitesinde birkaç kod sayfası belgelenmiştir. Eşleme dosyalarının nasıl yorumlandığının açıklaması için lütfen bu klasördeki readme.txt dosyasını gözden geçirin.

Aşağıdaki örnek, kod sayfası 1252'yi (Batı Avrupa dilleri için Windows kod sayfası) kullanarak en uygun eşlemeyi ve bunun dezavantajlarını gösterir. Kod sayfası 1252 için bir kodlama nesnesi almak üzere Encoding.GetEncoding(Int32) yöntemi kullanılır. Varsayılan olarak, desteklemediği Unicode karakterleri için bir en uygun eşleme kullanır. Örnek; boşluklarla ayrılan, ASCII olmayan üç karakteri içeren bir dizeyi örnekler - DAİRELİ LATIN BÜYÜK HARF S (U+24C8), ÜST SİMGE BEŞ (U+2075) ve SONSUZLUK (U+221E). Örneğin çıktısının gösterdiği üzere, dize kodlandığında boşluk olmayan üç orijinal karakter, SORU İŞARETİ (U+003F), BEŞ BASAMAĞI (U+0035) ve SEKİZ BASAMAĞI (U+0038) ile değiştirilir. Özellikle SEKİZ BASAMAĞI, desteklenmeyen SONSUZLUK karakteri için kötü bir değiştirmedir ve SORU İŞARETİ, orijinal karakter için kullanılabilir bir eşleme bulunmadığını gösterir.

using System;
using System.Text;

public class Example
{
   public static void Main()
   {
      // Get an encoding for code page 1252 (Western Europe character set).
      Encoding cp1252 = Encoding.GetEncoding(1252);

      // Define and display a string.
      string str = "\u24c8 \u2075 \u221e";
      Console.WriteLine("Original string: " + str);
      Console.Write("Code points in string: ");
      foreach (var ch in str)
         Console.Write("{0} ", Convert.ToUInt16(ch).ToString("X4"));

      Console.WriteLine("\n");

      // Encode a Unicode string.
      Byte[] bytes = cp1252.GetBytes(str);
      Console.Write("Encoded bytes: ");
      foreach (byte byt in bytes)
         Console.Write("{0:X2} ", byt);
      Console.WriteLine("\n");

      // Decode the string.
      string str2 = cp1252.GetString(bytes);
      Console.WriteLine("String round-tripped: {0}", str.Equals(str2));
      if (! str.Equals(str2)) {
         Console.WriteLine(str2);
         foreach (var ch in str2)
            Console.Write("{0} ", Convert.ToUInt16(ch).ToString("X4"));
      }
   }
}
// The example displays the following output:
//       Original string: Ⓢ ⁵ ∞
//       Code points in string: 24C8 0020 2075 0020 221E
//
//       Encoded bytes: 3F 20 35 20 38
//
//       String round-tripped: False
//       ? 5 8
//       003F 0020 0035 0020 0038
Imports System.Text

Module Example
    Public Sub Main()
        ' Get an encoding for code page 1252 (Western Europe character set).
        Dim cp1252 As Encoding = Encoding.GetEncoding(1252)

        ' Define and display a string.
        Dim str As String = String.Format("{0} {1} {2}", ChrW(&h24c8), ChrW(&H2075), ChrW(&h221E))
        Console.WriteLine("Original string: " + str)
        Console.Write("Code points in string: ")
        For Each ch In str
            Console.Write("{0} ", Convert.ToUInt16(ch).ToString("X4"))
        Next
        Console.WriteLine()
        Console.WriteLine()

        ' Encode a Unicode string.
        Dim bytes() As Byte = cp1252.GetBytes(str)
        Console.Write("Encoded bytes: ")
        For Each byt In bytes
            Console.Write("{0:X2} ", byt)
        Next
        Console.WriteLine()
        Console.WriteLine()

        ' Decode the string.
        Dim str2 As String = cp1252.GetString(bytes)
        Console.WriteLine("String round-tripped: {0}", str.Equals(str2))
        If Not str.Equals(str2) Then
            Console.WriteLine(str2)
            For Each ch In str2
                Console.Write("{0} ", Convert.ToUInt16(ch).ToString("X4"))
            Next
        End If
    End Sub
End Module
' The example displays the following output:
'       Original string: Ⓢ ⁵ ∞
'       Code points in string: 24C8 0020 2075 0020 221E
'       
'       Encoded bytes: 3F 20 35 20 38
'       
'       String round-tripped: False
'       ? 5 8
'       003F 0020 0035 0020 0038

En uygun eşleme, Unicode verilerini kod sayfası verisine kodlayan bir Encoding nesnesi için varsayılan davranıştır ve bu davranışı kullanan eski uygulamalar vardır. Ancak, güvenlik gerekçesiyle çoğu yeni uygulamanın, en uygun davranışından kaçınması gerekir. Örneğin, uygulamalar bir etki alanı adını en uygun kodlama ile koymamalıdır.

Not

Bir kodlama için aynı zamanda özel bir en uygun geri dönüş eşlemesi uygulayabilirsiniz. Daha fazla bilgi için Özel Geri Dönüş Stratejisi Uygulama bölümüne bakın.

Eğer en uygun geri dönüş bir kodlama nesnesi için varsayılansa, Encoding veya Encoding.GetEncoding(Int32, EncoderFallback, DecoderFallback) aşırı yüklemesini çağırarak bir Encoding.GetEncoding(String, EncoderFallback, DecoderFallback) nenesi aldığınızda başka bir geri dönüş stratejisi seçebilirsiniz. Aşağıdaki bölüm, kod sayfası 1252 ile eşleşemeyen her karakteri yıldız işareti (*) ile değiştiren bir örnek içerir.

using System;
using System.Text;

public class Example
{
   public static void Main()
   {
      Encoding cp1252r = Encoding.GetEncoding(1252,
                                  new EncoderReplacementFallback("*"),
                                  new DecoderReplacementFallback("*"));

      string str1 = "\u24C8 \u2075 \u221E";
      Console.WriteLine(str1);
      foreach (var ch in str1)
         Console.Write("{0} ", Convert.ToUInt16(ch).ToString("X4"));

      Console.WriteLine();

      byte[] bytes = cp1252r.GetBytes(str1);
      string str2 = cp1252r.GetString(bytes);
      Console.WriteLine("Round-trip: {0}", str1.Equals(str2));
      if (! str1.Equals(str2)) {
         Console.WriteLine(str2);
         foreach (var ch in str2)
            Console.Write("{0} ", Convert.ToUInt16(ch).ToString("X4"));

         Console.WriteLine();
      }
   }
}
// The example displays the following output:
//       Ⓢ ⁵ ∞
//       24C8 0020 2075 0020 221E
//       Round-trip: False
//       * * *
//       002A 0020 002A 0020 002A
Imports System.Text

Module Example
    Public Sub Main()
        Dim cp1252r As Encoding = Encoding.GetEncoding(1252,
                                           New EncoderReplacementFallback("*"),
                                           New DecoderReplacementFallback("*"))

        Dim str1 As String = String.Format("{0} {1} {2}", ChrW(&h24C8), ChrW(&h2075), ChrW(&h221E))
        Console.WriteLine(str1)
        For Each ch In str1
            Console.Write("{0} ", Convert.ToUInt16(ch).ToString("X4"))
        Next
        Console.WriteLine()

        Dim bytes() As Byte = cp1252r.GetBytes(str1)
        Dim str2 As String = cp1252r.GetString(bytes)
        Console.WriteLine("Round-trip: {0}", str1.Equals(str2))
        If Not str1.Equals(str2) Then
            Console.WriteLine(str2)
            For Each ch In str2
                Console.Write("{0} ", Convert.ToUInt16(ch).ToString("X4"))
            Next
            Console.WriteLine()
        End If
    End Sub
End Module
' The example displays the following output:
'       Ⓢ ⁵ ∞
'       24C8 0020 2075 0020 221E
'       Round-trip: False
'       * * *
'       002A 0020 002A 0020 002A

Değiştirme Geri Dönüşü

Bir karakterin hedef düzende tam eşleşmesi olmadığında ancak eşlenebileceği hiçbir uygun karakter bulunmadığında, uygulama bir değişim karakteri veya dizesi belirtebilir. Bu, kodunu çözemediği herhangi bir iki baytlık diziyi DEĞİŞİM_KARAKTERİ (U+FFFD) ile değiştiren Unicode kod çözücünün varsayılan davranışıdır. Bu ayrıca, kodlayamadığı veya kodunu çözemediği her karakteri bir soru işareti ile değiştiren ASCIIEncoding sınıfının da varsayılan davranışıdır. Aşağıdaki örnek, önceki örnekteki Unicode dizesi için karakter değiştirmeyi gösterir. Çıktının gösterdiği üzere bir ASCII bayt değeri olarak kodu çözülemeyen her karakter,bir soru işareti için ASCII kodu olan 0x3F ile değiştirilir.

using System;
using System.Text;

public class Example
{
   public static void Main()
   {
      Encoding enc = Encoding.ASCII;

      string str1 = "\u24C8 \u2075 \u221E";
      Console.WriteLine(str1);
      foreach (var ch in str1)
         Console.Write("{0} ", Convert.ToUInt16(ch).ToString("X4"));

      Console.WriteLine("\n");

      // Encode the original string using the ASCII encoder.
      byte[] bytes = enc.GetBytes(str1);
      Console.Write("Encoded bytes: ");
      foreach (var byt in bytes)
         Console.Write("{0:X2} ", byt);
      Console.WriteLine("\n");

      // Decode the ASCII bytes.
      string str2 = enc.GetString(bytes);
      Console.WriteLine("Round-trip: {0}", str1.Equals(str2));
      if (! str1.Equals(str2)) {
         Console.WriteLine(str2);
         foreach (var ch in str2)
            Console.Write("{0} ", Convert.ToUInt16(ch).ToString("X4"));

         Console.WriteLine();
      }
   }
}
// The example displays the following output:
//       Ⓢ ⁵ ∞
//       24C8 0020 2075 0020 221E
//
//       Encoded bytes: 3F 20 3F 20 3F
//
//       Round-trip: False
//       ? ? ?
//       003F 0020 003F 0020 003F
Imports System.Text

Module Example
    Public Sub Main()
        Dim enc As Encoding = Encoding.Ascii

        Dim str1 As String = String.Format("{0} {1} {2}", ChrW(&h24C8), ChrW(&h2075), ChrW(&h221E))
        Console.WriteLine(str1)
        For Each ch In str1
            Console.Write("{0} ", Convert.ToUInt16(ch).ToString("X4"))
        Next
        Console.WriteLine()
        Console.WriteLine()

        ' Encode the original string using the ASCII encoder.
        Dim bytes() As Byte = enc.GetBytes(str1)
        Console.Write("Encoded bytes: ")
        For Each byt In bytes
            Console.Write("{0:X2} ", byt)
        Next
        Console.WriteLine()
        Console.WriteLine()

        ' Decode the ASCII bytes.
        Dim str2 As String = enc.GetString(bytes)
        Console.WriteLine("Round-trip: {0}", str1.Equals(str2))
        If Not str1.Equals(str2) Then
            Console.WriteLine(str2)
            For Each ch In str2
                Console.Write("{0} ", Convert.ToUInt16(ch).ToString("X4"))
            Next
            Console.WriteLine()
        End If
    End Sub
End Module
' The example displays the following output:
'       Ⓢ ⁵ ∞
'       24C8 0020 2075 0020 221E
'       
'       Encoded bytes: 3F 20 3F 20 3F
'       
'       Round-trip: False
'       ? ? ?
'       003F 0020 003F 0020 003F

.NET, bir karakter tam olarak bir kodlama veya kod çözme işleminde eşlenmiyorsa yerine yeni dizeyi kullanan ve DecoderReplacementFallback sınıflarını içerirEncoderReplacementFallback. Varsayılan olarak bu değiştirme dizesi bir soru işaretidir, ancak farklı dize seçmek için bir sınıf oluşturucusu aşırı yüklemesini çağırabilirsiniz. Genellikle, değiştirme karakteri tek bir karakterdir, ancak bu, bir gereksinim değildir. Aşağıdaki örnek, değişim dizesi olarak yıldız işareti (*) kullanan bir EncoderReplacementFallback nesnesinin örneğini oluşturarak kod sayfası 1252'nin davranışını değiştirir.

using System;
using System.Text;

public class Example
{
   public static void Main()
   {
      Encoding cp1252r = Encoding.GetEncoding(1252,
                                  new EncoderReplacementFallback("*"),
                                  new DecoderReplacementFallback("*"));

      string str1 = "\u24C8 \u2075 \u221E";
      Console.WriteLine(str1);
      foreach (var ch in str1)
         Console.Write("{0} ", Convert.ToUInt16(ch).ToString("X4"));

      Console.WriteLine();

      byte[] bytes = cp1252r.GetBytes(str1);
      string str2 = cp1252r.GetString(bytes);
      Console.WriteLine("Round-trip: {0}", str1.Equals(str2));
      if (! str1.Equals(str2)) {
         Console.WriteLine(str2);
         foreach (var ch in str2)
            Console.Write("{0} ", Convert.ToUInt16(ch).ToString("X4"));

         Console.WriteLine();
      }
   }
}
// The example displays the following output:
//       Ⓢ ⁵ ∞
//       24C8 0020 2075 0020 221E
//       Round-trip: False
//       * * *
//       002A 0020 002A 0020 002A
Imports System.Text

Module Example
    Public Sub Main()
        Dim cp1252r As Encoding = Encoding.GetEncoding(1252,
                                           New EncoderReplacementFallback("*"),
                                           New DecoderReplacementFallback("*"))

        Dim str1 As String = String.Format("{0} {1} {2}", ChrW(&h24C8), ChrW(&h2075), ChrW(&h221E))
        Console.WriteLine(str1)
        For Each ch In str1
            Console.Write("{0} ", Convert.ToUInt16(ch).ToString("X4"))
        Next
        Console.WriteLine()

        Dim bytes() As Byte = cp1252r.GetBytes(str1)
        Dim str2 As String = cp1252r.GetString(bytes)
        Console.WriteLine("Round-trip: {0}", str1.Equals(str2))
        If Not str1.Equals(str2) Then
            Console.WriteLine(str2)
            For Each ch In str2
                Console.Write("{0} ", Convert.ToUInt16(ch).ToString("X4"))
            Next
            Console.WriteLine()
        End If
    End Sub
End Module
' The example displays the following output:
'       Ⓢ ⁵ ∞
'       24C8 0020 2075 0020 221E
'       Round-trip: False
'       * * *
'       002A 0020 002A 0020 002A

Not

Bir kodlama için ayrıca bir değiştirme sınıfı da uygulayabilirsiniz. Daha fazla bilgi için Özel Geri Dönüş Stratejisi Uygulama bölümüne bakın.

SORU İŞARETİ (U+003F) karakterine ek olarak, özellikle Unicode karakterlerine başarıyla çevrilemeyen bayt dizilerinin kodunu çözerken Unicode DEĞİŞTİRME KARAKTERİ (U+FFFD) de bir değiştirme dizesi olarak kullanılır. Ancak, istediğiniz değiştirme dizesini seçebilirsiniz ve bu dize birden çok karakteri içerebilir.

Özel Durum Geri Dönüşü

Bir en uygun geri dönüş veya değiştirme dizesi sağlamak yerine bir kodlayıcı, bir karakter kümesini kodlayamadığında EncoderFallbackException'i oluşturabilir; ve bir kod çözücü, bir bayt dizisinin kodunu çözemediğinde bir DecoderFallbackException'i oluşturabilir. Kodlama ve kod çözme işlemlerinde bir özel durum oluşturmak için, EncoderExceptionFallback yöntemine sırasıyla bir DecoderExceptionFallback ve bir Encoding.GetEncoding(String, EncoderFallback, DecoderFallback) nesnesi sağlayın. Aşağıdaki örnek, ASCIIEncoding sınıfıyla özel durum geri dönüşünü gösterir.

using System;
using System.Text;

public class Example
{
   public static void Main()
   {
      Encoding enc = Encoding.GetEncoding("us-ascii",
                                          new EncoderExceptionFallback(),
                                          new DecoderExceptionFallback());

      string str1 = "\u24C8 \u2075 \u221E";
      Console.WriteLine(str1);
      foreach (var ch in str1)
         Console.Write("{0} ", Convert.ToUInt16(ch).ToString("X4"));

      Console.WriteLine("\n");

      // Encode the original string using the ASCII encoder.
      byte[] bytes = {};
      try {
         bytes = enc.GetBytes(str1);
         Console.Write("Encoded bytes: ");
         foreach (var byt in bytes)
            Console.Write("{0:X2} ", byt);

         Console.WriteLine();
      }
      catch (EncoderFallbackException e) {
         Console.Write("Exception: ");
         if (e.IsUnknownSurrogate())
            Console.WriteLine("Unable to encode surrogate pair 0x{0:X4} 0x{1:X3} at index {2}.",
                              Convert.ToUInt16(e.CharUnknownHigh),
                              Convert.ToUInt16(e.CharUnknownLow),
                              e.Index);
         else
            Console.WriteLine("Unable to encode 0x{0:X4} at index {1}.",
                              Convert.ToUInt16(e.CharUnknown),
                              e.Index);
         return;
      }
      Console.WriteLine();

      // Decode the ASCII bytes.
      try {
         string str2 = enc.GetString(bytes);
         Console.WriteLine("Round-trip: {0}", str1.Equals(str2));
         if (! str1.Equals(str2)) {
            Console.WriteLine(str2);
            foreach (var ch in str2)
               Console.Write("{0} ", Convert.ToUInt16(ch).ToString("X4"));

            Console.WriteLine();
         }
      }
      catch (DecoderFallbackException e) {
         Console.Write("Unable to decode byte(s) ");
         foreach (byte unknown in e.BytesUnknown)
            Console.Write("0x{0:X2} ");

         Console.WriteLine("at index {0}", e.Index);
      }
   }
}
// The example displays the following output:
//       Ⓢ ⁵ ∞
//       24C8 0020 2075 0020 221E
//
//       Exception: Unable to encode 0x24C8 at index 0.
Imports System.Text

Module Example
    Public Sub Main()
        Dim enc As Encoding = Encoding.GetEncoding("us-ascii",
                                                   New EncoderExceptionFallback(),
                                                   New DecoderExceptionFallback())

        Dim str1 As String = String.Format("{0} {1} {2}", ChrW(&h24C8), ChrW(&h2075), ChrW(&h221E))
        Console.WriteLine(str1)
        For Each ch In str1
            Console.Write("{0} ", Convert.ToUInt16(ch).ToString("X4"))
        Next
        Console.WriteLine()
        Console.WriteLine()

        ' Encode the original string using the ASCII encoder.
        Dim bytes() As Byte = {}
        Try
            bytes = enc.GetBytes(str1)
            Console.Write("Encoded bytes: ")
            For Each byt In bytes
                Console.Write("{0:X2} ", byt)
            Next
            Console.WriteLine()
        Catch e As EncoderFallbackException
            Console.Write("Exception: ")
            If e.IsUnknownSurrogate() Then
                Console.WriteLine("Unable to encode surrogate pair 0x{0:X4} 0x{1:X3} at index {2}.",
                                  Convert.ToUInt16(e.CharUnknownHigh),
                                  Convert.ToUInt16(e.CharUnknownLow),
                                  e.Index)
            Else
                Console.WriteLine("Unable to encode 0x{0:X4} at index {1}.",
                                  Convert.ToUInt16(e.CharUnknown),
                                  e.Index)
            End If
            Exit Sub
        End Try
        Console.WriteLine()

        ' Decode the ASCII bytes.
        Try
            Dim str2 As String = enc.GetString(bytes)
            Console.WriteLine("Round-trip: {0}", str1.Equals(str2))
            If Not str1.Equals(str2) Then
                Console.WriteLine(str2)
                For Each ch In str2
                    Console.Write("{0} ", Convert.ToUInt16(ch).ToString("X4"))
                Next
                Console.WriteLine()
            End If
        Catch e As DecoderFallbackException
            Console.Write("Unable to decode byte(s) ")
            For Each unknown As Byte In e.BytesUnknown
                Console.Write("0x{0:X2} ")
            Next
            Console.WriteLine("at index {0}", e.Index)
        End Try
    End Sub
End Module
' The example displays the following output:
'       Ⓢ ⁵ ∞
'       24C8 0020 2075 0020 221E
'       
'       Exception: Unable to encode 0x24C8 at index 0.

Not

Ayrıca bir kodlama işlemi için özel bir özel durum işleyicisi uygulayabilirsiniz. Daha fazla bilgi için Özel Geri Dönüş Stratejisi Uygulama bölümüne bakın.

EncoderFallbackException ve DecoderFallbackException nesneleri, özel durumu oluşturan durum hakkında aşağıdaki bilgileri sağlar:

EncoderFallbackException ve DecoderFallbackException nesneleri özel durum hakkında yeterli tanılama bilgisi sağlasa da, kodlama veya kod çözme arabelleğine erişim sağlamaz. Bu nedenle bu nesneler, geçersiz verinin kodlama veya kod çözme yönteminde değiştirilmesine veya düzeltilmesine izin vermez.

Implementing a Custom Fallback Strategy

.NET, kod sayfaları tarafından dahili olarak uygulanan en uygun eşlemeye ek olarak, geri dönüş stratejisi uygulamak için aşağıdaki sınıfları içerir:

Ek olarak, aşağıdaki adımları izleyerek en iyi geri dönüş, değiştirme geri dönüşü veya özel durum geri dönüşü kullanan özel bir çözüm uygulayabilirsiniz:

  1. Kodlama işlemleri için EncoderFallback sınıfından, kod çözme işlemleri için DecoderFallback sınıfından bir sınıf türetin.

  2. Kodlama işlemleri için EncoderFallbackBuffer sınıfından, kod çözme işlemleri için DecoderFallbackBuffer sınıfından bir sınıf türetin.

  3. Özel durum geri dönüşü için, eğer önceden tanımlı EncoderFallbackException ve DecoderFallbackException sınıfları gereksinimlerinizi karşılamıyorsa, Exception veya ArgumentException gibi bir özel durum nesnesinden bir sınıf türetin.

EncoderFallback veya DecoderFallback Öğesinden Türetme

Özel bir geri dönüş çözümü uygulamak için, kodlama işlemleri için EncoderFallback sınıfından ve kod çözme işlemleri için DecoderFallback sınıfından devralan bir sınıf oluşturmanız gerekir. Bu sınıfların örnekleri Encoding.GetEncoding(String, EncoderFallback, DecoderFallback) yöntemine geçirilir ve kodlama sınıfıyla geri dönüş uygulaması arasında bir aracı görevi görür.

Bir kodlayıcı veya kod çözücü için özel bir geri dönüş çözümü oluşturduğunuzda, aşağıdaki üyeleri uygulamanız gerekir:

EncoderFallbackBuffer veya DecoderFallbackBuffer Öğesinden Türetme

Özel bir geri dönüş çözümü uygulamak için aynı zamanda, kodlama işlemleri için EncoderFallbackBuffer sınıfından ve kod çözme işlemleri için DecoderFallbackBuffer sınıfından devralan bir sınıf oluşturmanız gerekir. Bu sınıfların örnekleri CreateFallbackBuffer ve EncoderFallback sınıflarının DecoderFallback yöntemi tarafından döndürülür. EncoderFallback.CreateFallbackBuffer yöntemi, kodlayıcı tarafından kodlayamadığı ilk karakterle karşılaştığında çağırılır ve DecoderFallback.CreateFallbackBuffer yöntemi, kod çözücü tarafından başarıyla kodunu çözemediği bir veya daha fazla bayt ile karşılaştığında çağırılır. EncoderFallbackBuffer ve DecoderFallbackBuffer sınıfları geri dönüş uygulamasını sağlar. Her bir örnek, kodlanamayan karakteri veya kodu çözülemeyen bayt dizisini değiştirecek geri dönüş karakterlerini içeren bir arabelleği temsil eder.

Bir kodlayıcı veya kod çözücü için özel bir geri dönüş çözümü oluşturduğunuzda, aşağıdaki üyeleri uygulamanız gerekir:

Eğer geri dönüş uygulaması bir en uygun geri dönüş veya değiştirme geri dönüşü ise, EncoderFallbackBuffer ve DecoderFallbackBuffer sınıflarından türetilen sınıflar ayrıca iki özel örnek alanı içerir: arabellekteki tam karakter sayısı ve bellekte dönülecek sıradaki karakterin dizini.

Bir EncoderFallback Örneği

Önceki bir örnek, ASCII karakterlerine karşılık gelmeyen Unicode karakterlerini bir yıldız işareti (*) ile değiştirmek için değiştirme geri dönüşü kullandı. Aşağıdaki örnek, ASCII olmayan karakterler için daha iyi bir eşleme sağlamak üzere bunun yerine özel bir en uygun geri dönüş uygulaması kullanır.

Aşağıdaki kod, ASCII olmayan karakterlerin en uygun geri dönüş eşlemesini işlemek için CustomMapper sınıfından türetilen EncoderFallback adında bir sınıf tanımlar. CreateFallbackBuffer yöntemi, CustomMapperFallbackBuffer uygulamasını sağlayan bir EncoderFallbackBuffer nesnesini döndürür. CustomMapper sınıfı, desteklenmeyen Unicode karakterlerini (anahtar değeri) ve karşılık gelen 8 bitlik karakterleri (64 bitlik bir tamsayıda ardışık iki baytta depolanan karakterler) depolamak için bir Dictionary<TKey,TValue> nesnesi kullanır. Bu eşleşmeyi geri dönüş arabelleği için kullanılabilir yapmak amacıyla CustomMapper örneği, CustomMapperFallbackBuffer sınıf oluşturucusuna bir parametre olarak geçirilir. U+221E Unicode karakteri için en uzun eşleme "INF" dizesi olduğundan, MaxCharCount özelliği 3'ü döndürür.

public class CustomMapper : EncoderFallback
{
   public string DefaultString;
   internal Dictionary<ushort, ulong> mapping;

   public CustomMapper() : this("*")
   {
   }

   public CustomMapper(string defaultString)
   {
      this.DefaultString = defaultString;

      // Create table of mappings
      mapping = new Dictionary<ushort, ulong>();
      mapping.Add(0x24C8, 0x53);
      mapping.Add(0x2075, 0x35);
      mapping.Add(0x221E, 0x49004E0046);
   }

   public override EncoderFallbackBuffer CreateFallbackBuffer()
   {
      return new CustomMapperFallbackBuffer(this);
   }

   public override int MaxCharCount
   {
      get { return 3; }
   }
}
Public Class CustomMapper : Inherits EncoderFallback
    Public DefaultString As String
    Friend mapping As Dictionary(Of UShort, ULong)

    Public Sub New()
        Me.New("?")
    End Sub

    Public Sub New(ByVal defaultString As String)
        Me.DefaultString = defaultString

        ' Create table of mappings
        mapping = New Dictionary(Of UShort, ULong)
        mapping.Add(&H24C8, &H53)
        mapping.Add(&H2075, &H35)
        mapping.Add(&H221E, &H49004E0046)
    End Sub

    Public Overrides Function CreateFallbackBuffer() As System.Text.EncoderFallbackBuffer
        Return New CustomMapperFallbackBuffer(Me)
    End Function

    Public Overrides ReadOnly Property MaxCharCount As Integer
        Get
            Return 3
        End Get
    End Property
End Class

Aşağıdaki kod, CustomMapperFallbackBuffer sınıfından türetilen EncoderFallbackBuffer sınıfını tanımlar. En uygun eşlemeleri içeren ve CustomMapper içinde tanımlanan sözlük, kendi sınıf oluşturucusunda mevcuttur. Fallback yöntemi, eğer ASCII kodlayıcısının kodlayamadığı Unicode karakterlerinden herhangi biri eşleme sözlüğünde tanımlıysa true'i, aksi halde false'i döndürür. Her geri dönüş için, özel count değişkeni döndürülecek kalan karakter sayısını belirtir, özel index değişkeni ise döndürülecek bir sonraki karakterin charsToReturn dize arabelleğindeki konumu gösterir.

public class CustomMapperFallbackBuffer : EncoderFallbackBuffer
{
   int count = -1;                   // Number of characters to return
   int index = -1;                   // Index of character to return
   CustomMapper fb;
   string charsToReturn;

   public CustomMapperFallbackBuffer(CustomMapper fallback)
   {
      this.fb = fallback;
   }

   public override bool Fallback(char charUnknownHigh, char charUnknownLow, int index)
   {
      // Do not try to map surrogates to ASCII.
      return false;
   }

   public override bool Fallback(char charUnknown, int index)
   {
      // Return false if there are already characters to map.
      if (count >= 1) return false;

      // Determine number of characters to return.
      charsToReturn = String.Empty;

      ushort key = Convert.ToUInt16(charUnknown);
      if (fb.mapping.ContainsKey(key)) {
         byte[] bytes = BitConverter.GetBytes(fb.mapping[key]);
         int ctr = 0;
         foreach (var byt in bytes) {
            if (byt > 0) {
               ctr++;
               charsToReturn += (char) byt;
            }
         }
         count = ctr;
      }
      else {
         // Return default.
         charsToReturn = fb.DefaultString;
         count = 1;
      }
      this.index = charsToReturn.Length - 1;

      return true;
   }

   public override char GetNextChar()
   {
      // We'll return a character if possible, so subtract from the count of chars to return.
      count--;
      // If count is less than zero, we've returned all characters.
      if (count < 0)
         return '\u0000';

      this.index--;
      return charsToReturn[this.index + 1];
   }

   public override bool MovePrevious()
   {
      // Original: if count >= -1 and pos >= 0
      if (count >= -1) {
         count++;
         return true;
      }
      else {
         return false;
      }
   }

   public override int Remaining
   {
      get { return count < 0 ? 0 : count; }
   }

   public override void Reset()
   {
      count = -1;
      index = -1;
   }
}
Public Class CustomMapperFallbackBuffer : Inherits EncoderFallbackBuffer

    Dim count As Integer = -1        ' Number of characters to return
    Dim index As Integer = -1        ' Index of character to return
    Dim fb As CustomMapper
    Dim charsToReturn As String

    Public Sub New(ByVal fallback As CustomMapper)
        MyBase.New()
        Me.fb = fallback
    End Sub

    Public Overloads Overrides Function Fallback(ByVal charUnknownHigh As Char, ByVal charUnknownLow As Char, ByVal index As Integer) As Boolean
        ' Do not try to map surrogates to ASCII.
        Return False
    End Function

    Public Overloads Overrides Function Fallback(ByVal charUnknown As Char, ByVal index As Integer) As Boolean
        ' Return false if there are already characters to map.
        If count >= 1 Then Return False

        ' Determine number of characters to return.
        charsToReturn = String.Empty

        Dim key As UShort = Convert.ToUInt16(charUnknown)
        If fb.mapping.ContainsKey(key) Then
            Dim bytes() As Byte = BitConverter.GetBytes(fb.mapping.Item(key))
            Dim ctr As Integer
            For Each byt In bytes
                If byt > 0 Then
                    ctr += 1
                    charsToReturn += Chr(byt)
                End If
            Next
            count = ctr
        Else
            ' Return default.
            charsToReturn = fb.DefaultString
            count = 1
        End If
        Me.index = charsToReturn.Length - 1

        Return True
    End Function

    Public Overrides Function GetNextChar() As Char
        ' We'll return a character if possible, so subtract from the count of chars to return.
        count -= 1
        ' If count is less than zero, we've returned all characters.
        If count < 0 Then Return ChrW(0)

        Me.index -= 1
        Return charsToReturn(Me.index + 1)
    End Function

    Public Overrides Function MovePrevious() As Boolean
        ' Original: if count >= -1 and pos >= 0
        If count >= -1 Then
            count += 1
            Return True
        Else
            Return False
        End If
    End Function

    Public Overrides ReadOnly Property Remaining As Integer
        Get
            Return If(count < 0, 0, count)
        End Get
    End Property

    Public Overrides Sub Reset()
        count = -1
        index = -1
    End Sub
End Class

Aşağıdaki kod, daha sonra CustomMapper nesnesinin örneğini oluşturur ve Encoding.GetEncoding(String, EncoderFallback, DecoderFallback) yöntemine bunun bir örneğini geçirir. Çıktı, en uygun geri dönüş uygulamasının özgün dizedeki ASCII olmayan üç karakteri başarıyla işlediğini gösterir.

using System;
using System.Collections.Generic;
using System.Text;

class Program
{
   static void Main()
   {
      Encoding enc = Encoding.GetEncoding("us-ascii", new CustomMapper(), new DecoderExceptionFallback());

      string str1 = "\u24C8 \u2075 \u221E";
      Console.WriteLine(str1);
      for (int ctr = 0; ctr <= str1.Length - 1; ctr++) {
         Console.Write("{0} ", Convert.ToUInt16(str1[ctr]).ToString("X4"));
         if (ctr == str1.Length - 1)
            Console.WriteLine();
      }
      Console.WriteLine();

      // Encode the original string using the ASCII encoder.
      byte[] bytes = enc.GetBytes(str1);
      Console.Write("Encoded bytes: ");
      foreach (var byt in bytes)
         Console.Write("{0:X2} ", byt);

      Console.WriteLine("\n");

      // Decode the ASCII bytes.
      string str2 = enc.GetString(bytes);
      Console.WriteLine("Round-trip: {0}", str1.Equals(str2));
      if (! str1.Equals(str2)) {
         Console.WriteLine(str2);
         foreach (var ch in str2)
            Console.Write("{0} ", Convert.ToUInt16(ch).ToString("X4"));

         Console.WriteLine();
      }
   }
}
Imports System.Text
Imports System.Collections.Generic

Module Module1

    Sub Main()
        Dim enc As Encoding = Encoding.GetEncoding("us-ascii", New CustomMapper(), New DecoderExceptionFallback())

        Dim str1 As String = String.Format("{0} {1} {2}", ChrW(&H24C8), ChrW(&H2075), ChrW(&H221E))
        Console.WriteLine(str1)
        For ctr As Integer = 0 To str1.Length - 1
            Console.Write("{0} ", Convert.ToUInt16(str1(ctr)).ToString("X4"))
            If ctr = str1.Length - 1 Then Console.WriteLine()
        Next
        Console.WriteLine()

        ' Encode the original string using the ASCII encoder.
        Dim bytes() As Byte = enc.GetBytes(str1)
        Console.Write("Encoded bytes: ")
        For Each byt In bytes
            Console.Write("{0:X2} ", byt)
        Next
        Console.WriteLine()
        Console.WriteLine()

        ' Decode the ASCII bytes.
        Dim str2 As String = enc.GetString(bytes)
        Console.WriteLine("Round-trip: {0}", str1.Equals(str2))
        If Not str1.Equals(str2) Then
            Console.WriteLine(str2)
            For Each ch In str2
                Console.Write("{0} ", Convert.ToUInt16(ch).ToString("X4"))
            Next
            Console.WriteLine()
        End If
    End Sub
End Module

Ayrıca bkz.