Sdílet prostřednictvím


Kódování znaků v.NET Framework

Znaky jsou abstraktní entity, které mohou být zastoupeny mnoha různými způsoby. Kódování znaků je systém, který dvojice každého znaku v podporované znakové sady s hodnotu, která představuje znak. Například morseovce je znak kódování jednotlivých znaků latinku s bodový vzorek této dvojice a pomlčky, které jsou vhodné pro přenos přes telegrafní řádky. Znak kódování jednotlivých znaků podporované znakové sady s numerickou hodnotu, která představuje znak dvojic počítačů. Kódování znaků má dvě samostatné součásti:

  • Kodér, který převádí posloupnosti znaků do posloupnosti číselných hodnot (bajty).

  • Dekodér, která překládá posloupnost bajtů do posloupnosti znaků.

Kódování znaků popisuje pravidla, podle kterých kodéru a dekodéru pracovat. Například UTF8Encoding Třída popisuje pravidla, kódování a dekódování z 8 bitů Unicode Transformation Format (UTF-8), který používá jedno až čtyři bajty představují do jediného Unicode znaku. Kódování a dekódování může také zahrnovat ověření. Například UnicodeEncoding třídy kontroluje všechny zástupce zda tvoří dvojice platná náhradníků. (Náhradní pár sestává z rozsahu od U + D800 a U + DBFF následuje znak s bod kódu do U + DFFF rozsahu od U + DC00 bod kódu znaku). Základní strategie Určuje jak Kodér zpracovává neplatné znaky nebo jak dekodér zpracovává neplatné bajty.

Poznámka k upozorněníUpozornění

Na.Kódování třídy NET Framework umožňují ukládat a Převést znaková data.By není používají k ukládání binárních dat ve formátu řetězce.V závislosti na kódování použité, převod binárních dat řetězce formátu kódování třídy zavést neočekávané chování a vyrábět nepřesné nebo poškozená data.Binární data převést do formátu řetězce, použijte Convert.ToBase64String(Byte[]) metody.

Aplikace používají tento cíl společného jazykového modulu runtime kodéry mapovat reprezentace znaků Unicode podporované společný jazykový modul runtime pro další schémata kódování. Dekodéry používá k mapování znaků kódování Unicode kódování Unicode.

Toto téma se skládá z následujících částí:

Kódování v.NET Framework

Všechny třídy kódování znaků.NET Framework dědí System.Text.Encoding třídy, která je abstraktní třída definující funkce společné všem kódování znaků. Přístup jednotlivých kódování objektů v.NET Framework, postupujte takto:

  • Použít statické vlastnosti třídyEncoding , která vrací objekty představují standardní znakové kódování v.NET Framework (ASCII, UTF-7, UTF-8, UTF-16 a UTF-32). Například Encoding.Unicode vlastnost vrátí UnicodeEncoding objektu. Každý objekt používá náhradní sekundární popisovače řetězce, které nelze kódovat a bajtů, které nelze dekódovat. (Další informace naleznete Replacement Fallback oddílu.)

  • O kódování volání konstruktoru třídy. Tímto způsobem můžete vytvořit instanci objektů v ASCII, UTF-7, UTF-8, UTF-16 a UTF-32 kódování. Standardně používá každý objekt náhradní sekundární zpracování řetězců, které nelze kódovat a bajtů, které nelze dekódovat, ale můžete určit, že by měla být vyvolána výjimka místo. (Další informace naleznete Replacement Fallback a Exception Fallback oddíly.)

  • Volání Encoding.Encoding(Int32) konstruktor a předáte ji celé číslo představující kódování. Standardní kódování objektů pomocí nouzové náhradní a kódové stránky a dvoubajtové znakové sady (DBCS) kódování objektů přizpůsobená nouzové použití popisovače řetězce, které nelze kódovat a bajtů, které nelze dekódovat. (Další informace naleznete Best-Fit Fallback oddílu.)

  • Volání metodaEncoding.GetEncoding vrátí všechny standardní, kódová stránka nebo kódování DBCS v.NET Framework. Přetížení umožňují určit sekundární objekt kodéru a dekodéru.

PoznámkaPoznámka

Unicode Standard přiřazuje bod kódu (číslo) a název každého znaku ve všech podporovaných skriptu.Například znak "A" představuje název "LATINKY A velké písmeno" a bod kódu U + 0041.Kódování Unicode Transformation Format (UTF) definovat způsoby kódování tento bod kódu do posloupnost jednoho nebo více bajtů.Schéma kódování Unicode zjednodušuje vývoj aplikací svět připraven, protože umožňuje znaky zastoupeny v jednom kódování všechny znakové sady.Vývojáři aplikací již ke sledování schéma kódování použité k výrobě znaků pro určitý jazyk nebo psaní systému a dat lze sdílet mezi systémy mezinárodně bez poškození.

Na.NET Framework podporuje tři definice standardu Unicode kódování: UTF-8, UTF-16 a UTF-32.Další informace naleznete Unicode Standard na domovskou stránku Unicode.

Můžete načíst informace o kódování v.NET Framework voláním Encoding.GetEncodings metody. Na.NET Framework podporuje znakovými systémy uvedené v následující tabulce.

Kódování

Třída

Popis

Výhody a nevýhody

standard ASCII

ASCIIEncoding

Zakóduje omezený rozsah znaků pomocí nižší sedm bitů bajt.

Protože toto kódování pouze podporuje hodnoty znak U + 0000 až U + 007F, ve většině případů je nedostatečná mezinárodních aplikací.

UTF-7

UTF7Encoding

Představuje jako sekvence 7bitové znaky ASCII znaky. Unicode znaky jiné než standardu ASCII jsou reprezentovány řídicí sekvencí znaků standardu ASCII.

UTF-7 podporuje protokoly, například e-mailové a diskusní skupiny protokolů. Kódování UTF-7 však není zvlášť bezpečné ani robustní. V některých případech změnou jeden bit může radikálně změnit výklad celý řetězec UTF-7. V ostatních případech lze kódovat různých řetězců UTF-7 stejný text. Sekvence, které obsahují jiné znaky než ASCII vyžaduje více místa než UTF-8, UTF-7 a kódování a dekódování je pomalejší. Proto používejte UTF-8 namísto UTF-7-li to možné.

UTF-8

UTF8Encoding

Každý bod kódu Unicode představuje jako posloupnost jednoho do čtyř bajtů.

Podporuje data 8bitové formáty UTF-8 a pracuje s mnoha operačními systémy. Pro ASCII rozsah znaků je znaková sada UTF-8 totožná ASCII kódováním a umožňuje širší sadu znaků. Však čínské Japonština Korejština (ČJK) skriptů UTF-8 může vyžadovat tři bajtů pro každý znak a může způsobit větší velikosti dat než UTF-16. Všimněte si, že někdy množství dat ASCII jako značky HTML ospravedlňuje zvětší oblast CJK.

UTF-16

UnicodeEncoding

Jako posloupnost jednoho nebo dvou celých čísel 16-bit představuje každý bod kódu Unicode. Nejběžnější znaky Unicode vyžadují pouze jeden bod kódu UTF-16, i když doplňující znaky Unicode (U + 10 000 a vyšší) vyžadují dva body náhradního kódu UTF-16. Podporovány jsou obě pořadí bytů little-endian a big-endian.

Kódování UTF-16 společného jazykového modulu runtime se používá k reprezentaci Char a String systému představující používají hodnoty a to WCHAR hodnoty.

UTF-32

UTF32Encoding

Jako celé 32bitové číslo představuje každý bod kódu Unicode. Podporovány jsou obě pořadí bytů little-endian a big-endian.

Kódování UTF-32 se používá, když chcete vyhnout chování náhradního kód bod kódování UTF-16 v operačních systémech, pro které je příliš důležité kódovaného místa aplikace. Vykreslení zobrazení na jediné Glyfy můžete stále kódován s více znaky UTF-32.

Kódování ANSI/ISO

Poskytuje podporu pro různé znakové stránky. V operačních systémech Windows znakové stránky slouží k podpoře jazyk nebo skupinu jazyků. Tabulku obsahující seznam podporovaných znakových stránek.NET Framework viz Encoding Třída Můžete načíst objekt kódování pro určitou znakovou stránku voláním Encoding.GetEncoding(Int32) metody.

Znaková stránka obsahuje 256 bodů kódu a nuly. Ve většině znakové stránky představují 0 až 127 body kódu znakové sady ASCII a body kódu 128 až 255 významně liší mezi znakové stránky. Například znaková stránka 1252 poskytuje znaky latinky písemné systémy včetně angličtiny, němčiny a francouzštiny. Poslední kód 128 bodů v kódová stránka 1252 obsahovat znaky zvýraznění. Kódová stránka 1253 poskytuje kódy znaků, které jsou vyžadovány v řecké. Poslední kód 128 bodů v kódová stránka 1253 obsahovat řecké znaky. Proto aplikace, která využívá znakové stránky ANSI nelze uložit řecké a němčina v proudu stejný text pokud obsahuje identifikátor, který označuje kód odkazované stránky.

Dvoubajtové znakové sady (DBCS) kódování

Podporuje jazyky, například čínština, japonština nebo korejština, které obsahují více než 256 znaků. V sadě DBCS reprezentuje každý znak dvojice bodů kódu (dvoubajtová hodnota). Encoding.IsSingleByte Vrátí vlastnost false pro kódování DBCS. Můžete načíst objekt kódování pro konkrétní DBCS voláním Encoding.GetEncoding(Int32) metody.

V sadě DBCS reprezentuje každý znak dvojice bodů kódu (dvoubajtová hodnota). Když aplikace zpracovává DBCS data, první bajt znaku DBCS (vedoucí bajt) zpracovány v kombinaci s bezprostředně následující bajt stopu. Protože jednu dvojici dvoubajtové znakové body může představovat různé znaky v závislosti na znakové stránce toto schéma stále neumožňuje kombinaci dvou jazyků, například japonštiny a čínštiny do stejného datového proudu.

Tato kódování umožňují pracovat se znaky Unicode, jakož i s kódování nejčastěji používané pro starší aplikace. Kromě toho můžete vytvořit vlastní kódování podle definice třídy, který je odvozen od Encoding a přepsání jeho členů.

Výběr třídy kódování

Pokud máte možnost volby kódování pro aplikace, byste měli použít kódování Unicode, pokud možno buď UTF8Encoding nebo UnicodeEncoding. (Na.NET Framework podporuje také třetí kódování Unicode, UTF32Encoding.)

Pokud plánujete použít kódování ASCII (ASCIIEncoding), zvolte UTF8Encoding namísto. Kódování dva identické znakové sady ASCII, ale UTF8Encoding má následující výhody:

  • Že může představovat každý znak Unicode ASCIIEncoding podporuje pouze Unicode znaku hodnot mezi U + 0000 a U + 007F.

  • Poskytuje lepší zabezpečení a zjišťování chyb.

  • Byl naladěn jako rychlá co nejdříve a musí být rychlejší než jiné kódování. Dokonce i pro obsah, který je zcela v ASCII, jsou operace provedené pomocí UTF8Encoding rychlejší než operace provedené pomocí ASCIIEncoding.

Měli byste zvážit použití ASCIIEncoding pouze pro starší verze aplikací. Ale i pro starší aplikace UTF8Encoding může být vhodnější (za předpokladu výchozí nastavení) z následujících důvodů:

  • Pokud aplikace obsahuje obsah, který není čistě ASCII a zakóduje s ASCIIEncoding, každý znak-ASCII zakóduje jako otazník (?). Pokud aplikace poté dekóduje tato data, informace jsou ztraceny.

  • Pokud aplikace obsahuje obsah, který není čistě ASCII a zakóduje s UTF8Encoding, výsledek zdá být nesrozumitelné, pokud jsou interpretovány jako ASCII. Ale pokud aplikace pak používá k dekódování dat dekodér UTF-8, data provádí round trip úspěšně.

Ve webové aplikaci by měl odrážet znaků odeslaných klientovi odpověď na požadavek webové kódování použité v klientském počítači. Ve většině případů byste měli nastavit HttpResponse.ContentEncoding vlastnost hodnotu vrácenou HttpRequest.ContentEncoding vlastností zobrazení textu v kódování, že uživatel očekává.

Pomocí objektu kódování

Kodér jeho číselné (bajt) ekvivalentní převede řetězec znaků (nejčastěji znaků Unicode). Pomocí kodéru ASCII můžete například převést na ASCII znaky Unicode, takže lze zobrazit v konzole. Provést převod, zavolejte Encoding.GetBytes metody. Pokud chcete zjistit, kolik bajtů jsou požadovány k uložení zakódované znaky před provedením kódování, zavolejte GetByteCount metody.

Následující příklad používá jednobajtové pole k zakódování řetězce ve dvou samostatných operací. Udržuje index určuje počáteční pozici v bajtovém poli další sadu ASCII kódování bajtů. Volá ASCIIEncoding.GetByteCount(String) metodou, jak zajistit, že bajtové pole je dostatečně velké pro uchování kódovaný řetězec. Pak zavolá ASCIIEncoding.GetBytes(String, Int32, Int32, Byte[], Int32) Metoda kódování znaků v řetězci.

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

Dekodér převede bajtové pole, které odráží určitý znak kódování do sady znaků v poli znak nebo řetězec. Chcete-li dekódovat bajtové pole do pole znaků, můžete zavolat Encoding.GetChars metody. Chcete-li do řetězce dekódovat bajtové pole, zavolejte GetString metody. Pokud chcete zjistit, kolik znaků jsou požadovány k uložení dekódovanou bajty před provedením dekódování, zavolejte GetCharCount metody.

Následující příklad kóduje tři řetězce a dekóduje jejich do jednoho pole znaků. Udržuje index označuje pozice do pole znaků pro další sadu znaků dekódována. Volá GetCharCount metody tak, aby pole znaků dostatečně velké pro uchování všech na dekódovanou znaků. Pak zavolá ASCIIEncoding.GetChars(Byte[], Int32, Int32, Char[], Int32) Metoda dekódovat bajtové pole.

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

Kódování a dekódování metody třídy odvozené z Encoding jsou navrženy pro práci na úplnou sadu dat; To znamená všechna data kódována nebo dekódována dodané na jedinou metodu volání. V některých případech však data jsou dostupná v proudu a mohou být k dispozici pouze ze samostatných operací čtení dat kódována nebo dekódována. To vyžaduje operace kódování nebo dekódování pamatovat z předchozí vyvolání uloženého stavu. Metody tříd odvozených od Encoder a Decoder jsou schopny zpracovat kódování a dekódování operací rozložené na více volání metody.

Encoder Je k dispozici kódování tohoto objektu pro určité kódování Encoding.GetEncoder vlastnost. A Decoder je k dispozici kódování tohoto objektu pro určité kódování Encoding.GetDecoder vlastnost. Operace dekódování, Všimněte si, že třídy odvozené z Decoder patří Decoder.GetChars Metoda, ale nemají odpovídající metodu Encoding.GetString.

Následující příklad ukazuje rozdíl mezi použitím Encoding.GetChars a Decoder.GetChars metody pro dekódování do pole bajtů kódování Unicode. Příklad kóduje řetězec, který obsahuje některé znaky Unicode do souboru a potom pomocí dvou metod dekódování dekódovat deset bajtů najednou. Jelikož náhradní pár dochází v bajtech desátá a jedenáctá, dekóduje volání metody samostatné. Výstup ukazuje, Encoding.GetChars Metoda není správně dekódovat bajty a místo toho je nahrazen znakem U + FFFD (znak nahrazení). Na druhé straně Decoder.GetChars Metoda je úspěšně dekódovat bajtové pole získat původní řetězec.

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

Volba nouzové strategie

Metoda pokusí kódování nebo dekódování znaku, ale neexistuje žádné mapování, musí implementovat základní strategii, která určuje způsob zpracování selhání mapování. Existují tři typy základní strategií:

  • Přizpůsobená nouzové

  • Náhradní sekundární

  • Sekundární výjimka

Důležitá poznámkaDůležité

Nejběžnější problémy v kódování operací dojít při znak Unicode nelze namapovat k určitým kódem kódování stránky.Nejběžnější problémy v operace dekódování dojít při posloupnosti neplatný bajt nelze převést na platný znaků Unicode.Z těchto důvodů byste měli vědět, která používá kódování určitého objektu základní strategie.Je to možné, měli byste určit sekundární strategie, když konkretizujete objekt používá kódování objekt.

Přizpůsobená nouzové

Když znak nemá přesnou shodu v cílové kódování, zkuste namapovat na podobnou povahu kodéru. (Přizpůsobená se převážně kódování spíše než dekódování problém. Existují velmi málo znakové stránky, které obsahují znaky, které nelze úspěšně namapovány na Unicode). Výchozí znaková stránka je přizpůsobená nouzové a dvoubajtové znakové sady, kódování, které jsou načteny Encoding.GetEncoding(Int32) a Encoding.GetEncoding(String) přetížení.

PoznámkaPoznámka

Teoreticky podle tříd kódování Unicode.NET Framework (UTF8Encoding, UnicodeEncoding, a UTF32Encoding) tak lze použít k odstranění přizpůsobená sekundární problémy. podporovat každý znak v každé sadě znak

Strategie přizpůsobené lišit pro různé znakové stránky a nebyly podrobně zdokumentovány. Například pro některé znakové stránky mapuje znaky latinky s plnou šířkou na běžnější znaky latinky s poloviční šířkou. Pro jiné znakové stránky toto mapování není provedeno. I za agresivní strategie přizpůsobené není žádná který si dokážete představit některé znaky v kódování některé velikosti. Například čínský znak nemá žádné rozumné mapování kódová stránka 1252. V tomto případě se použije náhradní řetězec. Ve výchozím nastavení je tento řetězec pouze jeden otazník (U+003F).

Následující příklad používá kódová stránka 1252 (Windows znakovou stránku západoevropských jazycích) znázorňující přizpůsobená mapování a jeho nedostatky. Encoding.GetEncoding(Int32) Metoda slouží k načtení objektu kódování pro kódová stránka 1252. Standardně používá přizpůsobená mapování pro znaky Unicode nepodporuje. Příklad konkretizuje řetězec, který obsahuje tři znaky - v KROUŽKU S velké písmeno LATINKY U + 24 C 8 PĚT jako horní index (U + 2075) a NEKONEČNO (U + 221E) - oddělené mezerami. Výstup z příkladu ukazuje, kdy je kódovaný řetězec, tři znaky místo původní nahrazují OTAZNÍK (U + 003F), ČÍSLICE PĚT (U + 0035) a OSM ČÍSLIC (U + 0038). ČÍSLICE OSM je velmi chudých náhradní nepodporovaný znak NEKONEČNA a OTAZNÍK označuje, že nebyla k dispozici pro původní znak mapování.

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

Výchozí chování je přizpůsobená mapování Encoding objektu, kóduje data ve formátu Unicode do datové stránky kód a jsou starší aplikace, které jsou závislé na chování. Většina nových aplikací však neměli přizpůsobené chování z bezpečnostních důvodů. Například aplikace není vložte název domény prostřednictvím přizpůsobená kódování.

PoznámkaPoznámka

Můžete implementovat vlastní přizpůsobené sekundární mapování pro kódování.Další informace naleznete v oddílu Implementing a Custom Fallback Strategy.

Pokud přizpůsobená se výchozí kódování objektu, můžete zvolit jiný základní strategie při načítání Encoding voláním objektu Encoding.GetEncoding(Int32, EncoderFallback, DecoderFallback) nebo Encoding.GetEncoding(String, EncoderFallback, DecoderFallback) přetížení. Následující část obsahuje příklad, který nahradí každý znak, který nelze namapovat k kódová stránka 1252 hvězdičkou (*).

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

Náhradní nouzové

Znak v cílovém schématu nemá přesná shoda, ale neexistuje žádná odpovídající znak, který lze namapovat na, můžete určit aplikaci nahrazovací znak nebo řetězec. Toto je výchozí chování dekodéru Unicode REPLACEMENT_CHARACTER (U + FFFD) nahradí všechny dvoubajtový pořadí, které nelze dekódovat. Je také výchozí chování ASCIIEncoding třídy, který nahradí každý znak, který nelze kódovat nebo dekódovat s otazníkem. Znak nahrazení řetězce Unicode z předchozího příkladu ukazuje následující příklad. Výstup ukazuje, každý znak, který nelze dekódovat do bajtu hodnotou ASCII nahrazuje 0x3F, což je kód ASCII otazník.

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

Na.NET Framework zahrnuje EncoderReplacementFallback a DecoderReplacementFallback tříd, které nahradit náhradní řetězec Pokud znaku není mapována přesně v kódování nebo dekódování operace. Standardně je tento náhradní řetězec otazník, ale můžete volat přetížení konstruktoru třídy zvolit jiný řetězec. Náhradní řetězec je obvykle jeden znak, přestože to není vyžadováno. Následující příklad změní chování kódovací stránka 1252 kód podle konkretizaci EncoderReplacementFallback objekt, který používá hvězdičku (*) jako náhradní řetězec.

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
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
PoznámkaPoznámka

Můžete implementovat náhradní třída pro kódování.Další informace naleznete v oddílu Implementing a Custom Fallback Strategy.

Vedle OTAZNÍKEM (U + 003F) NAHRAZOVACÍ znak Unicode (U + FFFD) se běžně používá jako náhradní řetězec, zejména při dekódování bajtů sekvence, které nelze úspěšně převést na znaky Unicode. Máte zvolit libovolný řetězec náhradní volno a může obsahovat více znaků.

Nouzové výjimka

Namísto poskytování přizpůsobené nouzové nebo náhradní řetězec, lze vyvolat kodéru EncoderFallbackException Pokud nelze kódovat sada znaků a dekodér lze vyvolat DecoderFallbackException Pokud nelze dekódovat bajtové pole. K vyvoláním výjimky v kódování a dekódování operace můžete zadat EncoderExceptionFallback objektu a DecoderExceptionFallback objektu, aby Encoding.GetEncoding(String, EncoderFallback, DecoderFallback) metody. Následující příklad ukazuje sekundární s výjimkou ASCIIEncoding Třída

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.
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.
PoznámkaPoznámka

Můžete implementovat vlastní exception handler pro kódování operaci.Další informace naleznete v oddílu Implementing a Custom Fallback Strategy.

EncoderFallbackException a DecoderFallbackException objekty poskytují následující informace o stavu, který způsobil výjimku:

Ačkoli EncoderFallbackException a DecoderFallbackException objekty poskytují dostatečné diagnostické informace o výjimce, poskytují přístup na kódování nebo dekódování vyrovnávací paměti. Proto nepovolují neplatná data nahradit nebo opravit v rámci metody kódování nebo dekódování.

Provádění vlastní základní strategie

Vedle přizpůsobená mapování interně implementovaný pomocí znakových stránek.NET Framework zahrnuje následující třídy pro provádění strategie národního prostředí:

Kromě toho můžete implementovat vlastní řešení využívající přizpůsobená nouzové, nouzové náhradní nebo nouzové výjimku pomocí následujících kroků:

  1. Odvození třídy z EncoderFallback pro kódování operace a z DecoderFallback pro operace dekódování.

  2. Odvození třídy z EncoderFallbackBuffer pro kódování operace a z DecoderFallbackBuffer pro operace dekódování.

  3. Sekundární, pokud výjimka předdefinované EncoderFallbackException a DecoderFallbackException tříd podle svých potřeb, odvození třídy z objektu výjimky jako Exception nebo ArgumentException.

Vyplývající z EncoderFallback nebo DecoderFallback

Vlastní záložní řešení implementovat, musíte vytvořit třídu, která vychází z EncoderFallback pro kódování operace a z DecoderFallback pro operace dekódování. Instance těchto tříd jsou předány Encoding.GetEncoding(String, EncoderFallback, DecoderFallback) Metoda a slouží jako zprostředkovatel mezi kódování třídy a provádění národního prostředí.

Při vytváření vlastní záložní řešení kodéru a dekodéru musí implementovat následující členy:

Vyplývající z EncoderFallbackBuffer nebo DecoderFallbackBuffer

Vlastní záložní řešení implementovat, musíte také vytvořit třídy, která dědí z EncoderFallbackBuffer pro kódování operace a z DecoderFallbackBuffer pro operace dekódování. Jsou vrácené instance těchto tříd CreateFallbackBuffer metodu EncoderFallback a DecoderFallback tříd. EncoderFallback.CreateFallbackBuffer Je volána metoda kodérem když narazí na první znak, který není schopen kódovat, a DecoderFallback.CreateFallbackBuffer metoda volá dekodér když narazí na jeden nebo více bajtů, které není schopna dekódovat. EncoderFallbackBuffer a DecoderFallbackBuffer třídy poskytují základní implementace. Každá instance představuje vyrovnávací paměti, která obsahuje základní znaky, které nahradí znak, který nelze zakódovat nebo pořadí bajtů, které nelze dekódovat.

Při vytváření vlastní záložní řešení kodéru a dekodéru musí implementovat následující členy:

Přizpůsobená nouzové nebo nahrazení nouzové se sekundární implementace třídy odvozené z EncoderFallbackBuffer a DecoderFallbackBuffer také udržovat dvě pole privátní instance: přesný počet znaků ve vyrovnávací paměti; a index další znak vrátit do vyrovnávací paměti.

Příklad EncoderFallback

Předchozí příklad pro nahrazení sekundární nahradit znaky Unicode, které neodpovídá znaky ASCII s hvězdičkou (*). Následující příklad používá vlastní přizpůsobené sekundární provádění místo poskytnout lepší mapování-ASCII znaky.

Následující kód definuje třídu pojmenovanou CustomMapper , je odvozen z EncoderFallback zpracování přizpůsobená mapování - ASCII znaky. Jeho CreateFallbackBuffer Metoda vrátí CustomMapperFallbackBuffer objektu, který poskytuje EncoderFallbackBuffer provedení. CustomMapper Používá třídy Dictionary<TKey, TValue> objekt uložit mapování nepodporované znaky Unicode (hodnota klíče) a jejich odpovídající 8bitové znaky (které jsou uloženy ve dvou po sobě následujících bajtů v 64bitové celé číslo). Zpřístupnit toto mapování sekundární vyrovnávací paměť CustomMapper instance je předán jako parametr CustomMapperFallbackBuffer konstruktoru třídy. Protože řetězec "INF" je nejdelší mapování pro znaky Unicode U + 221E MaxCharCount vlastnost vrátí 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
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; }
   } 
}

Následující kód definuje CustomMapperFallbackBuffer třídy, který je odvozen od EncoderFallbackBuffer. Slovník obsahující přizpůsobená mapování, který je definován v CustomMapper instance je k dispozici jeho konstruktoru třídy. Jeho Fallback Metoda vrátí true Pokud znaků Unicode, které nelze zakódovat kodér ASCII jsou definovány ve slovníku mapování; v opačném případě vrátí hodnotu false. Pro každé nouzové soukromého count proměnná Určuje počet znaků, které mají být vráceny, zůstávají a privátní index proměnné označuje pozici v řetězci vyrovnávací charsToReturn, dalšího znaku návratu.

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

Následující kód poté vytvoří instanci CustomMapper objektu a předá ji instanci Encoding.GetEncoding(String, EncoderFallback, DecoderFallback) metody. Výstup označuje přizpůsobená sekundární provádění úspěšně zpracovává tři znaky než ASCII v původní řetězec.

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

Viz také

Odkaz

Encoder

Decoder

DecoderFallback

Encoding

EncoderFallback

Další zdroje

Kódování a lokalizace

Historie změn

Datum

Poslední dokumenty

Důvod

Říjen 2010

Rozsáhlé revidován.

Rozšíření informace