Bu popüler bir soru. Yazarın ne sorduğunu ve bunun en yaygın ihtiyaç olandan farklı olduğunu anlamak önemlidir. Kodun gerekli olmadığı yerlerde kötüye kullanılmasını engellemek için, daha sonra önce cevap verdim.
Ortak İhtiyaç
Her dizenin bir karakter kümesi ve kodlaması vardır. Bir System.String
nesneyi bir diziye dönüştürdüğünüzde System.Byte
hala bir karakter kümesi ve kodlaması vardır. Çoğu kullanım için, hangi karakter kümesine ve kodlamaya ihtiyacınız olduğunu bilirsiniz ve .NET "dönüşümle kopyalama" yı kolaylaştırır. Sadece uygun Encoding
sınıfı seçin .
// using System.Text;
Encoding.UTF8.GetBytes(".NET String to byte array")
Dönüşümün, hedef karakter kümesinin veya kodlamanın kaynaktaki bir karakteri desteklemediği durumları ele alması gerekebilir. Bazı seçenekleriniz var: istisna, değiştirme veya atlama. Varsayılan ilke '?' Yerine kullanılır.
// using System.Text;
var text = Encoding.ASCII.GetString(Encoding.ASCII.GetBytes("You win €100"));
// -> "You win ?100"
Açıkçası, dönüşümler mutlaka kayıpsız değildir!
Not: System.String
Kaynak karakter kümesi Unicode'dur.
Kafa karıştırıcı olan tek şey, .NET'in o karakter kümesinin belirli bir kodlamasının adı için bir karakter kümesinin adını kullanmasıdır. Encoding.Unicode
çağrılmalıdır Encoding.UTF16
.
Çoğu kullanım için bu kadar. Eğer ihtiyacınız olan buysa, burada okumayı bırakın. Bir kodlamanın ne olduğunu anlamadıysanız eğlenceli Joel Spolsky makalesine bakın .
Özel İhtiyaç
Şimdi, soru yazar, "Her dize bir bayt dizisi olarak saklanır, değil mi? Neden bu baytlara sahip olamıyorum?"
Herhangi bir dönüşüm istemiyor.
Gönderen C # spec :
C # 'da karakter ve dize işleme Unicode kodlaması kullanır. Karakter türü bir UTF-16 kod birimini ve dize türü bir dizi UTF-16 kod birimini temsil eder.
Dolayısıyla, boş dönüşüm (yani UTF-16'dan UTF-16'ya) istersek, istenen sonucu alacağımızı biliyoruz:
Encoding.Unicode.GetBytes(".NET String to byte array")
Ancak kodlamalardan bahsetmemek için, bunu başka bir şekilde yapmalıyız. Bir ara veri türü kabul edilebilirse, bunun için kavramsal bir kısayol vardır:
".NET String to byte array".ToCharArray()
Bu bize istenen veri tipini vermez, ancak Mehrdad'ın cevabı , bu Char dizisinin BlockCopy kullanarak bir Byte dizisine nasıl dönüştürüleceğini gösterir . Ancak, bu dizeyi iki kez kopyalar! Ve çok açık bir şekilde kodlamaya özgü kod kullanır: veri türü System.Char
.
Dize'nin saklandığı gerçek baytlara ulaşmanın tek yolu bir işaretçi kullanmaktır. fixed
İfadesi değerlerinin adresini alarak verir. C # spec'ten:
String türünde bir ifade için [...] başlatıcı, dizgideki ilk karakterin adresini hesaplar.
Bunu yapmak için, derleyici kod atlama ile dize nesnesinin diğer bölümleri üzerine yazar RuntimeHelpers.OffsetToStringData
. Ham baytları almak için dizeye bir işaretçi oluşturun ve gereken bayt sayısını kopyalayın.
// using System.Runtime.InteropServices
unsafe byte[] GetRawBytes(String s)
{
if (s == null) return null;
var codeunitCount = s.Length;
/* We know that String is a sequence of UTF-16 codeunits
and such codeunits are 2 bytes */
var byteCount = codeunitCount * 2;
var bytes = new byte[byteCount];
fixed(void* pRaw = s)
{
Marshal.Copy((IntPtr)pRaw, bytes, 0, byteCount);
}
return bytes;
}
@CodesInChaos'un işaret ettiği gibi, sonuç makinenin endianitesine bağlıdır. Ancak soru yazarı bununla ilgilenmiyor.