Not
Bu sayfaya erişim yetkilendirme gerektiriyor. Oturum açmayı veya dizinleri değiştirmeyi deneyebilirsiniz.
Bu sayfaya erişim yetkilendirme gerektiriyor. Dizinleri değiştirmeyi deneyebilirsiniz.
Bu makalede, .NET'in çeşitli kodlama düzenlerini kullanarak metin kodlama ve kod çözme için sağladığı sınıfların nasıl kullanılacağı açıklanmaktadır. Yönergeler, .NET'te Karakter Kodlamaya Giriş başlıklı bölümü okuduğunuz varsayımıyla hazırlanmıştır.
Kodlayıcılar ve kod çözücüler
.NET, çeşitli kodlama sistemlerini kullanarak metin kodlayan ve kodunu çözen kodlama sınıfları sağlar. Örneğin, UTF8Encoding sınıfı UTF-8'e kodlama ve ondan kod çözme kurallarını açıklar. .NET, #D1 örnekleri için UTF-16 kodlamasını (#D0 sınıfıyla temsil edilir) kullanır. Kodlayıcılar ve kod çözücüler diğer kodlama düzenleri için kullanılabilir.
Kodlama ve kod çözme de doğrulama içerebilir. Örneğin, #D0 sınıfı geçerli vekil çiftlerde olduklarından emin olmak için vekil aralıktaki tüm #D1 örneklerini denetler. Geri dönüş stratejisi, kodlayıcının geçersiz karakterleri nasıl işlediğini veya kod çözücülerin geçersiz baytları nasıl işlediğini belirler.
Uyarı
.NET kodlama sınıfları, karakter verilerini depolamak ve dönüştürmek için bir yol sağlar. İkili verileri dize biçiminde depolamak için kullanılmamalıdır. Kullanılan kodlamaya bağlı olarak, kodlama sınıfları ile ikili verileri dize biçimine dönüştürmek beklenmeyen davranışlara neden olabilir ve yanlış veya bozuk veriler üretebilir. İkili verileri dize formuna dönüştürmek için #D0 yöntemini kullanın.
.NET'teki tüm karakter kodlama sınıfları, tüm karakter kodlamalarında ortak olan işlevselliği tanımlayan soyut bir sınıf olan #D0 sınıfından devralır. .NET'te uygulanan tek tek kodlama nesnelerine erişmek için aşağıdakileri yapın:
.NET'te kullanılabilen standart karakter kodlamalarını (ASCII, UTF-7, UTF-8, UTF-16 ve UTF-32) temsil eden nesneleri döndüren #D0 sınıfının statik özelliklerini kullanın. Örneğin, #D0 özelliği bir #D1 nesnesi döndürür. Her nesne, kodlayamayacağı dizeleri ve kodunu çözemediği baytları işlemek için yedek geri dönüş kullanır. Daha fazla bilgi için bkz. Değiştirme yedekleme.
Kodlamanın sınıf oluşturucusunu çağırın. ASCII, UTF-7, UTF-8, UTF-16 ve UTF-32 kodlamaları için nesneler bu şekilde örneklenebilir. Varsayılan olarak, her nesne kodlayamayacağı dizeleri ve kodunu çözemediği baytları işlemek için yedek geri dönüş kullanır, ancak bunun yerine bir özel durumun atılması gerektiğini belirtebilirsiniz. Daha fazla bilgi için, Değiştirme geri dönüşü ve Özel durum geri dönüşü bölümlerine bakın.
Encoding(Int32) oluşturucuyu çağırın ve kodlamayı temsil eden bir tamsayı geçirerek bunu yapın. Standart kodlama nesneleri yedek geri dönüş kullanır ve kod sayfası ve çift bayt karakter kümesi (DBCS) kodlama nesneleri, kodlayamayacağı dizeleri ve kodunu çözemedikleri baytları işlemek için en uygun geri dönüşü kullanır. Daha fazla bilgi için bkz. En Uygun Yedekleme.
Encoding.GetEncoding yöntemini çağırın, bu yöntem .NET'te mevcut olan herhangi bir standart, code page veya DBCS kodlamasını döndürür. Aşırı yüklemeler hem kodlayıcı hem de kod çözücü için bir geri dönüş nesnesi belirtmenize olanak sağlar.
#D0 yöntemini çağırarak .NET'te kullanılabilen tüm kodlamalar hakkında bilgi alabilirsiniz. .NET, aşağıdaki tabloda listelenen karakter kodlama düzenlerini destekler.
| Kodlama sınıfı | Açıklama |
|---|---|
| ASCII | Sınırlı bir karakter aralığını, bir baytın daha düşük yedi bitini kullanarak kodlar. Bu kodlama yalnızca #D0 ile #B1 arasında karakter değerlerini desteklediğinden, çoğu durumda uluslararası uygulamalar için yetersizdir. |
| UTF-7 | Karakterleri 7 bit ASCII karakter dizileri olarak temsil eder. ASCII olmayan Unicode karakterler, ASCII karakterlerden oluşan bir kaçış dizisiyle temsil edilir. UTF-7, e-posta ve haber grubu gibi protokolleri destekler. Ancak UTF-7 özellikle güvenli veya sağlam değildir. Bazı durumlarda, bir biti değiştirmek utf-7 dizesinin tamamının yorumlanmasını kökten değiştirebilir. Diğer durumlarda, farklı UTF-7 dizeleri aynı metni kodlayabilir. ASCII olmayan karakterler içeren diziler için UTF-7, UTF-8'den daha fazla alan gerektirir ve kodlama/kod çözme daha yavaştır. Sonuç olarak, mümkünse UTF-7 yerine UTF-8 kullanmanız gerekir. |
| UTF-8 | Her Unicode kod noktasını bir ile dört baytlık bir dizi olarak temsil eder. UTF-8, 8 bit veri boyutlarını destekler ve birçok mevcut işletim sistemiyle iyi çalışır. ASCII karakter aralığı için UTF-8, ASCII kodlaması ile aynıdır ve daha geniş bir karakter kümesine izin verir. Ancak, ÇinceJapanese-Korean (CJK) betikleri için UTF-8 her karakter için üç bayt gerektirebilir ve UTF-16'dan daha büyük veri boyutlarına neden olabilir. Bazen HTML etiketleri gibi ASCII veri miktarı, CJK aralığının artan boyutunu haklı olarak belirler. |
| UTF-16 | Her Unicode kod noktasını bir veya iki 16 bit tamsayı dizisi olarak temsil eder. Unicode ek karakterleri (U+10000 ve üzeri) iki UTF-16 vekil kod noktası gerektirse de, en yaygın Unicode karakterleri yalnızca bir UTF-16 kod noktası gerektirir. Hem little-endian hem de big-endian bayt sıralamaları desteklenir. UTF-16 kodlaması ortak dil çalışma zamanı tarafından #D0 ve #D1 değerlerini temsil etmek için kullanılır ve Windows işletim sistemi tarafından #D2 değerleri temsil etmek için kullanılır. |
| UTF-32 | Her Unicode kod noktasını 32 bit tamsayı olarak temsil eder. Hem little-endian hem de big-endian bayt siparişleri desteklenir. UTF-32 kodlaması, uygulamalar kodlanmış alanın çok önemli olduğu işletim sistemlerinde UTF-16 kodlamasının vekil kod noktası davranışından kaçınmak istediğinde kullanılır. Bir ekranda işlenen tek glifler yine de birden fazla UTF-32 karakteriyle kodlanabilir. |
| ANSI/ISO kodlaması | Çeşitli kod sayfaları için destek sağlar. Windows işletim sistemlerinde kod sayfaları belirli bir dili veya dil grubunu desteklemek için kullanılır. .NET tarafından desteklenen kod sayfalarını listeleyen bir tablo için Encoding sınıfına bakın. #D0 yöntemini çağırarak belirli bir kod sayfası için kodlama nesnesi alabilirsiniz. Kod sayfası 256 kod noktası içerir ve sıfır tabanlıdır. Çoğu kod sayfasında 0 ile 127 arasındaki kod noktaları ASCII karakter kümesini temsil ve 128 ile 255 arasındaki kod noktaları kod sayfaları arasında önemli ölçüde farklılık gösterir. Örneğin, 1252 kod sayfası İngilizce, Almanca ve Fransızca dahil olmak üzere Latin yazma sistemlerinin karakterlerini sağlar. 1252 kod sayfasındaki son 128 kod noktası vurgu karakterlerini içerir. Kod sayfası 1253 Yunanca yazma sisteminde gerekli karakter kodları sağlar. Kod sayfası 1253'teki son 128 kod noktası Yunanca karakterleri içerir. Sonuç olarak, ANSI kod sayfalarını kullanan bir uygulama, başvurulan kod sayfasını belirten bir tanımlayıcı içermediği sürece Yunanca ve Almanca'yı aynı metin akışında depolayamaz. |
| Çift baytlık karakter kümesi (DBCS) kodlamaları | 256'dan fazla karakter içeren Çince, Japonca ve Korece gibi dilleri destekler. DBCS'de bir çift kod noktası (çift bayt) her karakteri temsil eder. #D0 özelliği DBCS kodlamaları için #D1 döndürür. #D0 yöntemini çağırarak belirli bir DBCS için bir kodlama nesnesi alabilirsiniz. Bir uygulama DBCS verilerini işlerken, bir DBCS karakterinin ilk baytı (ön bayt), hemen ardından gelen iz baytı ile birlikte işlenir. Tek çift baytlı kod noktası çifti kod sayfasına bağlı olarak farklı karakterleri temsil ettiğinden, bu düzen yine de aynı veri akışında Japonca ve Çince gibi iki dilin birleşimine izin vermez. |
Bu kodlamalar, Unicode karakterlerle ve eski uygulamalarda en yaygın olarak kullanılan kodlamalarla çalışmanızı sağlar. Ayrıca, Encoding türeten bir sınıf tanımlayıp üyelerini geçersiz kılarak özel bir kodlama oluşturabilirsiniz.
.NET Core kodlama desteği
Varsayılan olarak, .NET Core 28591 kod sayfası ve UTF-8 ve UTF-16 gibi Unicode kodlamaları dışındaki kod sayfası kodlamalarını kullanıma sunmaz. Ancak, .NET'i hedefleyen standart Windows uygulamalarında bulunan kod sayfası kodlamalarını uygulamanıza ekleyebilirsiniz. Daha fazla bilgi için CodePagesEncodingProvider konusuna bakın.
Kodlama Sınıfı Seçme
Uygulamanız tarafından kullanılacak kodlamayı seçme fırsatınız varsa, tercihen #D0 veya #B1 bir Unicode kodlaması kullanmalısınız. (.NET, UTF32Encoding adlı üçüncü bir Unicode kodlamasını da destekler.)
ASCII kodlaması ( #A0) kullanmayı planlıyorsanız bunun yerine #D1 seçin. İki kodlama ASCII karakter kümesi için aynıdır, ancak #D0 aşağıdaki avantajlara sahiptir:
Her Unicode karakterini temsil edebilir, fakat ASCIIEncoding yalnızca U+0000 ile U+007F arasındaki Unicode karakter değerlerini destekler.
Hata algılama ve daha iyi güvenlik sağlar.
Mümkün olduğunca hızlı olacak şekilde ayarlanmıştır ve diğer kodlamalardan daha hızlı olmalıdır. Tamamen ASCII olan içerik için bile, #D0 ile gerçekleştirilen işlemler #B1 ile gerçekleştirilen işlemlerden daha hızlıdır.
ASCIIEncoding yalnızca eski uygulamalar için kullanmayı düşünmelisiniz. Ancak, eski uygulamalar için bile #D0 aşağıdaki nedenlerle daha iyi bir seçim olabilir (varsayılan ayarları varsayarsak):
Uygulamanız kesinlikle ASCII olmayan içeriğe sahipse ve #B0 ile kodlarsa, ASCII olmayan her karakter soru işareti (?) olarak kodlanır. Uygulama daha sonra bu verilerin kodunu çözerse, bilgiler kaybolur.
Uygulamanız ASCII olmayan içeriği UTF8Encoding ile kodluyorsa, bu içerik ASCII olarak yorumlandığında anlaşılmaz görünebilir. Ancak uygulama daha sonra bu verilerin kodunu çözmek için UTF-8 kod çözücüsü kullanırsa, veriler başarıyla gidiş dönüş gerçekleştirir.
Bir web uygulamasında, bir web isteğine yanıt olarak istemciye gönderilen karakterler istemcide kullanılan kodlamayı yansıtmalıdır. Çoğu durumda, kullanıcının beklediği kodlamada metin görüntülemek için #D0 özelliğini #D1 özelliği tarafından döndürülen değere ayarlamanız gerekir.
Kodlama Nesnesi Kullanma
Kodlayıcı, bir karakter dizesini (en yaygın olarak Unicode karakterleri) sayısal (bayt) eşdeğerine dönüştürür. Örneğin, Unicode karakterleri konsolda görüntülenebilmeleri için ASCII'ye dönüştürmek için bir ASCII kodlayıcı kullanabilirsiniz. Dönüştürmeyi gerçekleştirmek için #D0 metodunu çağırırsınız. Kodlamayı gerçekleştirmeden önce kodlanmış karakterleri depolamak için kaç bayt gerektiğini belirlemek istiyorsanız, #D0 yöntemini çağırabilirsiniz.
Aşağıdaki örnek, dizeleri iki ayrı işlemde kodlamak için tek bir bayt dizisi kullanır. Sonraki ASCII ile kodlanmış bayt kümesi için bayt dizisindeki başlangıç konumunu gösteren bir dizin tutar. Bayt dizisinin kodlanmış dizeyi barındıracak kadar büyük olduğundan emin olmak için #D0 yöntemini çağırır. Ardından dizedeki karakterleri kodlamak için #D0 yöntemini çağırır.
using System;
using System.Text;
public class Example
{
public static void Main()
{
string[] strings= { "This is the first sentence. ",
"This is the second sentence. " };
Encoding asciiEncoding = Encoding.ASCII;
// Create array of adequate size.
byte[] bytes = new byte[49];
// Create index for current position of array.
int index = 0;
Console.WriteLine("Strings to encode:");
foreach (var stringValue in strings) {
Console.WriteLine($" {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.
Kod çözücü, belirli bir karakter kodlamayı yansıtan bayt dizisini, karakter dizisindeki veya dizedeki bir karakter kümesine dönüştürür. Bayt dizisinin kodunu karakter dizisine çözmek için #D0 yöntemini çağırırsınız. Bayt dizisini bir dizeye decode etmek için GetString yöntemini çağırırsınız. Kod çözme işlemini gerçekleştirmeden önce kodu çözülen baytları depolamak için kaç karakter gerektiğini belirlemek istiyorsanız, #D0 yöntemini çağırabilirsiniz.
Aşağıdaki örnek üç dizeyi kodlar ve sonra bunları tek bir karakter dizisi olarak çözer. Kodu çözülen bir sonraki karakter kümesi için karakter dizisindeki başlangıç konumunu gösteren bir dizin tutar. Karakter dizisinin kodu çözülen tüm karakterleri barındıracak kadar büyük olduğundan emin olmak için #D0 yöntemini çağırır. Ardından bayt dizisinin kodunu çözmek için #D0 yöntemini çağırır.
using System;
using System.Text;
public class Example
{
public static void Main()
{
string[] strings = { "This is the first sentence. ",
"This is the second sentence. ",
"This is the third sentence. " };
Encoding asciiEncoding = Encoding.ASCII;
// Array to hold encoded bytes.
byte[] bytes;
// Array to hold decoded characters.
char[] chars = new char[50];
// Create index for current position of character array.
int index = 0;
foreach (var stringValue in strings) {
Console.WriteLine($"String to Encode: {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.
#D0 türetilen bir sınıfın kodlama ve kod çözme yöntemleri, tam bir veri kümesi üzerinde çalışacak şekilde tasarlanmıştır; diğer bir ifadeyle kodlanacak veya kodu çözülecek tüm veriler tek bir yöntem çağrısında sağlanır. Ancak bazı durumlarda veriler bir akışta kullanılabilir ve kodlanacak veya çözülecek veriler yalnızca ayrı okuma işlemlerinden kullanılabilir. Bunun için kodlama veya kod çözme işleminin önceki çağrısından kaydedilmiş durumları anımsaması gerekir. #D0 ve #D1 türetilen sınıfların yöntemleri, birden çok yöntem çağrısına yayılan kodlama ve kod çözme işlemlerini işleyebilir.
Belirli bir kodlama için #D0 nesnesi, bu kodlamanın #D1 özelliğinden kullanılabilir. Belirli bir kodlama için #D0 nesnesi, bu kodlamanın #D1 özelliğinden kullanılabilir. Kod çözme işlemleri için, Decoder türetilen sınıfların bir Decoder.GetChars yöntemi içerdiğini, ancak Encoding.GetString ile karşılık gelen bir yöntemleri olmadığını unutmayın.
Aşağıdaki örnek, Unicode bayt dizisinin kodunu çözmek için #D0 ve #D1 yöntemlerini kullanma arasındaki farkı gösterir. Örnek, bir dosyaya bazı Unicode karakterleri içeren bir dizeyi kodlar ve sonra her seferinde on bayt kodunu çözmek için iki kod çözme yöntemini kullanır. Onuncu ve on birinci baytlarda surrojet çift oluştuğundan, ayrı yöntem çağrılarıyla çözülür. Çıktıda gösterildiği gibi, Encoding.GetString yöntemi baytların kodunu doğru şekilde çözemez ve bunun yerine U+FFFD (Değiştirme Karakteri) ile değiştirir. Öte yandan, Decoder.GetChars yöntemi bayt dizisini çözümleyerek özgün dizeyi başarıyla elde edebildi.
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
Geri Dönüş Stratejisi Seçme
Bir yöntem bir karakteri kodlamaya veya kodunu çözmeye çalıştığında ancak eşleme olmadığında, başarısız eşlemenin nasıl işleneceğini belirleyen bir geri dönüş stratejisi uygulamalıdır. Üç tür geri dönüş stratejisi vardır:
En uygun yedek çözüm
Yedek seçenek
İstisna yedeği
Önemli
Kodlama işlemlerinde en yaygın sorunlar, bir Unicode karakteri belirli bir kod sayfası kodlamasına eşlenemediğinde oluşur. Kod çözme işlemlerinde en yaygın sorunlar, geçersiz bayt dizileri geçerli Unicode karakterlerine çevrilemediğinde oluşur. Bu nedenlerden dolayı, belirli bir kodlama nesnesinin hangi geri dönüş stratejisini kullandığını bilmeniz gerekir. Mümkün olduğunda, bir kodlama nesnesinin örneğini oluştururken kullanılan geri dönüş stratejisini belirtmelisiniz.
Best-Fit Geri Dönüş
Bir karakterin hedef kodlamada tam eşleşmesi olmadığında kodlayıcı bunu benzer bir karakterle eşlemeyi deneyebilir. (En uygun geri dönüş, kod çözme sorunu yerine çoğunlukla bir kodlamadır. Unicode ile başarıyla eşlenemeyen karakterler içeren çok az kod sayfası vardır.) En uygun geri dönüş, kod sayfası ve #D0 ve #D1 aşırı yüklemeleri tarafından alınan çift baytlık karakter kümesi kodlamaları için varsayılan değerdir.
Uyarı
Teoride, .NET'te sağlanan Unicode kodlama sınıfları ( #A0 , #B1 ve #B2 ) her karakter kümesindeki her karakteri destekler, böylece en uygun geri dönüş sorunlarını ortadan kaldırmak için kullanılabilirler.
En uygun stratejiler farklı kod sayfaları için farklılık gösterir. Örneğin, bazı kod sayfalarında tam genişlikli Latin karakterler, daha yaygın olan yarım genişlikli Latin karakterlere eşlenir. Diğer kod sayfaları için bu eşleme yapılmaz. Agresif bir en iyi uyum stratejisi altında bile, bazı kodlamalardaki bazı karakterler için mümkün olan bir uyum yoktur. Örneğin, Çince bir ideografın 1252 kod sayfasıyla makul eşlemesi yoktur. Bu durumda, bir değiştirme dizesi kullanılır. Varsayılan olarak, bu dize yalnızca tek bir SORU İşaretİdir (U+003F).
Uyarı
En uygun stratejiler ayrıntılı olarak belgelenmez. Ancak, Unicode Konsorsiyumu'nun web sitesinde birkaç kod sayfası belgelenmiştir. Eşleme dosyalarının nasıl yorumlandığının açıklaması için lütfen bu klasördeki readme.txt dosyasını gözden geçirin.
Aşağıdaki örnek, en uygun eşlemeyi ve dezavantajlarını göstermek için 1252 kod sayfasını (Batı Avrupa dilleri için Windows kod sayfası) kullanır. Encoding.GetEncoding(Int32) yöntemi, kod sayfası 1252 için bir kodlama nesnesi elde etmek amacıyla kullanılır. Varsayılan olarak, desteklemediği Unicode karakterleri için en uygun eşlemeyi kullanır. Örnek, ASCII olmayan üç karakter içeren bir dizenin örneğini oluşturur: DAIRE IÇINE ALıNMıŞ LATIN BÜYÜK HARF S (U+24C8), ÜST SIMGE BEŞ (U+2075) ve SONSUZLUK (U+221E) - boşluklarla ayrılmış. Örnekteki çıktıda gösterildiği gibi, dize kodlandığında, üç orijinal boşluk olmayan karakterin yerini SORU İŞARETİ (U+003F), RAKAM BEŞ (U+0035) ve RAKAM SEKİZ (U+0038) alır. RAKAM SEKİZ, desteklenmeyen INFINITY karakteri için özellikle kötü bir değişimdir ve SORU İŞARETİ orijinal karakter için bir eşleme bulunmadığını gösterir.
using System;
using System.Text;
public class Example
{
public static void Main()
{
// Get an encoding for code page 1252 (Western Europe character set).
Encoding cp1252 = Encoding.GetEncoding(1252);
// Define and display a string.
string str = "\u24c8 \u2075 \u221e";
Console.WriteLine("Original string: " + str);
Console.Write("Code points in string: ");
foreach (var ch in str)
Console.Write("{0} ", Convert.ToUInt16(ch).ToString("X4"));
Console.WriteLine("\n");
// Encode a Unicode string.
Byte[] bytes = cp1252.GetBytes(str);
Console.Write("Encoded bytes: ");
foreach (byte byt in bytes)
Console.Write("{0:X2} ", byt);
Console.WriteLine("\n");
// Decode the string.
string str2 = cp1252.GetString(bytes);
Console.WriteLine($"String round-tripped: {str.Equals(str2)}");
if (! str.Equals(str2)) {
Console.WriteLine(str2);
foreach (var ch in str2)
Console.Write("{0} ", Convert.ToUInt16(ch).ToString("X4"));
}
}
}
// The example displays the following output:
// Original string: Ⓢ ⁵ ∞
// Code points in string: 24C8 0020 2075 0020 221E
//
// Encoded bytes: 3F 20 35 20 38
//
// String round-tripped: False
// ? 5 8
// 003F 0020 0035 0020 0038
Imports System.Text
Module Example
Public Sub Main()
' Get an encoding for code page 1252 (Western Europe character set).
Dim cp1252 As Encoding = Encoding.GetEncoding(1252)
' Define and display a string.
Dim str As String = String.Format("{0} {1} {2}", ChrW(&h24c8), ChrW(&H2075), ChrW(&h221E))
Console.WriteLine("Original string: " + str)
Console.Write("Code points in string: ")
For Each ch In str
Console.Write("{0} ", Convert.ToUInt16(ch).ToString("X4"))
Next
Console.WriteLine()
Console.WriteLine()
' Encode a Unicode string.
Dim bytes() As Byte = cp1252.GetBytes(str)
Console.Write("Encoded bytes: ")
For Each byt In bytes
Console.Write("{0:X2} ", byt)
Next
Console.WriteLine()
Console.WriteLine()
' Decode the string.
Dim str2 As String = cp1252.GetString(bytes)
Console.WriteLine("String round-tripped: {0}", str.Equals(str2))
If Not str.Equals(str2) Then
Console.WriteLine(str2)
For Each ch In str2
Console.Write("{0} ", Convert.ToUInt16(ch).ToString("X4"))
Next
End If
End Sub
End Module
' The example displays the following output:
' Original string: Ⓢ ⁵ ∞
' Code points in string: 24C8 0020 2075 0020 221E
'
' Encoded bytes: 3F 20 35 20 38
'
' String round-tripped: False
' ? 5 8
' 003F 0020 0035 0020 0038
En iyi eşleme, Unicode verilerini kod sayfası verilerine kodlayan bir Encoding nesnesi için varsayılan davranıştır ve bu davranışa dayanan eski uygulamalar vardır. Ancak, çoğu yeni uygulama güvenlik nedeniyle en uygun davranıştan kaçınmalıdır. Örneğin, uygulamalar en uygun kodlama aracılığıyla bir etki alanı adı koymamalıdır.
Uyarı
Ayrıca, kodlama için özel bir en uygun geri dönüş eşlemesi de uygulayabilirsiniz. Daha fazla bilgi için Özel Geri Dönüş Stratejisini Uygulama bölümüne bakın.
Kodlama nesnesi için en uygun geri dönüş varsayılan değerse, Encoding.GetEncoding(Int32, EncoderFallback, DecoderFallback) veya Encoding.GetEncoding(String, EncoderFallback, DecoderFallback) aşırı yüklemesini çağırarak bir Encoding nesnesi aldığınızda başka bir geriye dönüş stratejisi seçebilirsiniz. Aşağıdaki bölüm, 1252 kod sayfasına eşlenemeyen her karakteri yıldız (*) ile değiştiren bir örnek içerir.
using System;
using System.Text;
public class Example
{
public static void Main()
{
Encoding cp1252r = Encoding.GetEncoding(1252,
new EncoderReplacementFallback("*"),
new DecoderReplacementFallback("*"));
string str1 = "\u24C8 \u2075 \u221E";
Console.WriteLine(str1);
foreach (var ch in str1)
Console.Write("{0} ", Convert.ToUInt16(ch).ToString("X4"));
Console.WriteLine();
byte[] bytes = cp1252r.GetBytes(str1);
string str2 = cp1252r.GetString(bytes);
Console.WriteLine($"Round-trip: {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
Alternatif Çözüm
Bir karakterin hedef düzende tam eşleşmesi yoksa, ancak eşlenebileceği uygun bir karakter yoksa, uygulama yeni bir karakter veya dize belirtebilir. Bu, kodunu çözemediği iki baytlık diziyi REPLACEMENT_CHARACTER (U+FFFD) ile değiştiren Unicode kod çözücü için varsayılan davranıştır. Ayrıca #D0 sınıfının varsayılan davranışıdır ve kodlayamadığı veya çözemediği her karakteri bir soru işaretiyle değiştirir. Aşağıdaki örnekte, önceki örnekteki Unicode dizesinin karakter değişimi gösterilmektedir. Çıktıda gösterildiği gibi, ASCII bayt değerine çözülemeyen her karakter, soru işaretinin ASCII kodu olan 0x3F ile değiştirilir.
using System;
using System.Text;
public class Example
{
public static void Main()
{
Encoding enc = Encoding.ASCII;
string str1 = "\u24C8 \u2075 \u221E";
Console.WriteLine(str1);
foreach (var ch in str1)
Console.Write("{0} ", Convert.ToUInt16(ch).ToString("X4"));
Console.WriteLine("\n");
// Encode the original string using the ASCII encoder.
byte[] bytes = enc.GetBytes(str1);
Console.Write("Encoded bytes: ");
foreach (var byt in bytes)
Console.Write("{0:X2} ", byt);
Console.WriteLine("\n");
// Decode the ASCII bytes.
string str2 = enc.GetString(bytes);
Console.WriteLine($"Round-trip: {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, #D0 ve #D1 sınıflarını içerir. Bu sınıflar, bir karakter bir kodlama veya kod çözme işleminde tam olarak eşlenmiyorsa yerine bir değiştirme dizesi koyar. Varsayılan olarak, bu değiştirme dizesi bir soru işaretidir, ancak farklı bir dize seçmek için sınıf oluşturucusunun aşırı yüklenmiş bir versiyonunu çağırabilirsiniz. Genellikle, değiştirme dizesi tek bir karakterdir, ancak bu bir gereksinim değildir. Aşağıdaki örnek, değiştirme dizesi olarak yıldız (*) kullanan bir EncoderReplacementFallback nesnesinin örneğini oluşturarak kod sayfası 1252 kodlayıcısının davranışını değiştiriyor.
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
Uyarı
Kodlama için bir değiştirme sınıfı da uygulayabilirsiniz. Daha fazla bilgi için Özel Geri Dönüş Stratejisi Uygulama bölümüne bakın.
SORU İŞARETİ'ne (U+003F) ek olarak, Unicode DEĞİşTİrME KARAKTERİ (U+FFFD), özellikle unicode karakterlerine başarıyla çevrilemeyen bayt dizilerinin kodunu çözdüğünüzde genellikle değiştirme dizesi olarak kullanılır. Ancak, yerine koymak için herhangi bir dizeyi seçmekte özgürsünüz ve bu dize birden çok karakter içerebilir.
İstisna Yedek Çözümü
Kodlayıcı, bir dizi karakteri kodlayamıyorsa en uygun geri dönüş veya değiştirme dizesi sağlamak yerine bir #D0 oluşturabilir ve kod çözücü bir bayt dizisinin kodunu çözemezse #D1 oluşturabilir. Kodlama ve kod çözme işlemlerinde özel durum oluşturmak için, #D2 yöntemine sırasıyla bir #D0 nesnesi ve #D1 nesnesi sağlayın. Aşağıdaki örnek, ASCIIEncoding sınıfıyla özel durum yedeklemesini gösterir.
using System;
using System.Text;
public class Example
{
public static void Main()
{
Encoding enc = Encoding.GetEncoding("us-ascii",
new EncoderExceptionFallback(),
new DecoderExceptionFallback());
string str1 = "\u24C8 \u2075 \u221E";
Console.WriteLine(str1);
foreach (var ch in str1)
Console.Write("{0} ", Convert.ToUInt16(ch).ToString("X4"));
Console.WriteLine("\n");
// Encode the original string using the ASCII encoder.
byte[] bytes = {};
try {
bytes = enc.GetBytes(str1);
Console.Write("Encoded bytes: ");
foreach (var byt in bytes)
Console.Write("{0:X2} ", byt);
Console.WriteLine();
}
catch (EncoderFallbackException e) {
Console.Write("Exception: ");
if (e.IsUnknownSurrogate())
Console.WriteLine($"Unable to encode surrogate pair 0x{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.
Uyarı
Kodlama işlemi için özel bir özel durum işleyicisi de uygulayabilirsiniz. Daha fazla bilgi için Özel Geri Dönüş Stratejisi Uygulama bölümüne bakın.
#D0 ve #D1 nesneleri, özel duruma neden olan koşul hakkında aşağıdaki bilgileri sağlar:
#D0 nesnesi, kodlanamayan karakterin veya karakterlerin bilinmeyen bir vekil çifti (bu durumda yöntem #B2 döndürür) veya bilinmeyen tek bir karakteri (bu durumda yöntem #B3 ) temsil edip etmediğini belirten bir #D1 yöntemi içerir. Vekil çiftindeki karakterlere EncoderFallbackException.CharUnknownHigh ve EncoderFallbackException.CharUnknownLow özelliklerinden erişilebilir. Bilinmeyen karakter, EncoderFallbackException.CharUnknown özelliğinden kullanılabilir. #D0 özelliği, dizede kodlanamayan ilk karakterin bulunduğu konumu gösterir.
#D0 nesnesi, çözülemeyen bir bayt dizisi döndüren bir #D1 özelliği içerir. #D0 özelliği bilinmeyen baytların başlangıç konumunu gösterir.
#D0 ve #D1 nesneleri özel durum hakkında yeterli tanılama bilgileri sağlasa da, kodlama veya kod çözme arabelleğine erişim sağlamaz. Bu nedenle, kodlama veya kod çözme yönteminde geçersiz verilerin değiştirilmesine veya düzeltilmesine izin vermezler.
Özel Geri Dönüş Stratejisi Uygulaması
.NET, kod sayfaları tarafından dahili olarak uygulanan en uygun eşlemeye ek olarak, geri dönüş stratejisi uygulamak için aşağıdaki sınıfları içerir:
Kodlama işlemlerindeki karakterleri değiştirmek için #D0 ve #D1 kullanın.
Kod çözme işlemlerindeki karakterleri değiştirmek için #D0 ve #D1 kullanın.
Bir karakter kodlanamadığında EncoderExceptionFallback ve EncoderExceptionFallbackBuffer kullanarak bir EncoderFallbackException fırlatın.
Karakterin kodu çözülemediğinde bir DecoderFallbackException atmak için DecoderExceptionFallback ve DecoderExceptionFallbackBuffer kullanın.
Ayrıca, aşağıdaki adımları izleyerek en uygun geri dönüş, yedek geri dönüş veya özel durum geri dönüşü kullanan özel bir çözüm uygulayabilirsiniz:
Kodlama işlemleri için #D0 ve kod çözme işlemleri için #D1 bir sınıf türetin.
Kodlama işlemleri için #D0 ve kod çözme işlemleri için #D1 bir sınıf türetin.
Özel durum geri dönüşü için, önceden tanımlanmış #D0 ve #D1 sınıfları gereksinimlerinizi karşılamıyorsa, #D2 veya #B3 gibi bir özel durum nesnesinden bir sınıf türetin.
EncoderFallback veya DecoderFallback'ten türetme
Özel bir geri dönüş çözümü uygulamak için kodlama işlemleri için #D0 ve kod çözme işlemleri için #D1 devralan bir sınıf oluşturmanız gerekir. Bu sınıfların örnekleri #D0 yöntemine geçirilir ve kodlama sınıfı ile geri dönüş uygulaması arasında aracı görevi görür.
Kodlayıcı veya kod çözücü için özel bir geri dönüş çözümü oluşturduğunuzda aşağıdaki üyeleri uygulamanız gerekir:
EncoderFallback.MaxCharCount veya DecoderFallback.MaxCharCount özelliği, en iyi uyum, değiştirme veya özel durum yedeklemesinin tek bir karakteri değiştirmek için döndürebileceği mümkün olan en fazla karakter sayısını döndürür. Özel özel durum geri dönüşü için değeri sıfırdır.
Özel EncoderFallbackBuffer veya DecoderFallbackBuffer uygulamanızı döndüren EncoderFallback.CreateFallbackBuffer veya DecoderFallback.CreateFallbackBuffer yöntemi. yöntemi, başarıyla kodlayamadığı ilk karakterle karşılaştığında kodlayıcı tarafından veya kodu başarıyla çözemediği ilk baytla karşılaştığında kod çözücü tarafından çağrılır.
EncoderFallbackBuffer veya DecoderFallbackBuffer'dan türetme
Özel bir geri dönüş çözümü uygulamak için kodlama işlemleri için #D0 ve kod çözme işlemleri için #D1 devralan bir sınıf da oluşturmanız gerekir. Bu sınıfların örnekleri, #D1 ve #D2 sınıflarının #D0 yöntemi tarafından döndürülür. #D0 yöntemi kodlayamadığı ilk karakterle karşılaştığında kodlayıcı tarafından çağrılır ve kodunu çözemediği bir veya daha fazla baytla karşılaştığında kod çözücü tarafından #D1 yöntemi çağrılır. #D0 ve #D1 sınıfları geri dönüş uygulamasını sağlar. Her örnek, kodlanamayan karakterin veya kodlanamayan bayt dizisinin yerini alacak geri dönüş karakterlerini içeren bir arabelleği temsil eder.
Kodlayıcı veya kod çözücü için özel bir geri dönüş çözümü oluşturduğunuzda aşağıdaki üyeleri uygulamanız gerekir:
EncoderFallbackBuffer.Fallback veya DecoderFallbackBuffer.Fallback metodu. EncoderFallbackBuffer.Fallback, kodlayıcı tarafından kodlayamayacağı karakter hakkında geri dönüş arabelleğine bilgi sağlamak için çağrılır. Kodlanacak karakter bir vekil çift olabileceğinden, bu yöntem aşırı yüklenmiştir. Bir aşırı yükleme, kodlanacak karaktere ve dizedeki dizinine geçirilir. İkinci aşırı yükleme, dizedeki diziniyle birlikte yüksek ve düşük vekile geçirilir. DecoderFallbackBuffer.Fallback yöntemi, kod çözücü tarafından, kodunu çözemediği baytlar hakkında geri dönüş arabelleğine bilgi sağlamak için çağrılır. Bu yönteme, kodlayamadığı bir bayt dizisi ve ilk baytın dizini verilir. Geri alma arabelleği en uygun veya yedek karakter veya karakterleri sağlayabiliyorsa, geri alma yöntemi
truedöndürmelidir; aksi takdirde,falsedöndürmelidir. Bir istisna geri dönüşü için, geri dönüş yöntemi bir istisna oluşturmalıdır.Geri dönüş arabelleğinden sonraki karakteri almak için kodlayıcı veya kod çözücü tarafından tekrar tekrar çağrılan #D0 veya #D1 yöntemi. Tüm geri dönüş karakterleri döndürüldüyse yöntemi U+0000 döndürmelidir.
EncoderFallbackBuffer.Remaining veya DecoderFallbackBuffer.Remaining özelliği, geri dönüş arabelleğinde kalan karakter sayısını döndürür.
EncoderFallbackBuffer.MovePrevious veya DecoderFallbackBuffer.MovePrevious metodu, geri dönüş arabelleğindeki geçerli konumu önceki karaktere taşır.
Geri dönüş arabelleğinin yeniden başlatılmasını sağlayan #D0 veya #D1 yöntemi.
Yedekleme uygulaması en uygun yedekleme veya yerine yedekleme ise, ve sınıflarından türetilen sınıflar, iki özel örnek alanı da tutar: arabellekteki tam karakter sayısı; ve döndürülecek arabellekteki sonraki karakterin dizini.
EncoderFallback Örneği
Önceki bir örnekte, ASCII karakterlerine karşılık olmayan Unicode karakterleri yıldız (*) ile değiştirmek için yedek geri dönüş kullanılmıştır. Aşağıdaki örnek, ASCII olmayan karakterlerin daha iyi eşlemesini sağlamak için bunun yerine özel en uygun geri dönüş uygulamasını kullanır.
Aşağıdaki kod, ASCII olmayan karakterlerin en iyi eşleştirilmesini işlemek için EncoderFallback'den türetilen CustomMapper adlı bir sınıfı tanımlar.
CreateFallbackBuffer yöntemi, EncoderFallbackBuffer uygulamasını sağlayan bir CustomMapperFallbackBuffer nesnesi döndürür. #D0 sınıfı, desteklenmeyen Unicode karakterlerinin (anahtar değeri) ve karşılık gelen 8 bit karakterlerinin (64 bit tamsayıda ardışık iki bayt olarak depolanır) eşlemelerini depolamak için bir #D1 nesnesi kullanır. Bu eşlemeye geri dönüş tamponunda erişim sağlamak için, #D0 örneğinin #D1 sınıf kurucusunun parametresi olarak geçirilmesi gerekir. En uzun eşleme U+221E Unicode karakteri için "INF" dizesi olduğundan, MaxCharCount özelliği 3 döndürür.
public class CustomMapper : EncoderFallback
{
public string DefaultString;
internal Dictionary<ushort, ulong> mapping;
public CustomMapper() : this("*")
{
}
public CustomMapper(string defaultString)
{
this.DefaultString = defaultString;
// Create table of mappings
mapping = new Dictionary<ushort, ulong>();
mapping.Add(0x24C8, 0x53);
mapping.Add(0x2075, 0x35);
mapping.Add(0x221E, 0x49004E0046);
}
public override EncoderFallbackBuffer CreateFallbackBuffer()
{
return new CustomMapperFallbackBuffer(this);
}
public override int MaxCharCount
{
get { return 3; }
}
}
Public Class CustomMapper : Inherits EncoderFallback
Public DefaultString As String
Friend mapping As Dictionary(Of UShort, ULong)
Public Sub New()
Me.New("?")
End Sub
Public Sub New(ByVal defaultString As String)
Me.DefaultString = defaultString
' Create table of mappings
mapping = New Dictionary(Of UShort, ULong)
mapping.Add(&H24C8, &H53)
mapping.Add(&H2075, &H35)
mapping.Add(&H221E, &H49004E0046)
End Sub
Public Overrides Function CreateFallbackBuffer() As System.Text.EncoderFallbackBuffer
Return New CustomMapperFallbackBuffer(Me)
End Function
Public Overrides ReadOnly Property MaxCharCount As Integer
Get
Return 3
End Get
End Property
End Class
Aşağıdaki kod, EncoderFallbackBuffer sınıfından türetilen CustomMapperFallbackBuffer sınıfını tanımlar. En uygun eşlemeleri içeren ve CustomMapper örneği içinde tanımlanan sözlük, sınıf kurucusundan erişilebilir. #D0 yöntemi, ASCII kodlayıcının kodlayamayacağı Unicode karakterlerinden herhangi biri eşleme sözlüğünde tanımlanmışsa #D1 döndürür; aksi takdirde, #B2 döndürür. Her geri dönüş için, özel #D0 değişkeni döndürülecek karakterlerin sayısını gösterir ve özel #D1 değişkeni, döndürülecek sonraki karakterin dize arabelleğindeki #B2 konumunu gösterir.
public class CustomMapperFallbackBuffer : EncoderFallbackBuffer
{
int count = -1; // Number of characters to return
int index = -1; // Index of character to return
CustomMapper fb;
string charsToReturn;
public CustomMapperFallbackBuffer(CustomMapper fallback)
{
this.fb = fallback;
}
public override bool Fallback(char charUnknownHigh, char charUnknownLow, int index)
{
// Do not try to map surrogates to ASCII.
return false;
}
public override bool Fallback(char charUnknown, int index)
{
// Return false if there are already characters to map.
if (count >= 1) return false;
// Determine number of characters to return.
charsToReturn = String.Empty;
ushort key = Convert.ToUInt16(charUnknown);
if (fb.mapping.ContainsKey(key)) {
byte[] bytes = BitConverter.GetBytes(fb.mapping[key]);
int ctr = 0;
foreach (var byt in bytes) {
if (byt > 0) {
ctr++;
charsToReturn += (char) byt;
}
}
count = ctr;
}
else {
// Return default.
charsToReturn = fb.DefaultString;
count = 1;
}
this.index = charsToReturn.Length - 1;
return true;
}
public override char GetNextChar()
{
// We'll return a character if possible, so subtract from the count of chars to return.
count--;
// If count is less than zero, we've returned all characters.
if (count < 0)
return '\u0000';
this.index--;
return charsToReturn[this.index + 1];
}
public override bool MovePrevious()
{
// Original: if count >= -1 and pos >= 0
if (count >= -1) {
count++;
return true;
}
else {
return false;
}
}
public override int Remaining
{
get { return count < 0 ? 0 : count; }
}
public override void Reset()
{
count = -1;
index = -1;
}
}
Public Class CustomMapperFallbackBuffer : Inherits EncoderFallbackBuffer
Dim count As Integer = -1 ' Number of characters to return
Dim index As Integer = -1 ' Index of character to return
Dim fb As CustomMapper
Dim charsToReturn As String
Public Sub New(ByVal fallback As CustomMapper)
MyBase.New()
Me.fb = fallback
End Sub
Public Overloads Overrides Function Fallback(ByVal charUnknownHigh As Char, ByVal charUnknownLow As Char, ByVal index As Integer) As Boolean
' Do not try to map surrogates to ASCII.
Return False
End Function
Public Overloads Overrides Function Fallback(ByVal charUnknown As Char, ByVal index As Integer) As Boolean
' Return false if there are already characters to map.
If count >= 1 Then Return False
' Determine number of characters to return.
charsToReturn = String.Empty
Dim key As UShort = Convert.ToUInt16(charUnknown)
If fb.mapping.ContainsKey(key) Then
Dim bytes() As Byte = BitConverter.GetBytes(fb.mapping.Item(key))
Dim ctr As Integer
For Each byt In bytes
If byt > 0 Then
ctr += 1
charsToReturn += Chr(byt)
End If
Next
count = ctr
Else
' Return default.
charsToReturn = fb.DefaultString
count = 1
End If
Me.index = charsToReturn.Length - 1
Return True
End Function
Public Overrides Function GetNextChar() As Char
' We'll return a character if possible, so subtract from the count of chars to return.
count -= 1
' If count is less than zero, we've returned all characters.
If count < 0 Then Return ChrW(0)
Me.index -= 1
Return charsToReturn(Me.index + 1)
End Function
Public Overrides Function MovePrevious() As Boolean
' Original: if count >= -1 and pos >= 0
If count >= -1 Then
count += 1
Return True
Else
Return False
End If
End Function
Public Overrides ReadOnly Property Remaining As Integer
Get
Return If(count < 0, 0, count)
End Get
End Property
Public Overrides Sub Reset()
count = -1
index = -1
End Sub
End Class
Aşağıdaki kod daha sonra #D0 nesnesinin örneğini oluşturur ve bunun bir örneğini #D1 yöntemine geçirir. Çıkış, en uygun geri dönüş uygulamasının özgün dizedeki ASCII olmayan üç karakteri başarıyla işlediğini gösterir.
using System;
using System.Collections.Generic;
using System.Text;
class Program
{
static void Main()
{
Encoding enc = Encoding.GetEncoding("us-ascii", new CustomMapper(), new DecoderExceptionFallback());
string str1 = "\u24C8 \u2075 \u221E";
Console.WriteLine(str1);
for (int ctr = 0; ctr <= str1.Length - 1; ctr++) {
Console.Write("{0} ", Convert.ToUInt16(str1[ctr]).ToString("X4"));
if (ctr == str1.Length - 1)
Console.WriteLine();
}
Console.WriteLine();
// Encode the original string using the ASCII encoder.
byte[] bytes = enc.GetBytes(str1);
Console.Write("Encoded bytes: ");
foreach (var byt in bytes)
Console.Write("{0:X2} ", byt);
Console.WriteLine("\n");
// Decode the ASCII bytes.
string str2 = enc.GetString(bytes);
Console.WriteLine($"Round-trip: {str1.Equals(str2)}");
if (! str1.Equals(str2)) {
Console.WriteLine(str2);
foreach (var ch in str2)
Console.Write("{0} ", Convert.ToUInt16(ch).ToString("X4"));
Console.WriteLine();
}
}
}
Imports System.Text
Imports System.Collections.Generic
Module Module1
Sub Main()
Dim enc As Encoding = Encoding.GetEncoding("us-ascii", New CustomMapper(), New DecoderExceptionFallback())
Dim str1 As String = String.Format("{0} {1} {2}", ChrW(&H24C8), ChrW(&H2075), ChrW(&H221E))
Console.WriteLine(str1)
For ctr As Integer = 0 To str1.Length - 1
Console.Write("{0} ", Convert.ToUInt16(str1(ctr)).ToString("X4"))
If ctr = str1.Length - 1 Then Console.WriteLine()
Next
Console.WriteLine()
' Encode the original string using the ASCII encoder.
Dim bytes() As Byte = enc.GetBytes(str1)
Console.Write("Encoded bytes: ")
For Each byt In bytes
Console.Write("{0:X2} ", byt)
Next
Console.WriteLine()
Console.WriteLine()
' Decode the ASCII bytes.
Dim str2 As String = enc.GetString(bytes)
Console.WriteLine("Round-trip: {0}", str1.Equals(str2))
If Not str1.Equals(str2) Then
Console.WriteLine(str2)
For Each ch In str2
Console.Write("{0} ", Convert.ToUInt16(ch).ToString("X4"))
Next
Console.WriteLine()
End If
End Sub
End Module
Ayrıca bkz.
- .NET'de karakter kodlamaya giriş
- Encoder
- Decoder
- DecoderFallback
- Encoding
- EncoderFallback
- Genelleştirme ve yerelleştirme