Как преобразовать строку в массив байтов в .NET?

У меня есть строка, которую мне нужно преобразовать в эквивалентный массив байтов в .NET.

Это должно быть легко, но у меня спазмы мозга.

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
73
0
68 927
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Ответ принят как подходящий

Вам нужно использовать кодировку (System.Text.Encoding), чтобы сообщить .NET, что вы ожидаете в качестве вывода. Например, в UTF-16 (= System.Text.Encoding.Unicode):

var result = System.Text.Encoding.Unicode.GetBytes(text);

В System.Text.Encoding гораздо больше кодировок, чем просто Unicode: убедитесь, что вы понимаете, какая из них вам нужна.

Joel Coehoorn 28.10.2008 00:24

Джоэл: Поэтому я написал «например». ;-) Но ваш комментарий, конечно, верен.

Konrad Rudolph 28.10.2008 00:27

:) Пытаясь показать, где находятся кодировки, отличные от UTF16, я, наверное, мог бы сформулировать это лучше.

Joel Coehoorn 28.10.2008 00:42

не могли бы вы увидеть мой вопрос, связанный с этим?

Moeez 19.05.2020 07:34

Нравится:

    string test = "text";
    byte[] arr = Encoding.UTF8.GetBytes(test);

Какую кодировку вы используете? У Конрада это в значительной степени не так, но есть и другие, и вы можете получить глупые результаты, используя неправильный:

byte[] bytes = System.Text.Encoding.XXX.GetBytes(text)

Где XXX может быть:

ASCII
BigEndianUnicode
Default
Unicode
UTF32
UTF7
UTF8

Сначала определитесь, какую кодировку вы хотите: сначала вам нужно знать немного о Unicode.

Затем определите, какому System.Text.Encoding соответствует. Мой Справочная карта Core .NET описывает большинство распространенных и то, как получить экземпляр (например, с помощью статического свойства Encoding или путем вызова Encoding.GetEncoding.

Наконец, определитесь, хотите ли вы использовать все байты сразу (это самый простой способ работы - вызовите Encoding.GetBytes (строка) один раз, и все готово) или вам нужно разбить его на куски - в этом случае вы захотите использовать Encoding.GetEncoder а затем кодировать по частям. Кодировщик заботится о сохранении состояния между вызовами, например, в случае, если вам нужно прервать половину пути через символ.

@JonSkeet: Вам действительно не нужна кодировка, если вы (или кто-то другой) на самом деле не собираетесь интерпретировать байтов, не так ли? Для таких задач, как сжатие, шифрование, обфускация и т. д., Кодирование кажется несущественным ... нет причин испытывать проблемы, если они вам не нужны ..

user541686 30.04.2012 11:59

@Mehrdad: Ты, абсолютно, знаешь. Кодировка определяет, что делает преобразование из строки в массив байтов. Сжатие и шифрование - это разные вещи. В противном случае это все равно, что сказать, что формат изображения не имеет значения, когда вы хотите сохранить изображение в виде файла - много разных форматов изображений могут быть в порядке, но по определению должен быть задействован один.

Jon Skeet 30.04.2012 12:09

@JonSkeet: Разве ты не можешь просто сказать byte[] bytes = new byte[str.Length * sizeof(char)]; Buffer.BlockCopy(str.ToCharArray(), 0, bytes, 0, bytes.Length)? Кого волнует, какая кодировка (или если в строке вообще есть действительные символы), если вы знаете, что можете вернуть ее в той же форме, сделав обратное?

user541686 30.04.2012 12:14

@Mehrdad: Значит, это UTF-16. Это все еще кодировка - просто она естественная, используемая для внутреннего использования для char. (И вас может очень заботить тот факт, что это вдвое больше, чем должно быть, если ваша строка полностью состоит из ASCII.)

Jon Skeet 30.04.2012 12:18

@JonSkeet: Верно, но моя точка зрения в том, что простой факт, что пользователь хочет «получить байты», не означает, что ему даже нужно знать, какое «кодирование» средства вообще ... это имеет значение, только если он устный перевод их , а не просто работать с ними как с черным ящиком. (Что касается проблемы с пространством: да, это, очевидно, проблема с мог, но довольно часто, когда вам «нужны просто байты», это не имеет значения, как я предполагаю, дело было здесь. Очевидно, что выгодный знать о кодировках, но вы разве необходимость не знает о них здесь, а?)

user541686 30.04.2012 12:21

@Mehrdad: Нет, пользователю делает необходимо знать кодировку. Тот факт, что UTF-16 в некотором смысле является естественной кодировкой для .NET, не означает, что это кодировка, которую он хочет использовать. Смысл записи данных в том, чтобы их можно было прочитать снова - и для этого потребуется использовать ту же кодировку. Тот факт, что OP ссылается на «эквивалентный массив байтов», предполагает, что они не знают, что кодировки вообще существуют, и что жизненно важно понимать кодировки, если вы собираетесь преобразовывать между текстовым и двоичным представлениями.

Jon Skeet 30.04.2012 12:24

Я видел, как люди бесчисленное множество не могут правильно сохранять информацию, потому что они не понимают кодировки. По моему опыту, обучение их этой теме - гораздо лучший подход, чем использование Buffer.BlockCopy и предполагая, это то, чего они хотят.

Jon Skeet 30.04.2012 12:25

@JonSkeet: Тогда что делать, если какой-то символ в строке недействителен в кодировке, для которой вы хотите «получить байты» (возможно, потому что кто-то еще дал вам строку, и вы не несете ответственности за ее содержимое ... может быть, у него есть символы частного использования, или, может быть, они даже не сказать вам кодировку)? Использование какой-либо конкретной кодировки не имеет смысла, потому что для ваших символов может не быть никакого преобразования. Напротив, если вы просто используете метод, который я упомянул, тогда не имеет значения, действительны ли символы, потому что они в любом случае будут работать правильно.

user541686 30.04.2012 12:28

@Mehrdad: строка не кодирует имеют (или всегда UTF-16). Если он читается из UTF-8, он все равно попадает в UTF-16 внутри. Дело не в том, что ваш метод не использует кодировку - дело в том, что это скрытый, что IMO плохо. Очевидно, вам нужно использовать кодировку соответствующий, но просто попытаться отмахнуться от проблемы, как если бы ее не было, - действительно, очень плохая идея, ИМО. Сохранение незнания кодировок - это нет путь вперед. Если вы хотите использовать UTF-16, сделайте это явно (Encoding.Unicode).

Jon Skeet 30.04.2012 12:42

@JonSkeet: Я не понимаю вашего комментария «Строка не имеет кодировки (или всегда UTF-16)» ... эти двое идут друг против друга. Должен ли System.String всегда содержать UTF-16? Если на то пошло, должен это подчиняется какой-то другой конкретной кодировке?

user541686 30.04.2012 12:48

@Mehrdad: Это всегда последовательность char, которая сама по себе является единицей кода UTF-16. (Обратите внимание, что это не кодовая точка Unicode.) Но бессмысленно говорить, например, о «строке UTF-8». У вас может быть «представление строки в кодировке UTF-8» (которое будет массивом байтов), но это другое дело.

Jon Skeet 30.04.2012 12:49

@JonSkeet: Я не понимаю. Если вы утверждаете, что string всегда должен содержать действительные данные UTF-16, то это неверно ("\uFFFF\uFFFF"). И если вы утверждаете, что не обязательно содержит действительные данные UTF-16 и что он может представлять данные в более, чем одна возможная кодировка, тогда я прошу вопрос: какой смысл использовать Encoding.XXX.GetBytes() в строке, когда вы не Не знаете, какую кодировку использовать? (Это не похоже на то, что люди дают вам кодировку для каждого отдельного объекта string, который они передают вам ...)

user541686 30.04.2012 12:58

@Mehrdad: Это зависит от того, что вы имеете в виду под словом «действительный». По определению, он всегда содержит кодовые единицы UTF-16. Конечно, им не нужно сопоставляться с определенными символами Unicode ... но они по-прежнему UTF-16. Поэтому, если вы хотите представить какое-то значение в частном диапазоне, вы делаете это в UTF-16, а затем конвертируете в кодировку UTF-8 (или любую другую) те же символы частного диапазона позже. Если вы не знаете, какую кодировку использовать, вы вообще преобразуете не следует в байты. Это все равно, что просить сохранить изображение без указания формата изображения - просто скажите «нет».

Jon Skeet 30.04.2012 13:51

@JonSkeet: Извините, это из будущего, не знаю, как я пропустил комментарий ... но имеет смысл зашифровать / сжать строку для транспортировки / хранения, не зная (или не заботясь), какую кодировку использовать. Кодирование вообще не нужно задействовать во многих подобных сценариях.

user541686 18.01.2013 07:08

@Mehrdad: Можно сжимать, а затем распаковывать какое-то двоичное представление строки, не зная, в какой кодировке оно используется. нет отлично подходит для обработки сжатых двоичных данных, как если бы это был текст. Каждый раз, когда вы хотите преобразовать строку в двоичную или наоборот, вы должен знаете, какую кодировку использовать, и будете согласованы в обоих направлениях.

Jon Skeet 18.01.2013 11:05

@JonSkeet: Да, это именно то, что я сказал, верно? Пока вы не пытаетесь интерпретировать байтов, вам не нужно беспокоиться о кодировке. :)

user541686 18.01.2013 11:18

@Mehrdad: Но кто-то будет интерпретировать байты позже. Вы правы в том, что часть сжатия / шифрования не нуждается в заботе, но то, что позже превратит ее обратно в строку, обязательно ... и если никто Когда-либо не будет интерпретировать данные, там не так много точка в том, чтобы быть там. Так что да, вам все равно нужно выбрать кодировку и убедиться, что она используется последовательно. Какую кодировку вы решите использовать, является произвольной в некотором роде, если она может кодировать весь ваш текст, хотя это повлияет на пространство и т. д. Произвольная - это не то же самое, что и нерелевантная.

Jon Skeet 18.01.2013 11:25

@JonSkeet: Итак, вы говорите, что я должен выбираю кодировку, если, например, все, который я делаю, конвертирую string в byte[], сжимаю его и записываю в файл, чтобы завтра я мог прочитать его в byte[] и распаковать его в string на той же машине? Если так, я нахожу это заявление немного шокирующим - почему кодировка имеет значение? Да, завтра я «интерпретирую» строку, но какое значение имеет кодировка? Единственное, что имеет значение, это то, что я возвращаю то, с чего начал ... и все.

user541686 18.01.2013 11:28

@Mehrdad: Да, конечно. Так же, как вы должен выбираете формат изображения, если хотите сохранить изображение на диск. Используйте эту аналогию, насколько можете. Строки не состоят из байтов (концептуально), поэтому для преобразования байтов к вы должны пройти какое-то преобразование ... и это именно кодировка.

Jon Skeet 18.01.2013 11:33

@JonSkeet: Э ... да, это должен проходит через преобразование немного, это правда по определению. Но ты не обязательно для забота, какое конкретное преобразование является, пока черный ящик может декодировать байты за вас. Верно? Я чувствую, что это должно быть очевидно ... зачем вам все равно, что такое внутри в коробке (конкретная кодировка)? Итак, вам не нужно знать что-нибудь о как, он работает (или какое слово "кодировка" даже средства!) ... все вам нужен, это byte[] GetBytes(string) и string GetString(byte[]), и все! И это то, что делает BitConverter, никаких проблем с кодированием.

user541686 18.01.2013 11:38

Другими словами, для человека должно быть вполне возможно и законно знать ничего такого о кодировках (и никогда не необходимость to) и запрашивать «представление byte[]» строки, если он никогда не собирается интерпретировать байтов. Это все, что я говорю - ответ, в котором для преобразования используется BitConverter (или что-то подобное), легко справился бы с этой задачей, и он бы сделал это без упоминания слова «кодировка» ни разу - так что на самом деле кодировка не является Это то, о чем OP должен должен беспокоиться.

user541686 18.01.2013 11:42

@Mehrdad: Кодировка является - черный ящик. Есть много черных ящиков на выбор (разные кодировки). Вам не нужно ничего знать о внутреннем устройстве, но вам нужно выбрать одно и то же преобразование в обоих направлениях. Ответ с использованием BitConverter все еще выбирает кодировку - он просто предпочитает не называть это так. Вы бы предпочли, чтобы я сказал: «Вам нужно выбрать преобразование строки в байты, обычно через System.Text.Encoding»? Это точно то же самое, только более коряво сказано в ИМО. Опять же, подумайте о форматах изображений: вам нужно выбрать формат для перехода от пикселей к байтам.

Jon Skeet 18.01.2013 11:44

Важным моментом является то, что пользователь не может запрашивать представление вbyte[], потому что доступно множество различных опций.

Jon Skeet 18.01.2013 11:45

@JonSkeet: «Вы бы предпочли, если бы я сказал:« Вам нужно выбрать преобразование строки в байты, обычно через System.Text.Encoding »» - Да! Точно: если бы вы сказали это, то пользователю нужно было бы знать ничего такого о Unicode, чтобы достичь своей цели! Это - ключевое различие между Text.Encoding и BitConverter - один из них предназначен для случаев, когда делать заботится о кодировке, а другой - для случаев, когда кодирование на 100% не имеет отношения к вашей цели. Вот почему я здесь прокомментировал: вы сказали OP потребности знать о Unicode, когда на самом деле это не имеет значения (просто используйте BitConverter).

user541686 18.01.2013 11:45

@Mehrdad: Использование BitConverter по-прежнему означает выбор, просто не осознавая, что есть варианты являются. (Кроме того, я не могу найти, какой метод BitConverter вы имеете в виду, если честно.) Опять же, подумайте о версии изображения: если бы кто-то спросил вас, как сохранить изображение на диск, вы бы не задались естественным вопросом о том, какой формат? Я не понимаю, почему для кого-то должно быть спорным знание довольно простой разницы между байтами и символами и возможность выбирать разные кодировки. Не похоже, что они должны воплощать в жизнь их.

Jon Skeet 18.01.2013 11:50

@JonSkeet: Ой, извиняюсь за упоминание BitConverter, я имел в виду System.Buffer.BlockCopy, который может копировать любой примитивный массив (например, char[]) в byte[] и наоборот ... Я думал не о том классе, извините за то, что сбил вас с толку.

user541686 18.01.2013 11:52

@JonSkeet: Что касается задачи с изображением: это то же самое. Если BlockCopy может выполнять кодирование / декодирование в вашем классе Picture, тогда вам нужно знать ничего такого о различных форматах изображений (или даже их существование), чтобы достичь того, что вам нужно, если вы никогда не собираетесь использовать устный перевод байтов самостоятельно. . Нет необходимости говорить пользователю, что он хочет узнать о BMP. Это гораздо меньшее препятствие, которое нужно преодолеть (вообще-то, нет), чем изучение Unicode!

user541686 18.01.2013 11:53

У вас есть пример класса изображений .NET, который мог обрабатывает Buffer.BlockCopy? Вам не нужно знать много о Unicode, хотя, очевидно, чем больше, тем лучше. Но вам делать нужно сделать выбор. Если вы хотите написать класс StringConverter, который скрывает этот выбор, а всегда использует Encoding.UTF8 (или что-то еще), тогда продолжайте - но вы все равно делаете выбор, и я не думаю, что кому-то действительно выгодно скрывать его. Рано или поздно вы обязательно столкнетесь с ситуацией, когда вам нужно понять самые основы кодирования, так почему бы не научиться раньше, чем позже?

Jon Skeet 18.01.2013 12:20

@Mehrdad, позволяя черному ящику произвольно выбирать кодировку и особенно полагаясь на лежащее в основе .net представление строки в UTF-16, вы вводите будущие потенциальные ошибки. Что, если следующее обновление системы .net изменит способ представления строк в памяти? Например, вместо Little-Endian это может быть Big-Endian. Предположим, мы конвертируем строку в массив байтов, а затем сжимаем ее. После нескольких месяцев и обновления .net мы пытаемся распаковать и преобразовать обратно в строку. Но на этот раз будет фигня! Все потому, что кодировка явно не указана.

Thanasis Ioannidis 27.06.2018 14:53

@ThanasisIoannidis: Прошло 5 лет, но, оглядываясь назад, кажется, что я довольно ясно дал понять, что нужно ли указывать кодировку или нет, зависит от того, что именно вы пытаетесь сделать. И обратите внимание, что это нет, «позволяющий черному ящику выбирать кодировку». BlockCopy нигде не решает какую-либо кодировку, и в этом суть. например Если вам нужна передача без потерь в идентичной системе, вы должны использовать необработанные байты независимо от того, действительны ли они в соответствии с какой-либо конкретной кодировкой. OTOH, если вам нужна совместимость, вы кодируете / декодируете.

user541686 27.06.2018 15:06

@Mehrdad при условии, что в первую очередь есть необработанные байты. Бывает, что .net реализует строки с базовым массивом символов, но это детали реализации. Даже между идентичными системами никто не гарантирует, что будет базовый массив для получения необработанных байтов. Он может легко превратиться в связанный список или любую другую структуру данных (маловероятно, но все же вы поняли). Тем не менее, вам нужно будет указать способ преобразования этой строки (с этой странной базовой реализацией) в последовательность байтов, и этот способ преобразования из строки в байт называется кодировкой.

Thanasis Ioannidis 27.06.2018 15:23

@ThanasisIoannidis: Прежде всего, C# позволяет закрепить строку и напрямую обращаться к основным символам, так что вы сразу ошибаетесь. Во-вторых, даже если бы это было не так, связанный список (или что-то еще) ничего бы не изменил. Какой бы ни была основная реализация, у вас есть Buffer.BlockCopy() и string.ToCharArray, которые дают вам необработанные байты, которые можно использовать для идеальной реконструкции. Посылают ли они кого-нибудь, чтобы подняться на Эверест и передать персонажей по радио на Луну и обратно, зависит от структуры, а не от вашего дела, и это совершенно не имеет значения.

user541686 27.06.2018 15:28

@ThanasisIoannidis: Представьте, что вы пишете коммуникационную библиотеку для вашей программы, которая работает на двух машинах, возможно, с API void Send(string), string Receive(). Вы действительно должен иметь возможность передавать string сам по себе точно так же, как вы передаете char[] или byte[]. На самом деле ваша библиотека не касается, является ли этот string UTF-16LE, UTF-16BE или иначе. Это могут быть совершенно случайные единицы кода для всего, что вам нужно. Ваша библиотека может и должна выполнять свою работу по передаче без потерь в любом случае. И предполагать, что внутреннее кодирование не просто необходимо; это теряет информацию.

user541686 27.06.2018 15:31

@Mehrdad, что касается массива символов, это не массив байтов, пока к нему не применяется тип кодирования немного. BlockCopy выполняет эту кодировку в вашем случае, даже если эта кодировка - это просто копирование памяти каждого байта массива char. Это не обязательно должен быть один из System.Text.Encodings (чтобы не потерять информацию). Какой бы способ вы ни использовали для получения массива байтов, это кодировка. Контракт о том, как получить byte [] из строки. Если упомянутая вами библиотека предназначена для преобразования туда и обратно в одной и той же или идентичных системах, да, вам не нужно указывать кодировку. Библиотека сделает это за вас.

Thanasis Ioannidis 27.06.2018 15:53

Но даже с той же библиотекой, если она полагается на базовую реализацию, могут появиться ошибки. Вы не можете гарантировать, что система будет идентична при декодировании. Что, если .net изменится с Little-Endian на Big-Endian на принимающей части передачи? ToCharArray будет кодировать в Little-Endian, а FromCharArray на принимающей части будет использовать Big-Endian, что приведет к повреждению данных. Очевидно, ваш путь - это способ конвертировать string в byte[] в .net. Но явное указание кодировки - это еще один способ преобразования string в byte[], который кажется более надежным.

Thanasis Ioannidis 27.06.2018 15:54

@ThanasisIoannidis: Вопрос в том, что кто предоставляет контракт какие и должен ли вызываемый абонент заботиться об этом или нет. Но в этот момент вы просто повторяете себя. Мне нечего добавить. Не стесняйтесь двигаться дальше.

user541686 27.06.2018 16:08

не могли бы вы увидеть мой вопрос, связанный с этим?

Moeez 19.05.2020 07:34

@Faisal: пожалуйста, не используйте комментарии к старым вопросам (в данном случае более десяти лет назад), чтобы привлечь внимание к новому вопросу, если только конкретно нового вопроса не вышло из обсуждения в существующих комментариях.

Jon Skeet 19.05.2020 10:22

Другие вопросы по теме