Ini pertanyaan populer. Penting untuk memahami apa yang ditanyakan oleh penulis pertanyaan, dan berbeda dari apa yang mungkin merupakan kebutuhan paling umum. Untuk mencegah penyalahgunaan kode yang tidak diperlukan, saya sudah jawab yang pertama.
Kebutuhan Umum
Setiap string memiliki rangkaian karakter dan pengodean. Saat Anda mengonversi System.String
objek ke array, System.Byte
Anda masih memiliki kumpulan karakter dan pengodean. Untuk sebagian besar penggunaan, Anda akan tahu set karakter dan penyandian yang Anda butuhkan dan .NET membuatnya mudah untuk "menyalin dengan konversi." Pilih saja Encoding
kelas yang sesuai .
// using System.Text;
Encoding.UTF8.GetBytes(".NET String to byte array")
Konversi mungkin perlu menangani kasus di mana karakter target yang ditetapkan atau pengodean tidak mendukung karakter yang ada di sumber. Anda memiliki beberapa pilihan: pengecualian, penggantian atau lewati. Kebijakan default adalah mengganti '?'.
// using System.Text;
var text = Encoding.ASCII.GetString(Encoding.ASCII.GetBytes("You win €100"));
// -> "You win ?100"
Jelas, konversi tidak harus rugi!
Catatan: Untuk System.String
rangkaian karakter sumber adalah Unicode.
Satu-satunya hal yang membingungkan adalah .NET menggunakan nama set karakter untuk nama satu pengkodean set karakter tertentu. Encoding.Unicode
harus dipanggil Encoding.UTF16
.
Itu saja untuk sebagian besar penggunaan. Jika itu yang Anda butuhkan, berhenti membaca di sini. Lihat artikel Joel Spolsky yang menyenangkan jika Anda tidak mengerti apa itu encoding.
Kebutuhan Khusus
Sekarang, penulis pertanyaan bertanya, "Setiap string disimpan sebagai array byte, kan? Mengapa saya tidak bisa hanya memiliki byte itu?"
Dia tidak menginginkan pertobatan.
Dari spesifikasi C # :
Pemrosesan karakter dan string dalam C # menggunakan pengkodean Unicode. Tipe char mewakili unit kode UTF-16, dan tipe string mewakili urutan unit kode UTF-16.
Jadi, kita tahu bahwa jika kita meminta konversi nol (yaitu, dari UTF-16 ke UTF-16), kita akan mendapatkan hasil yang diinginkan:
Encoding.Unicode.GetBytes(".NET String to byte array")
Tetapi untuk menghindari penyebutan encoding, kita harus melakukannya dengan cara lain. Jika tipe data antara dapat diterima, ada jalan pintas konseptual untuk ini:
".NET String to byte array".ToCharArray()
Itu tidak memberikan kita tipe data yang diinginkan tetapi jawaban Mehrdad menunjukkan bagaimana mengubah array Char ini menjadi array Byte menggunakan BlockCopy . Namun, ini menyalin string dua kali! Dan, itu juga secara eksplisit menggunakan kode khusus pengkodean: tipe data System.Char
.
Satu-satunya cara untuk mendapatkan byte aktual dari String yang disimpan adalah dengan menggunakan pointer. The fixed
pernyataan memungkinkan mengambil alamat nilai-nilai. Dari spesifikasi C #:
[Untuk] ekspresi tipe string, ... initializer menghitung alamat karakter pertama dalam string.
Untuk melakukannya, kompiler menulis kode lompati bagian lain dari objek string RuntimeHelpers.OffsetToStringData
. Jadi, untuk mendapatkan byte mentah, buat saja pointer ke string dan salin jumlah byte yang dibutuhkan.
// 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;
}
Seperti @CodesInChaos tunjukkan, hasilnya tergantung pada endianness dari mesin. Tetapi penulis pertanyaan tidak peduli dengan itu.