Це популярне питання. Важливо зрозуміти, що задає автор питання, і чим він відрізняється від того, що, мабуть, є найпоширенішою потребою. Щоб відмовити від неправильного використання коду там, де він не потрібен, я відповів першим пізніше.
Загальна потреба
Кожна рядок має набір символів та кодування. Коли ви перетворюєте System.String
об'єкт у масив, у System.Byte
вас все ще є набір символів та кодування. У більшості звичок ви знаєте, який набір символів та кодування вам потрібен, і .NET спрощує "копіювання з перетворенням". Просто виберіть відповідний Encoding
клас.
// using System.Text;
Encoding.UTF8.GetBytes(".NET String to byte array")
Перетворення може потребувати обробки випадків, коли цільовий набір символів або кодування не підтримує символ, що знаходиться в джерелі. У вас є кілька варіантів: виняток, заміна або пропуск. Політикою за замовчуванням є заміна '?'.
// using System.Text;
var text = Encoding.ASCII.GetString(Encoding.ASCII.GetBytes("You win €100"));
// -> "You win ?100"
Зрозуміло, що конверсії не обов'язково без втрат!
Примітка. Для System.String
набору символів джерелом є Unicode.
Єдина заплутана річ у тому, що .NET використовує ім'я набору символів для імені одного конкретного кодування цього набору символів. Encoding.Unicode
слід називати Encoding.UTF16
.
Це все для більшості звичаїв. Якщо це те, що вам потрібно, перестаньте читати тут. Дивіться цікаву статтю Джоела Спольського, якщо ви не розумієте, що таке кодування.
Конкретна потреба
Тепер автор запитує: "Кожна рядок зберігається як масив байтів, так? Чому я просто не можу мати ці байти?"
Він не хоче перетворення.
Від специфікації C # :
Для обробки символів і рядків у C # використовується кодування Unicode. Тип char являє собою кодову одиницю UTF-16, а тип рядка являє собою послідовність кодових одиниць UTF-16.
Отже, ми знаємо, що якщо попросимо конвертувати нуль (тобто з UTF-16 в UTF-16), ми отримаємо бажаний результат:
Encoding.Unicode.GetBytes(".NET String to byte array")
Але щоб уникнути згадки про кодування, ми повинні зробити це іншим способом. Якщо проміжний тип даних прийнятний, для цього існує концептуальний ярлик:
".NET String to byte array".ToCharArray()
Це не дає нам потрібного типу даних, але відповідь Мехрдада показує, як перетворити цей масив Char у масив байтів за допомогою BlockCopy . Однак це копіює рядок двічі! І він занадто явно використовує специфічний для кодування код: тип даних System.Char
.
Єдиний спосіб дістатися до фактичних байтів, в яких зберігається рядок, - це використовувати покажчик. fixed
Заява дозволяє приймати адреса значень. Від специфікації C #:
[Для] виразу рядка типу, ... ініціалізатор обчислює адресу першого символу в рядку.
Для цього компілятор записує код пропускання через інші частини об'єкта рядка RuntimeHelpers.OffsetToStringData
. Отже, щоб отримати необроблені байти, просто створіть вказівник на рядок і скопіюйте кількість потрібних байтів.
// 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, результат залежить від витривалості машини. Але автор питання цим не займається.