Freigeben über


Verwenden von Zeichencodierungsklassen in .NET

In diesem Artikel wird erläutert, wie Sie die Klassen verwenden, die .NET für die Codierung und Decodierung von Text mithilfe verschiedener Codierungsschemas bereitstellt. In den Anweisungen wird davon ausgegangen, dass Sie die Einführung in die Zeichencodierung in .NET gelesen haben.

Encoder und Decoder

.NET stellt Codierungsklassen bereit, die Text mithilfe verschiedener Codierungssysteme codieren und decodieren. Beispielsweise beschreibt die Klasse UTF8Encoding die Regeln für das Codieren nach und Decodieren aus UTF-8. .NET verwendet UTF-16-Codierung (dargestellt durch die UnicodeEncoding Klasse) für string Instanzen. Encoder und Decoder sind für andere Codierungsschemas verfügbar.

Die Kodierung und Dekodierung kann auch eine Überprüfung umfassen. Beispielsweise überprüft die UnicodeEncoding-Klasse alle Instanzen des char im Ersatzzeichenbereich, um sicherzustellen, dass sie sich in gültigen Ersatzzeichenpaaren befinden. Eine Fallbackstrategie bestimmt, wie ein Encoder ungültige Zeichen behandelt oder wie ein Decoder ungültige Bytes verarbeitet.

Warnung

.NET-Codierungsklassen bieten eine Möglichkeit zum Speichern und Konvertieren von Zeichendaten. Sie sollten nicht zum Speichern von Binärdaten in Zeichenfolgenform verwendet werden. Je nach verwendeter Codierung kann das Konvertieren von Binärdaten in das Zeichenfolgenformat mit den Codierungsklassen zu unerwartetem Verhalten führen und ungenaue oder beschädigte Daten erzeugen. Verwenden Sie die Convert.ToBase64String Methode, um Binärdaten in ein Zeichenfolgenformular zu konvertieren.

Alle Zeichencodierungsklassen in .NET erben von der System.Text.Encoding Klasse. Dabei handelt es sich um eine abstrakte Klasse, die die Funktionalität definiert, die allen Zeichencodierungen gemeinsam ist. Gehen Sie wie folgt vor, um auf die einzelnen in .NET implementierten Codierungsobjekte zuzugreifen:

  • Verwenden Sie die statischen Eigenschaften der Encoding Klasse, die Objekte zurückgeben, die die standardzeichencodierungen darstellen, die in .NET verfügbar sind (ASCII, UTF-7, UTF-8, UTF-16 und UTF-32). Beispielsweise gibt die Encoding.Unicode Eigenschaft ein UnicodeEncoding Objekt zurück. Jedes Objekt verwendet ersatzfallback zum Behandeln von Zeichenfolgen, die nicht codiert werden können, und Bytes, die nicht decodiert werden können. Weitere Informationen finden Sie unter "Ersatzfallback".

  • Rufen Sie den Klassenkonstruktor der Codierung auf. Objekte für die ASCII-, UTF-7-, UTF-8-, UTF-16- und UTF-32-Codierungen können auf diese Weise instanziiert werden. Standardmäßig verwendet jedes Objekt ersatzfallback zum Behandeln von Zeichenfolgen, die nicht codiert werden können, und Byte, die nicht decodiert werden können, aber Sie können angeben, dass stattdessen eine Ausnahme ausgelöst werden soll. Weitere Informationen finden Sie unter "Ersatzfallback " und "Ausnahmefallback".

  • Rufen Sie den Encoding(Int32) Konstruktor auf und übergeben Sie ihm eine ganze Zahl, die die Codierung darstellt. Standardcodierungsobjekte verwenden Ersatzfallback und Codepage- und DBCS-Codierungsobjekte (Double-Byte Character Set) verwenden am besten geeigneten Fallback, um Zeichenfolgen zu verarbeiten, die nicht codiert werden können, und Bytes, die sie nicht decodieren können. Weitere Informationen finden Sie im Abschnitt Best-fit-Fallback.

  • Rufen Sie die Encoding.GetEncoding Methode auf, die eine beliebige Standard-, Codepage- oder DBCS-Codierung zurückgibt, die in .NET verfügbar ist. Mit Überladungen können Sie ein Fallbackobjekt sowohl für den Encoder als auch für den Decoder angeben.

Sie können Informationen zu allen in .NET verfügbaren Codierungen abrufen, indem Sie die Encoding.GetEncodings Methode aufrufen. .NET unterstützt die in der folgenden Tabelle aufgeführten Zeichencodierungsschemas.

Codierungsklasse Beschreibung
ASCII Codiert einen begrenzten Zeichenbereich mithilfe der unteren sieben Bits eines Bytes. Da diese Codierung nur Zeichenwerte zwischen U+0000 und U+007F unterstützt, ist sie meistens für internationalisierte Anwendungen unzureichend.
UTF-7 Stellt Zeichen als Sequenzen von 7-Bit-ASCII-Zeichen dar. Nicht-ASCII-Unicode-Zeichen werden durch eine Escapesequenz von ASCII-Zeichen dargestellt. UTF-7 unterstützt Protokolle wie E-Mail und Newsgroup. UTF-7 ist jedoch nicht besonders sicher oder robust. In einigen Fällen kann das Ändern eines Bits die Interpretation einer gesamten UTF-7-Zeichenfolge radikal ändern. In anderen Fällen können unterschiedliche UTF-7-Zeichenfolgen denselben Text codieren. Für Sequenzen, die Nicht-ASCII-Zeichen enthalten, erfordert UTF-7 mehr Speicherplatz als UTF-8, und die Codierung/Decodierung ist langsamer. Daher sollten Sie UTF-8 anstelle von UTF-7 verwenden, wenn möglich.
UTF-8 Stellt jeden Unicode-Codepunkt als Sequenz von 1 bis vier Bytes dar. UTF-8 unterstützt 8-Bit-Datengrößen und eignet sich gut für viele vorhandene Betriebssysteme. Für den ASCII-Zeichenbereich ist UTF-8 mit ASCII-Codierung identisch und ermöglicht eine breitere Anzahl von Zeichen. Für Chinesisch-Japanese-Korean-Skripts (CJK) kann UTF-8 jedoch drei Byte für jedes Zeichen erfordern und eine größere Datengröße als UTF-16 verursachen. Manchmal rechtfertigt die Menge an ASCII-Daten, wie HTML-Tags, die erhöhte Größe für den CJK-Bereich.
UTF-16 Stellt jeden Unicode-Codepunkt als Sequenz von einer oder zwei 16-Bit-Ganzzahlen dar. Die häufigsten Unicode-Zeichen erfordern nur einen UTF-16-Codepunkt, obwohl Unicode-Zusatzzeichen (U+10000 und höher) zwei UTF-16-Ersatzcodepunkte erfordern. Sowohl Little-Endian- als auch Big-Endian-Bytereihenfolgen werden unterstützt. UTF-16-Codierung wird von der Common Language Runtime verwendet, um Char- und String-Werte darzustellen, und vom Windows-Betriebssystem, um WCHAR-Werte darzustellen.
UTF-32 Stellt jeden Unicode-Codepunkt als 32-Bit-Ganzzahl dar. Sowohl Little-Endian- als auch Big-Endian-Bytereihenfolgen werden unterstützt. UTF-32-Codierung wird verwendet, wenn Anwendungen das Surrogate-Codepunktverhalten der UTF-16-Codierung auf Betriebssystemen vermeiden möchten, für die codierter Speicherplatz zu wichtig ist. Einzelne Glyphen, die auf einer Anzeige gerendert werden, können weiterhin mit mehr als einem UTF-32-Zeichen codiert werden.
ANSI/ISO-Codierung Bietet Unterstützung für eine Vielzahl von Codeseiten. Unter Windows-Betriebssystemen werden Codeseiten verwendet, um eine bestimmte Sprache oder Gruppe von Sprachen zu unterstützen. Eine Tabelle, in der die von .NET unterstützten Codeseiten aufgelistet sind, finden Sie in der Encoding Klasse. Sie können ein Codierungsobjekt für eine bestimmte Codeseite abrufen, indem Sie die Encoding.GetEncoding(Int32) Methode aufrufen. Eine Codeseite enthält 256 Codepunkte und ist nullbasiert. In den meisten Codeseiten stellen Codepunkte 0 bis 127 den ASCII-Zeichensatz dar, und Codepunkte 128 bis 255 unterscheiden sich erheblich zwischen Codeseiten. Beispielsweise stellt die Codepage 1252 die Zeichen für lateinische Schreibsysteme bereit, einschließlich Englisch, Deutsch und Französisch. Die letzten 128 Codepunkte auf der Codeseite 1252 enthalten die Akzentzeichen. Codepage 1253 stellt Zeichencodes bereit, die im griechischen Schreibsystem erforderlich sind. Die letzten 128 Codepunkte auf der Codeseite 1253 enthalten die griechischen Zeichen. Daher kann eine Anwendung, die sich auf ANSI-Codeseiten stützt, Griechisch und Deutsch im selben Textstream speichern, es sei denn, sie enthält einen Bezeichner, der die referenzierte Codeseite angibt.
DbCS-Codierungen (Double-Byte Character Set) Unterstützt Sprachen wie Chinesisch, Japanisch und Koreanisch, die mehr als 256 Zeichen enthalten. In einem DBCS stellt ein Paar von Codepunkten (ein Doppelbyte) jedes Zeichen dar. Die Encoding.IsSingleByte Eigenschaft gibt false für DBCS-Codierungen zurück. Sie können ein Codierungsobjekt für einen bestimmten DBCS abrufen, indem Sie die Encoding.GetEncoding(Int32) Methode aufrufen. Wenn eine Anwendung DBCS-Daten verarbeitet, wird das erste Byte eines DBCS-Zeichens (das Leadbyte) in Kombination mit dem Trail-Byte verarbeitet, das unmittelbar darauf folgt. Da ein einzelnes Paar von Double-Byte-Codepunkten je nach Codepage unterschiedliche Zeichen darstellen kann, lässt dieses Schema die Kombination zweier Sprachen, z. B. Japanisch und Chinesisch, im gleichen Datenstrom immer noch nicht zu.

Mit diesen Codierungen können Sie sowohl mit Unicode-Zeichen als auch mit Codierungen arbeiten, die am häufigsten in älteren Anwendungen verwendet werden. Darüber hinaus können Sie eine benutzerdefinierte Codierung erstellen, indem Sie eine Klasse definieren, die von Encoding abgeleitet wird und deren Mitglieder überschreibt.

.NET Core-Codierungsunterstützung

Standardmäßig stellt .NET Core keine codeseitigen Codierungen außer Codepage 28591 und den Unicode-Codierungen wie UTF-8 und UTF-16 zur Verfügung. Sie können jedoch die Codepage-Codierungen von Standard-Windows-Apps, die auf .NET abzielen, zu Ihrer App hinzufügen. Weitere Informationen finden Sie im Thema CodePagesEncodingProvider.

Auswählen einer Codierungsklasse

Wenn Sie die Möglichkeit haben, die Codierung auszuwählen, die von Ihrer Anwendung verwendet werden soll, sollten Sie eine Unicode-Codierung verwenden, vorzugsweise entweder UTF8Encoding oder UnicodeEncoding. (.NET unterstützt auch eine dritte Unicode-Codierung. UTF32Encoding)

Wenn Sie eine ASCII-Codierung (ASCIIEncoding) verwenden möchten, wählen Sie UTF8Encoding stattdessen aus. Die beiden Codierungen sind für den ASCII-Zeichensatz identisch, haben jedoch UTF8Encoding die folgenden Vorteile:

  • Es kann jedes Unicode-Zeichen darstellen, während ASCIIEncoding nur die Unicode-Zeichenwerte zwischen U+0000 und U+007F unterstützt werden.

  • Es bietet Fehlererkennung und bessere Sicherheit.

  • Es wurde darauf optimiert, so schnell wie möglich zu sein und sollte schneller sein als jede andere Kodierung. Auch bei Inhalten, die vollständig ASCII sind, werden Vorgänge, die mit UTF8Encoding durchgeführt werden, schneller ausgeführt als Vorgänge, die mit ASCIIEncoding durchgeführt werden.

Sie sollten die Verwendung ASCIIEncoding nur für Ältere Anwendungen in Betracht ziehen. Selbst bei älteren Anwendungen UTF8Encoding kann es jedoch aus folgenden Gründen eine bessere Wahl sein (unter Der Annahme von Standardeinstellungen):

  • Wenn Ihre Anwendung Inhalte enthält, die nicht streng ASCII sind und sie mit ASCIIEncodingcodiert, codiert jedes Nicht-ASCII-Zeichen als Fragezeichen (?). Wenn die Anwendung diese Daten dann decodiert, gehen die Informationen verloren.

  • Wenn Ihre Anwendung Inhalte enthält, die nicht streng ASCII sind und sie mit UTF8Encoding codiert, scheint das Ergebnis unverständlich zu sein, wenn es als ASCII interpretiert wird. Wenn die Anwendung dann jedoch einen UTF-8-Decoder zum Decodieren dieser Daten verwendet, führt die Daten erfolgreich einen Roundtrip durch.

In einer Webanwendung sollten Zeichen, die als Reaktion auf eine Webanforderung an den Client gesendet werden, die Codierung widerspiegeln, die auf dem Client verwendet wird. In den meisten Fällen sollten Sie die HttpResponse.ContentEncoding Eigenschaft auf den von der HttpRequest.ContentEncoding Eigenschaft zurückgegebenen Wert festlegen, um Text in der Codierung anzuzeigen, die der Benutzer erwartet.

Verwenden eines Encoding-Objekts

Ein Encoder konvertiert eine Zeichenfolge von Zeichen (am häufigsten Unicode-Zeichen) in seine numerische (Byte)-Entsprechung. Sie können z. B. einen ASCII-Encoder verwenden, um Unicode-Zeichen in ASCII zu konvertieren, damit sie auf der Konsole angezeigt werden können. Zum Ausführen der Konvertierung rufen Sie die Encoding.GetBytes Methode auf. Wenn Sie ermitteln möchten, wie viele Bytes zum Speichern der codierten Zeichen erforderlich sind, bevor Sie die Codierung ausführen, können Sie die GetByteCount Methode aufrufen.

Im folgenden Beispiel wird ein einzelnes Bytearray verwendet, um Zeichenfolgen in zwei separaten Vorgängen zu codieren. Es verwaltet einen Index, der die Startposition im Bytearray für den nächsten Satz von ASCII-codierten Bytes angibt. Sie ruft die ASCIIEncoding.GetByteCount(String) Methode auf, um sicherzustellen, dass das Bytearray groß genug ist, um die codierte Zeichenfolge aufzunehmen. Anschließend wird die ASCIIEncoding.GetBytes(String, Int32, Int32, Byte[], Int32) Methode aufgerufen, um die Zeichen in der Zeichenfolge zu codieren.

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($"   {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($"{ShowByteValues(bytes, index)}");
      Console.WriteLine();

      // Decode Unicode byte array to a string.
      string newString = asciiEncoding.GetString(bytes, 0, index);
      Console.WriteLine($"Decoded: {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.

Ein Decoder konvertiert ein Byte-Array, das eine bestimmte Zeichencodierung in eine Reihe von Zeichen widerspiegelt, entweder in einem Zeichenarray oder in einer Zeichenfolge. Um ein Bytearray in ein Zeichenarray zu decodieren, rufen Sie die Encoding.GetChars Methode auf. Um ein Bytearray in eine Zeichenfolge zu decodieren, rufen Sie die GetString Methode auf. Wenn Sie ermitteln möchten, wie viele Zeichen zum Speichern der decodierten Bytes erforderlich sind, bevor Sie die Decodierung ausführen, können Sie die GetCharCount Methode aufrufen.

Im folgenden Beispiel werden drei Zeichenfolgen codiert und dann in ein einzelnes Array von Zeichen decodiert. Es verwaltet einen Index, der die Startposition im Zeichenarray für den nächsten Satz decodierter Zeichen angibt. Sie ruft die GetCharCount Methode auf, um sicherzustellen, dass das Zeichenarray groß genug ist, um alle decodierten Zeichen aufzunehmen. Anschließend wird die ASCIIEncoding.GetChars(Byte[], Int32, Int32, Char[], Int32) Methode aufgerufen, um das Bytearray zu decodieren.

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

Die von einer Klasse abgeleiteten Encoding Codierungs- und Decodierungsmethoden sind so konzipiert, dass sie an einem vollständigen Satz von Daten arbeiten. Das heißt, alle zu codierenden oder decodierten Daten werden in einem einzigen Methodenaufruf bereitgestellt. In einigen Fällen sind daten jedoch in einem Datenstrom verfügbar, und die zu codierenden oder decodierten Daten sind möglicherweise nur aus separaten Lesevorgängen verfügbar. Dies erfordert vom Codierungs- oder Decodierungsvorgang, sich den gespeicherten Zustand aus dem vorherigen Aufruf zu merken. Methoden von Klassen, die von Encoder und Decoder abgeleitet sind, können Codierungs- und Decodierungsvorgänge durchführen, die mehrere Methodenaufrufe umfassen.

Ein Encoder Objekt für eine bestimmte Codierung ist über die Eigenschaft dieser Codierung Encoding.GetEncoder() verfügbar. Ein Decoder Objekt für eine bestimmte Codierung ist über die Eigenschaft dieser Codierung Encoding.GetDecoder() verfügbar. Beachten Sie bei Decodierungsvorgängen, dass Klassen, die von Decoder abgeleitet sind, eine Decoder.GetChars-Methode enthalten, aber keine Methode, die Encoding.GetString entspricht.

Im folgenden Beispiel wird der Unterschied zwischen der Verwendung der Encoding.GetString- und Decoder.GetChars-Methoden zum Decodieren eines Unicode-Bytearrays veranschaulicht. Im Beispiel wird eine Zeichenfolge, die einige Unicode-Zeichen enthält, in eine Datei codiert. Anschließend werden die beiden Decodierungsmethoden verwendet, um sie jeweils zehn Bytes zu decodieren. Da ein Ersatzpaar in den zehnten und elften Bytes auftritt, wird es in separaten Methodenaufrufen decodiert. Wie die Ausgabe zeigt, kann die Methode die Encoding.GetString Bytes nicht richtig decodieren und ersetzt sie stattdessen durch U+FFFD (REPLACEMENT CHARACTER). Andererseits kann die Decoder.GetChars Methode das Bytearray erfolgreich decodieren, um die ursprüngliche Zeichenfolge abzurufen.

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

Auswählen einer Fallback-Strategie

Wenn eine Methode versucht, ein Zeichen zu codieren oder zu decodieren, aber keine Zuordnung vorhanden ist, muss eine Fallbackstrategie implementiert werden, die bestimmt, wie die fehlgeschlagene Zuordnung behandelt werden soll. Es gibt drei Arten von Fallbackstrategien:

  • Am besten geeigneter Fallback

  • Ersatz-Notlösung

  • Ausnahme-Rückfalloption

Von Bedeutung

Die häufigsten Probleme bei Codierungsvorgängen treten auf, wenn ein Unicode-Zeichen nicht einer bestimmten Codeseitencodierung zugeordnet werden kann. Die häufigsten Probleme bei Decodierungsvorgängen treten auf, wenn ungültige Bytesequenzen nicht in gültige Unicode-Zeichen übersetzt werden können. Aus diesen Gründen sollten Sie wissen, welche Fallbackstrategie ein bestimmtes Codierungsobjekt verwendet. Wenn möglich, sollten Sie die Fallbackstrategie angeben, die von einem Codierungsobjekt verwendet wird, wenn Sie das Objekt instanziieren.

Best-Fit Fallback

Wenn ein Zeichen keine genaue Übereinstimmung in der Zielcodierung hat, kann der Encoder versuchen, es einem ähnlichen Zeichen zuzuordnen. Der am besten geeignete Fallback ist meist ein Codierungs- statt eines Decodierungsproblems. Es gibt nur wenige Zeichensätze, die Zeichen enthalten, die nicht erfolgreich Unicode zugeordnet werden können. Der beste Fallback ist die Standardeinstellung für Codepage- und Double-Byte-Zeichensatzcodierungen, die von den Encoding.GetEncoding(Int32) und Encoding.GetEncoding(String) Überladungen abgerufen werden.

Hinweis

Theoretisch unterstützen die in .NET (UTF8Encoding, UnicodeEncodingund UTF32Encoding) bereitgestellten Unicode-Codierungsklassen jedes Zeichen in jedem Zeichensatz, sodass sie verwendet werden können, um Fallbackprobleme am besten zu beseitigen.

Am besten geeignete Strategien variieren für unterschiedliche Codeseiten. Bei einigen Codeseiten werden lateinische Zeichen mit voller Breite z. B. den gängigeren lateinischen Zeichen halber Breite zugeordnet. Für andere Codeseiten wird diese Zuordnung nicht erstellt. Selbst bei einer aggressiven optimalen Strategie gibt es in einigen Codierungen für manche Zeichen keine denkbare Zuordnung. Beispielsweise hat ein chinesischer Ideograph keine vernünftige Zuordnung zu Codepage 1252. In diesem Fall wird eine Ersetzungszeichenfolge verwendet. Diese Zeichenfolge ist standardmäßig nur ein einzelnes FRAGEZEICHEN (U+003F).

Hinweis

Best-Fit-Strategien sind nicht detailliert dokumentiert. Mehrere Codeseiten sind jedoch auf der Website des Unicode Consortiums dokumentiert. Bitte lesen Sie die readme.txt Datei in diesem Ordner, um eine Beschreibung der Interpretation der Zuordnungsdateien zu finden.

Im folgenden Beispiel wird die Codepage 1252 (die Windows-Codeseite für westeuropäische Sprachen) verwendet, um eine beste Anpassung und deren Nachteile darzustellen. Die Encoding.GetEncoding(Int32) Methode wird verwendet, um ein Codierungsobjekt für Codepage 1252 abzurufen. Standardmäßig wird ein Best-Fit-Mapping für nicht unterstützte Unicode-Zeichen verwendet. Im Beispiel wird eine Zeichenfolge instanziiert, die drei Nicht-ASCII-Zeichen enthält - CIRCLED LATIN CAPITAL LETTER S (U+24C8), SUPERSCRIPT FIVE (U+2075) und INFINITY (U+221E) durch Leerzeichen getrennt. Wie die Ausgabe aus dem Beispiel zeigt, werden, wenn der String codiert wird, die drei ursprünglichen Nicht-Leerzeichen durch FRAGEZEICHEN (U+003F), ZIFFER FÜNF (U+0035) und ZIFFER ACHT (U+0038) ersetzt. DIGIT EIGHT ist ein besonders schlechter Ersatz für das nicht unterstützte INFINITY-Zeichen, und FRAGEZEICHEN weist darauf hin, dass keine Zuordnung für das ursprüngliche Zeichen verfügbar war.

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

Die optimale Zuordnung ist das Standardverhalten für ein Encoding Objekt, das Unicode-Daten in Codeseitendaten codiert, und es gibt Legacyanwendungen, die auf diesem Verhalten basieren. Neue Anwendungen sollten jedoch aus Sicherheitsgründen das Best-Fit-Verhalten vermeiden. Anwendungen sollten beispielsweise keinen Domänennamen durch eine bestmögliche Codierung durchlaufen lassen.

Hinweis

Sie können auch eine benutzerdefinierte Best-Fit-Fallbackabbildung für eine Codierung implementieren. Weitere Informationen finden Sie im Abschnitt "Implementieren einer benutzerdefinierten Fallbackstrategie ".

Wenn für ein Codierungsobjekt die beste Übereinstimmung als Standardfallback festgelegt ist, können Sie beim Abrufen eines Encoding-Objekts eine andere Fallbackstrategie auswählen, indem Sie das Encoding.GetEncoding(Int32, EncoderFallback, DecoderFallback)-Objekt aufrufen oder Encoding.GetEncoding(String, EncoderFallback, DecoderFallback) überladen. Der folgende Abschnitt enthält ein Beispiel, das jedes Zeichen ersetzt, das nicht der Codepage 1252 durch ein Sternchen (*) zugeordnet werden kann.

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

Ersatzfallback

Wenn ein Zeichen keine genaue Übereinstimmung im Zielschema hat, es aber kein geeignetes Zeichen gibt, dem es zugeordnet werden kann, kann die Anwendung ein Ersetzungszeichen oder eine Zeichenfolge angeben. Dies ist das Standardverhalten für den Unicode-Decoder, der eine beliebige Zwei-Byte-Sequenz ersetzt, die nicht mit REPLACEMENT_CHARACTER (U+FFFD) decodiert werden kann. Es ist auch das Standardverhalten der ASCIIEncoding Klasse, das jedes Zeichen ersetzt, das nicht durch ein Fragezeichen codiert oder decodiert werden kann. Im folgenden Beispiel wird die Zeichenersetzung für die Unicode-Zeichenfolge aus dem vorherigen Beispiel veranschaulicht. Wie die Ausgabe zeigt, wird jedes Zeichen, das nicht in einen ASCII-Bytewert decodiert werden kann, durch 0x3F ersetzt, bei dem es sich um den ASCII-Code für ein Fragezeichen handelt.

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: {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 enthält die EncoderReplacementFallback und DecoderReplacementFallback Klassen, die eine Ersetzungszeichenfolge bereitstellen, wenn ein Zeichen nicht exakt in einem Codierungs- oder Decodierungsvorgang zugeordnet werden kann. Standardmäßig ist diese Ersetzungszeichenfolge ein Fragezeichen, Sie können jedoch eine Klassenkonstruktorüberladung aufrufen, um eine andere Zeichenfolge auszuwählen. In der Regel ist die Ersetzungszeichenfolge ein einzelnes Zeichen, obwohl dies keine Anforderung ist. Im folgenden Beispiel wird das Verhalten des Codepage 1252-Encoders geändert, indem ein Objekt instanziiert wird, das ein EncoderReplacementFallback Sternchen (*) als Ersetzungszeichenfolge verwendet.

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

Hinweis

Sie können auch eine Ersatzklasse für eine Codierung implementieren. Weitere Informationen finden Sie im Abschnitt "Implementieren einer benutzerdefinierten Fallbackstrategie ".

Zusätzlich zu FRAGEZEICHEN (U+003F) wird das Unicode REPLACEMENT CHARACTER (U+FFFD) häufig als Ersetzungszeichenfolge verwendet, insbesondere beim Decodieren von Bytesequenzen, die nicht erfolgreich in Unicode-Zeichen übersetzt werden können. Sie können jedoch eine beliebige Ersetzungszeichenfolge auswählen, und sie kann mehrere Zeichen enthalten.

Ausnahmefallback

Anstatt einen optimal geeigneten Fallback oder eine Ersetzungszeichenfolge bereitzustellen, kann ein Encoder einen EncoderFallbackException Auslösen, wenn er eine Reihe von Zeichen nicht codieren kann, und ein Decoder kann einen DecoderFallbackException Fehler auslösen, wenn er kein Bytearray decodieren kann. Um eine Ausnahme bei Codierungs- und Decodierungsvorgängen auszuwerfen, geben Sie ein EncoderExceptionFallback Objekt bzw. ein DecoderExceptionFallback Objekt an die Encoding.GetEncoding(String, EncoderFallback, DecoderFallback) Methode an. Im folgenden Beispiel wird ein Ausnahmefallback mit der ASCIIEncoding Klasse veranschaulicht.

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{Convert.ToUInt16(e.CharUnknownHigh):X4} 0x{Convert.ToUInt16(e.CharUnknownLow):X3} at index {e.Index}.");
         else
            Console.WriteLine($"Unable to encode 0x{Convert.ToUInt16(e.CharUnknown):X4} at index {e.Index}.");
         return;
      }
      Console.WriteLine();

      // Decode the ASCII bytes.
      try {
         string str2 = enc.GetString(bytes);
         Console.WriteLine($"Round-trip: {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 {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.

Hinweis

Sie können auch einen benutzerdefinierten Ausnahmehandler für einen Codierungsvorgang implementieren. Weitere Informationen finden Sie im Abschnitt "Implementieren einer benutzerdefinierten Fallbackstrategie ".

Die EncoderFallbackException und DecoderFallbackException die Objekte enthalten die folgenden Informationen zu der Bedingung, die die Ausnahme verursacht hat:

Obwohl die Objekte EncoderFallbackException und DecoderFallbackException ausreichende Diagnoseinformationen über die Ausnahme bereitstellen, ermöglichen sie keinen Zugriff auf den Kodierungs- oder Dekodierungspuffer. Daher dürfen ungültige Daten nicht innerhalb der Codierungs- oder Decodierungsmethode ersetzt oder korrigiert werden.

Implementieren einer benutzerdefinierten Fallbackstrategie

Neben der am besten geeigneten Zuordnung, die intern von Codeseiten implementiert wird, enthält .NET die folgenden Klassen für die Implementierung einer Fallbackstrategie:

Darüber hinaus können Sie eine benutzerdefinierte Lösung implementieren, die bestmöglichen Fallback, Ersetzungs-Fallback oder Ausnahme-Fallback verwendet, indem Sie die folgenden Schritte ausführen:

  1. Leiten Sie eine Klasse von EncoderFallback für Codierungsvorgänge ab und von DecoderFallback für Dekodierungsvorgänge.

  2. Leiten Sie eine Klasse von EncoderFallbackBuffer für Codierungsvorgänge ab und von DecoderFallbackBuffer für Dekodierungsvorgänge.

  3. Wenn die vordefinierten EncoderFallbackException und DecoderFallbackException Klassen Ihre Anforderungen nicht erfüllen, leiten Sie eine Klasse von einem Ausnahmeobjekt ab, wie zum Beispiel Exception oder ArgumentException.

Ableiten von EncoderFallback oder DecoderFallback

Um eine benutzerdefinierte Fallbacklösung zu implementieren, müssen Sie eine Klasse erstellen, die von EncoderFallback für Codierungsvorgänge erbt und von DecoderFallback für Decodierungsvorgänge. Instanzen dieser Klassen werden an die Encoding.GetEncoding(String, EncoderFallback, DecoderFallback) Methode übergeben und dienen als Vermittler zwischen der Codierungsklasse und der Fallbackimplementierung.

Wenn Sie eine benutzerdefinierte Fallbacklösung für einen Encoder oder Decoder erstellen, müssen Sie die folgenden Member implementieren:

Ableiten von EncoderFallbackBuffer oder DecoderFallbackBuffer

Um eine benutzerdefinierte Fallbacklösung zu implementieren, müssen Sie auch eine Klasse erstellen, die von EncoderFallbackBuffer für Codierungsvorgänge erbt und von DecoderFallbackBuffer für Decodierungsvorgänge. Instanzen dieser Klassen werden von der CreateFallbackBuffer Methode der EncoderFallback Klassen und DecoderFallback Klassen zurückgegeben. Die EncoderFallback.CreateFallbackBuffer Methode wird vom Encoder aufgerufen, wenn es auf das erste Zeichen trifft, das nicht codiert werden kann, und die DecoderFallback.CreateFallbackBuffer Methode wird vom Decoder aufgerufen, wenn eine oder mehrere Bytes auftreten, die nicht decodiert werden können. Die EncoderFallbackBuffer Und DecoderFallbackBuffer Klassen stellen die Fallbackimplementierung bereit. Jede Instanz stellt einen Puffer dar, der die Fallbackzeichen enthält, die das Zeichen ersetzen, das nicht codiert werden kann, oder die Bytesequenz, die nicht decodiert werden kann.

Wenn Sie eine benutzerdefinierte Fallbacklösung für einen Encoder oder Decoder erstellen, müssen Sie die folgenden Member implementieren:

  • Die EncoderFallbackBuffer.Fallback oder DecoderFallbackBuffer.Fallback Methode. EncoderFallbackBuffer.Fallback wird vom Encoder aufgerufen, um den Fallbackpuffer mit Informationen zum Zeichen bereitzustellen, das nicht codiert werden kann. Da es sich bei dem zu codierenden Zeichen um ein Ersatzpaar handelt, wird diese Methode überladen. Eine Überladung wird übergeben, um das Zeichen zu codieren und dessen Index in der Zeichenfolge zu bestimmen. Die zweite Überladung wird zusammen mit dem Index in der Zeichenfolge an den hohen und niedrigen Ersatz übergeben. Die DecoderFallbackBuffer.Fallback Methode wird vom Decoder aufgerufen, um den Fallbackpuffer mit Informationen zu den Bytes bereitzustellen, die nicht decodiert werden können. Dieser Methode wird ein Byte-Array übergeben, das nicht decodiert werden kann, zusammen mit dem Index des ersten Bytes. Die Fallbackmethode sollte true zurückgeben, falls der Fallbackpuffer ein passendes oder ein Ersatzzeichen bereitstellen kann; andernfalls sollte sie false zurückgeben. Bei einem Ausnahmefallback sollte die Fallbackmethode eine Ausnahme auslösen.

  • Die EncoderFallbackBuffer.GetNextChar Methode DecoderFallbackBuffer.GetNextChar, die vom Encoder oder Decoder wiederholt aufgerufen wird, um das nächste Zeichen aus dem Fallbackpuffer zu erhalten. Wenn alle Fallbackzeichen zurückgegeben wurden, sollte die Methode U+0000 zurückgeben.

  • Die Eigenschaft EncoderFallbackBuffer.Remaining oder DecoderFallbackBuffer.Remaining, die die Anzahl der im Fallbackpuffer verbleibenden Zeichen zurückgibt.

  • Die EncoderFallbackBuffer.MovePrevious-Methode oder die DecoderFallbackBuffer.MovePrevious-Methode, die die aktuelle Position im Fallback-Puffer auf das vorherige Zeichen verschiebt.

  • Die EncoderFallbackBuffer.Reset Oder DecoderFallbackBuffer.Reset Methode, die den Fallbackpuffer neu initialisiert.

Wenn die Fallback-Implementierung ein Best-Fit-Fallback oder ein Ersatz-Fallback ist, verwalten die von EncoderFallbackBuffer und DecoderFallbackBuffer abgeleiteten Klassen auch zwei private Instanzfelder: die genaue Anzahl der Zeichen im Puffer und den Index des nächsten Zeichens im Puffer, das zurückgegeben werden soll.

Ein EncoderFallback-Beispiel

In einem früheren Beispiel wurde ein Ersatzfallback verwendet, um Unicode-Zeichen zu ersetzen, die nicht ASCII-Zeichen mit einem Sternchen (*) entsprechen. Im folgenden Beispiel wird stattdessen eine benutzerdefinierte, optimale Fallback-Implementierung verwendet, um eine bessere Zuordnung von Nicht-ASCII-Zeichen zu gewährleisten.

Der folgende Code definiert eine Klasse namens CustomMapper, die von EncoderFallback abgeleitet ist, um die Best-Fit-Zuordnung von Nicht-ASCII-Zeichen zu behandeln. Die CreateFallbackBuffer Methode gibt ein CustomMapperFallbackBuffer Objekt zurück, das die EncoderFallbackBuffer Implementierung bereitstellt. Die CustomMapper Klasse verwendet ein Dictionary<TKey,TValue> Objekt, um die Zuordnungen von nicht unterstützten Unicode-Zeichen (dem Schlüsselwert) und den entsprechenden 8-Bit-Zeichen (die in zwei aufeinander folgenden Bytes in einer 64-Bit-Ganzzahl gespeichert werden) zu speichern. Um diese Zuordnung dem Fallbackpuffer zur Verfügung zu stellen, wird die CustomMapper Instanz als Parameter an den CustomMapperFallbackBuffer Klassenkonstruktor übergeben. Da die längste Zuordnung die Zeichenfolge "INF" für das Unicode-Zeichen U+221E ist, gibt die MaxCharCount Eigenschaft 3 zurück.

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

Der folgende Code definiert die Klasse CustomMapperFallbackBuffer, die von EncoderFallbackBuffer abgeleitet ist. Das Wörterbuch, das am besten geeignete Zuordnungen enthält und in der CustomMapper Instanz definiert ist, ist über den Klassenkonstruktor verfügbar. Die Fallback Methode gibt true zurück, wenn eines der Unicode-Zeichen, die der ASCII-Encoder nicht codieren kann, im Zuordnungswörterbuch definiert wird. Andernfalls gibt sie false zurück. Für jeden Fallback gibt die private count Variable die Anzahl der Zeichen an, die zurückgegeben werden sollen, und die private index Variable gibt die Position im Zeichenfolgenpuffer des charsToReturnnächsten zurückzugebenden Zeichens an.

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

Der folgende Code instanziiert dann das CustomMapper Objekt und übergibt eine Instanz an die Encoding.GetEncoding(String, EncoderFallback, DecoderFallback) Methode. Die Ausgabe gibt an, dass die am besten geeignete Fallbackimplementierung die drei Nicht-ASCII-Zeichen in der ursprünglichen Zeichenfolge erfolgreich verarbeitet.

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

Siehe auch