Как получить согласованное байтовое представление строк в С# без ручного указания кодировки?

Как преобразовать string в byte[] в .NET(С#) без указания конкретной кодировки вручную?

Я собираюсь зашифровать строку. Я могу зашифровать его без преобразования, но мне все равно хотелось бы знать, почему здесь начинается кодирование.

Кроме того, почему кодирование должно учитываться? Не могу ли я просто получить, в каких байтах хранится строка? Почему существует зависимость от кодировок символов?

1844
задан Agnel Kurian 23 янв. '09 в 16:39
источник поделиться
37 ответов
  • 1
  • 2

В отличие от ответов здесь вам НЕ нужно беспокоиться о кодировании , если, байты не нужно интерпретировать!

Как вы уже упоминали, ваша цель состоит в том, чтобы просто "получить, какие байты хранится в строке".
(И, конечно, чтобы иметь возможность перестроить строку из байтов.)

Для этих целей я честно не понимаю, почему люди продолжают говорить вам, что вам нужны кодировки. Вы, конечно, НЕ должны беспокоиться об кодировании для этого.

Просто сделайте это вместо:

static byte[] GetBytes(string str)
{
    byte[] bytes = new byte[str.Length * sizeof(char)];
    System.Buffer.BlockCopy(str.ToCharArray(), 0, bytes, 0, bytes.Length);
    return bytes;
}

static string GetString(byte[] bytes)
{
    char[] chars = new char[bytes.Length / sizeof(char)];
    System.Buffer.BlockCopy(bytes, 0, chars, 0, bytes.Length);
    return new string(chars);
}

Пока ваша программа (или другие программы) не пытается каким-то образом интерпретировать байты, о которых вы, очевидно, не упомянули, вы намереваетесь сделать, тогда в этом подходе есть nothing! Беспокойство по поводу кодировок просто делает вашу жизнь более сложной без какой-либо реальной причины.

Дополнительное преимущество для этого подхода:

Не имеет значения, содержит ли строка недопустимые символы, потому что вы все равно можете получить данные и восстановить исходную строку!

Он будет закодирован и декодирован точно так же, потому что вы просто смотрите на байты.

Если вы использовали конкретную кодировку, это могло бы вызвать проблемы с кодированием/расшифровкой недопустимых символов.

1693
ответ дан Mehrdad 30 апр. '12 в 10:44
источник поделиться

Это зависит от кодировки вашей строки (ASCII, UTF-8,...).

Например:

byte[] b1 = System.Text.Encoding.UTF8.GetBytes (myString);
byte[] b2 = System.Text.Encoding.ASCII.GetBytes (myString);

Небольшая выборка, почему кодирование имеет значение:

string pi = "\u03a0";
byte[] ascii = System.Text.Encoding.ASCII.GetBytes (pi);
byte[] utf8 = System.Text.Encoding.UTF8.GetBytes (pi);

Console.WriteLine (ascii.Length); //Will print 1
Console.WriteLine (utf8.Length); //Will print 2
Console.WriteLine (System.Text.Encoding.ASCII.GetString (ascii)); //Will print '?'

ASCII просто не оборудован для обработки специальных символов.

Внутри платформа .NET использует UTF-16 для представления строк, поэтому, если вы просто хотите получить точные байты, которые использует .NET, используйте System.Text.Encoding.Unicode.GetBytes (...).

Для получения дополнительной информации см. Кодировка символов в .NET Framework (MSDN).

1036
ответ дан bmotmans 23 янв. '09 в 16:43
источник поделиться

Принятый ответ очень, очень сложный. Используйте включенные классы .NET для этого:

const string data = "A string with international characters: Norwegian: ÆØÅæøå, Chinese: 喂 谢谢";
var bytes = System.Text.Encoding.UTF8.GetBytes(data);
var decoded = System.Text.Encoding.UTF8.GetString(bytes);

Не изобретайте велосипед, если вам не нужно...

233
ответ дан Erik A. Brandstadmoen 30 апр. '12 в 10:26
источник поделиться
BinaryFormatter bf = new BinaryFormatter();
byte[] bytes;
MemoryStream ms = new MemoryStream();

string orig = "喂 Hello 谢谢 Thank You";
bf.Serialize(ms, orig);
ms.Seek(0, 0);
bytes = ms.ToArray();

MessageBox.Show("Original bytes Length: " + bytes.Length.ToString());

MessageBox.Show("Original string Length: " + orig.Length.ToString());

for (int i = 0; i < bytes.Length; ++i) bytes[i] ^= 168; // pseudo encrypt
for (int i = 0; i < bytes.Length; ++i) bytes[i] ^= 168; // pseudo decrypt

BinaryFormatter bfx = new BinaryFormatter();
MemoryStream msx = new MemoryStream();            
msx.Write(bytes, 0, bytes.Length);
msx.Seek(0, 0);
string sx = (string)bfx.Deserialize(msx);

MessageBox.Show("Still intact :" + sx);

MessageBox.Show("Deserialize string Length(still intact): " 
    + sx.Length.ToString());

BinaryFormatter bfy = new BinaryFormatter();
MemoryStream msy = new MemoryStream();
bfy.Serialize(msy, sx);
msy.Seek(0, 0);
byte[] bytesy = msy.ToArray();

MessageBox.Show("Deserialize bytes Length(still intact): " 
   + bytesy.Length.ToString());
103
ответ дан Michael Buen 23 янв. '09 в 19:36
источник поделиться

Вам нужно учитывать кодировку, потому что 1 символ может быть представлен 1 или более байтами (до 6), а разные кодировки будут обрабатывать эти байты по-разному.

У Джоэля есть проводка по этому поводу:

Абсолютный минимум Каждый разработчик программного обеспечения Абсолютно, положительно должен знать о Unicode и наборах символов (нет оправданий!)

77
ответ дан Zhaph - Ben Duguid 23 янв. '09 в 17:03
источник поделиться

Это популярный вопрос. Важно понять, что задает автор вопроса, и что он отличается от того, что, скорее всего, является наиболее распространенной потребностью. Чтобы препятствовать неправильному использованию кода, в котором он не нужен, я ответил позже.

Общая потребность

Каждая строка имеет набор символов и кодировку. Когда вы конвертируете объект 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.

Что это для большинства обычаев. Если это вам нужно, перестаньте читать здесь. См. Статью статья Джоэл Спольски, если вы не понимаете, что такое кодировка.

Особая потребность

Теперь автор вопроса спрашивает: "Каждая строка хранится как массив байтов, правильно? Почему я не могу просто иметь эти байты?"

Он не хочет конверсии.

Из С# spec:

Обработка символов и строк в С# использует кодировку Unicode. charтип представляет собой кодовый блок UTF-16, а тип строки представляет собой последовательность кодовых блоков UTF-16.

Итак, мы знаем, что если мы попросим нулевое преобразование (т.е. от UTF-16 до UTF-16), мы получим желаемый результат:

Encoding.Unicode.GetBytes(".NET String to byte array")

Но чтобы избежать упоминания кодировок, мы должны сделать это по-другому. Если допустим промежуточный тип данных, для этого есть концептуальный ярлык:

".NET String to byte array".ToCharArray()

Это не дает нам желаемого типа данных, но Ответ Mehrdad показывает, как преобразовать этот массив Char в массив байтов, используя BlockCopy. Однако это копирует строку дважды! И он слишком явно использует кодирующий код: тип данных System.Char.

Единственный способ получить фактические байты, в которых хранится String, - это использовать указатель. Оператор fixed позволяет принимать адрес значений. Из спецификации С#:

[Для] выражения строки типа... инициализатор вычисляет адрес первого символа в строке.

Для этого компилятор пишет код, пропускающий другие части строкового объекта с помощью 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, результат зависит от точности машины. Но автор вопроса не заинтересован в этом.

74
ответ дан Tom Blodget 02 дек. '13 в 7:43
источник поделиться

Чтобы продемонстрировать, что звук Mehrdrad отвечает, его подход может даже сохраняться непарный суррогат персонажи (из которых многие выровнялись против моего ответа, но каждый из них одинаково виновен, например System.Text.Encoding.UTF8.GetBytes, System.Text.Encoding.Unicode.GetBytes; эти методы кодирования не могут сохраняться, например, с высокими суррогатными символами d800 и они просто заменяют высокие суррогатные символы значением fffd):

using System;

class Program
{     
    static void Main(string[] args)
    {
        string t = "爱虫";            
        string s = "Test\ud800Test"; 

        byte[] dumpToBytes = GetBytes(s);
        string getItBack = GetString(dumpToBytes);

        foreach (char item in getItBack)
        {
            Console.WriteLine("{0} {1}", item, ((ushort)item).ToString("x"));
        }    
    }

    static byte[] GetBytes(string str)
    {
        byte[] bytes = new byte[str.Length * sizeof(char)];
        System.Buffer.BlockCopy(str.ToCharArray(), 0, bytes, 0, bytes.Length);
        return bytes;
    }

    static string GetString(byte[] bytes)
    {
        char[] chars = new char[bytes.Length / sizeof(char)];
        System.Buffer.BlockCopy(bytes, 0, chars, 0, bytes.Length);
        return new string(chars);
    }        
}

Вывод:

T 54
e 65
s 73
t 74
? d800
T 54
e 65
s 73
t 74

Попробуйте сделать это с помощью System.Text.Encoding.UTF8.GetBytes или System.Text.Encoding.Unicode.GetBytes, они просто заменят высокие суррогатные символы значением FFFD

Каждый раз, когда в этом вопросе есть движение, я все еще думаю о сериализаторе (будь то от Microsoft или от стороннего компонента), который может сохранять строки даже в том случае, если содержит непарные суррогатные символы; Время от времени я google: сериализация непарного суррогатного символа .NET. Это не заставляет меня потерять сон, но это раздражает, когда время от времени кто-то комментирует мой ответ, что он испорчен, но их ответы одинаково ошибочны, когда дело касается непарных суррогатных персонажей.

Darn, Microsoft должна была просто использовать System.Buffer.BlockCopy в своем BinaryFormatter

谢谢!

34
ответ дан Michael Buen 30 апр. '12 в 15:50
источник поделиться

Первая часть вашего вопроса (как получить байты) уже была отвечена другими: посмотрите в пространстве имен System.Text.Encoding.

Я рассмотрю ваш следующий вопрос: почему вам нужно выбрать кодировку? Почему вы не можете получить это из самого класса строк?

Ответ состоит из двух частей.

Прежде всего, байты, используемые внутри класса string, не имеют значения, и всякий раз, когда вы предполагаете, что это так, вы, вероятно, вводите ошибку.

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

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

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

Что приводит меня ко второй части... выбор Unicode encoding говорит .Net использовать базовые байты. Вам нужно выбрать эту кодировку, потому что, когда появляется какой-то новый Unicode-Plus, среда исполнения .Net должна быть свободной, чтобы использовать эту новую, лучшую модель кодирования, не нарушая вашу программу. Но, на данный момент (и в будущем), просто выбор кодировки Unicode дает вам то, что вы хотите.

Также важно понять, что ваша строка должна быть переписана на провод, и это предполагает, по крайней мере, некоторый перевод битового шаблона, даже если вы используете подходящую кодировку. Компьютер должен учитывать такие вещи, как Big vs Little Endian, порядок сетевого байта, пакетирование, информацию о сеансе и т.д.

34
ответ дан Joel Coehoorn 23 янв. '09 в 18:54
источник поделиться

Попробуйте это, намного меньше кода:

System.Text.Encoding.UTF8.GetBytes("TEST String");
34
ответ дан Nathan 26 июля '11 в 1:52
источник поделиться

Хорошо, я прочитал все ответы, и они говорили об использовании кодировки или о сериализации, которая бросает непарные суррогаты.

Плохо, когда строка, например, исходит из SQL Server, где она была построена из массива байтов, например, хэш пароля. Если мы отбросим что-нибудь от него, он будет хранить недопустимый хеш, и если мы хотим сохранить его в XML, мы хотим оставить его неповрежденным (потому что писатель XML исключает исключение для любого непарного суррогата, который он находит).

Поэтому я использую Base64 кодировку байтовых массивов в таких случаях, но, впрочем, в Интернете есть только одно решение для этого в С#, и в нем есть ошибка, и это только один способ, поэтому я исправил ошибку и выполнил процедуру записи. Вот вы, будущие гуглеры:

public static byte[] StringToBytes(string str)
{
    byte[] data = new byte[str.Length * 2];
    for (int i = 0; i < str.Length; ++i)
    {
        char ch = str[i];
        data[i * 2] = (byte)(ch & 0xFF);
        data[i * 2 + 1] = (byte)((ch & 0xFF00) >> 8);
    }

    return data;
}

public static string StringFromBytes(byte[] arr)
{
    char[] ch = new char[arr.Length / 2];
    for (int i = 0; i < ch.Length; ++i)
    {
        ch[i] = (char)((int)arr[i * 2] + (((int)arr[i * 2 + 1]) << 8));
    }
    return new String(ch);
}
21
ответ дан Gman 10 марта '11 в 11:57
источник поделиться

Также объясните, почему кодирование следует принимать во внимание. Не могу ли я просто получить, в каких байтах хранится строка? Почему эта зависимость от кодировки?!!!

Потому что нет такой вещи, как "байты строки".

Строка (или более общий текст) состоит из символов: букв, цифр и других символов. Все это. Компьютеры, однако, ничего не знают о персонажах; они могут обрабатывать только байты. Поэтому, если вы хотите сохранить или передать текст с помощью компьютера, вам необходимо преобразовать символы в байты. Как ты это делаешь? Здесь, где на сцену выходят кодировки.

Кодировка - это не что иное, как соглашение о переводе логических символов на физические байты. Простейшей и самой известной кодировкой является ASCII, и это все, что вам нужно, если вы пишете на английском языке. Для других языков вам понадобятся более полные кодировки, поскольку любой из Unicode - самый безопасный выбор в настоящее время.

Итак, короче говоря, попытка "получить байты строки без использования кодировок" столь же невозможна, как "запись текста без использования какого-либо языка".

Кстати, я настоятельно рекомендую вам (и всем, если на то пошло) прочитать эту небольшую часть мудрости: Абсолютный минимум Каждый разработчик программного обеспечения Абсолютно, Положительно должен знать о Unicode и наборах символов (без отговорок!)

18
ответ дан Konamiman 16 июля '09 в 14:45
источник поделиться

С# для преобразования массива string в byte:

public static byte[] StrToByteArray(string str)
{
   System.Text.UTF8Encoding  encoding=new System.Text.UTF8Encoding();
   return encoding.GetBytes(str);
}
18
ответ дан Shyam sundar shah 05 июня '13 в 13:52
источник поделиться
byte[] strToByteArray(string str)
{
    System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding();
    return enc.GetBytes(str);
}
17
ответ дан gkrogers 23 янв. '09 в 16:43
источник поделиться

Вы можете использовать следующий код для преобразования между массивом строк и байтов.

string s = "Hello World";

// String to Byte[]

byte[] byte1 = System.Text.Encoding.Default.GetBytes(s);

// OR

byte[] byte2 = System.Text.ASCIIEncoding.Default.GetBytes(s);

// Byte[] to string

string str = System.Text.Encoding.UTF8.GetString(byte1);
15
ответ дан Jarvis Stark 09 сент. '14 в 14:30
источник поделиться

Я не уверен, но я думаю, что строка сохраняет свою информацию как массив Chars, который неэффективен с байтами. В частности, определение Char означает "Представляет символ Unicode".

возьмите этот пример:

String str = "asdf éß";
String str2 = "asdf gh";
EncodingInfo[] info =  Encoding.GetEncodings();
foreach (EncodingInfo enc in info)
{
    System.Console.WriteLine(enc.Name + " - " 
      + enc.GetEncoding().GetByteCount(str)
      + enc.GetEncoding().GetByteCount(str2));
}

Обратите внимание, что ответ Unicode равен 14 байтам в обоих случаях, тогда как ответ UTF-8 составляет только 9 байтов для первого и только 7 для второго.

Итак, если вы просто хотите использовать байты, используемые строкой, просто используйте Encoding.Unicode, но это будет неэффективно с объемом памяти.

11
ответ дан Ed Marty 23 янв. '09 в 17:34
источник поделиться

Ключевой проблемой является то, что глиф в строке принимает 32 бита (16 бит для символьного кода), но у байта всего 8 бит. Индивидуальное сопоставление не существует, если вы не ограничиваете себя строками, которые содержат только символы ASCII. System.Text.Encoding имеет множество способов сопоставления строки с байтом [], вам нужно выбрать ту, которая позволяет избежать потери информации, и которая проста в использовании вашим клиентом, когда ей нужно сопоставить байт [] назад к строке.

Utf8 - популярная кодировка, компактная и не потеряющая.

9
ответ дан Hans Passant 23 янв. '09 в 17:15
источник поделиться

Самый быстрый способ

public static byte[] GetBytes(string text)
{
    return System.Text.ASCIIEncoding.UTF8.GetBytes(text);
}

ИЗМЕНИТЬ как прокомментировал Макотосан, теперь это лучший способ:

Encoding.UTF8.GetBytes(text)
8
ответ дан Sunrising 22 марта '10 в 11:40
источник поделиться

Использование:

    string text = "string";
    byte[] array = System.Text.Encoding.UTF8.GetBytes(text);

Результат:

[0] = 115
[1] = 116
[2] = 114
[3] = 105
[4] = 110
[5] = 103
8
ответ дан mashet 22 окт. '13 в 15:55
источник поделиться

Вы можете использовать следующий код для преобразования string в byte array в .NET

string s_unicode = "abcéabc";
byte[] utf8Bytes = System.Text.Encoding.UTF8.GetBytes(s_unicode);
5
ответ дан Shyam sundar shah 02 сент. '13 в 14:21
источник поделиться

Ближайшим подходом к вопросу OP является Tom Blodget, который фактически входит в объект и извлекает байты. Я говорю ближе, потому что это зависит от реализации объекта String.

"Can't I simply get what bytes the string has been stored in?"

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

То, что вы хотите, это каждый символ байтов в массиве. И именно здесь происходит "кодирование". По умолчанию вы получите UTF-16LE. Если вы сами не заботитесь о самих байтах, за исключением поездки туда и обратно, вы можете выбрать любую кодировку, включая "по умолчанию", и преобразовать ее позже (при условии, что те же параметры, что и кодировка по умолчанию, кодовые точки, исправления ошибок, разрешенные вещи, такие как непарные суррогаты и т.д.

Но зачем оставлять "кодировку" до магии? Почему бы не указать кодировку, чтобы вы знали, какие байты вы получите?

"Why is there a dependency on character encodings?"

Кодирование (в этом контексте) просто означает байты, которые представляют вашу строку. Не байты строкового объекта. Вам нужны байты, в которые была сохранена строка, - вот где вопрос был задан наивно. Вам нужны байты строки в смежном массиве, которые представляют строку, а не все другие двоичные данные, которые могут содержать строковый объект.

Это означает, что сохранение строки не имеет значения. Вы хотите, чтобы строка "закодирована" в байты в массиве байтов.

Мне нравится ответ Tom Bloget, потому что он взял вас к направлению "байтов строкового объекта". Это зависит от реализации, и, поскольку он заглядывает внутрь, может быть трудно восстановить копию строки.

Ответ Mehrdad неверен, поскольку он вводит в заблуждение на концептуальном уровне. У вас все еще есть список байтов, закодированных. Его особое решение позволяет сохранить непарные суррогаты - это зависит от реализации. Его конкретное решение не создавало бы строковых байтов точно, если GetBytes по умолчанию возвратил строку в UTF-8.


Я изменил свое мнение об этом (решение Mehrdad) - это не получает байты строки; скорее, он получает байты массива символов, которые были созданы из строки. Независимо от кодирования, тип данных char в С# является фиксированным размером. Это позволяет создать массив байтов с последовательной длиной, и он позволяет воспроизводить массив символов на основе размера массива байтов. Поэтому, если кодировка была UTF-8, но каждый char составлял 6 байтов для размещения наибольшего значения utf8, он все равно работал бы. Так что действительно - кодирование персонажа не имеет значения.

Но использовалось преобразование - каждый символ помещался в поле фиксированного размера (тип символа С#). Однако какое это представление не имеет значения, что технически является ответом на ОП. Итак - если вы все равно собираетесь конвертировать... Почему бы не "закодировать"?

4
ответ дан Gerard ONeill 18 авг. '15 в 20:04
источник поделиться

Вот моя небезопасная реализация преобразования String в Byte[]:

public static unsafe Byte[] GetBytes(String s)
{
    Int32 length = s.Length * sizeof(Char);
    Byte[] bytes = new Byte[length];

    fixed (Char* pInput = s)
    fixed (Byte* pBytes = bytes)
    {
        Byte* source = (Byte*)pInput;
        Byte* destination = pBytes;

        if (length >= 16)
        {
            do
            {
                *((Int64*)destination) = *((Int64*)source);
                *((Int64*)(destination + 8)) = *((Int64*)(source + 8));

                source += 16;
                destination += 16;
            }
            while ((length -= 16) >= 16);
        }

        if (length > 0)
        {
            if ((length & 8) != 0)
            {
                *((Int64*)destination) = *((Int64*)source);

                source += 8;
                destination += 8;
            }

            if ((length & 4) != 0)
            {
                *((Int32*)destination) = *((Int32*)source);

                source += 4;
                destination += 4;
            }

            if ((length & 2) != 0)
            {
                *((Int16*)destination) = *((Int16*)source);

                source += 2;
                destination += 2;
            }

            if ((length & 1) != 0)
            {
                ++source;
                ++destination;

                destination[0] = source[0];
            }
        }
    }

    return bytes;
}

Это намного быстрее, чем принятый anwser, даже если он не такой элегантный, как есть. Вот мои тесты секундомера более 10000000 итераций:

[Second String: Length 20]
Buffer.BlockCopy: 746ms
Unsafe: 557ms

[Second String: Length 50]
Buffer.BlockCopy: 861ms
Unsafe: 753ms

[Third String: Length 100]
Buffer.BlockCopy: 1250ms
Unsafe: 1063ms

Чтобы использовать его, вы должны отметить "Разрешить небезопасный код" в своих свойствах построения проекта. В соответствии с .NET Framework 3.5 этот метод также можно использовать как расширение строки:

public static unsafe class StringExtensions
{
    public static Byte[] ToByteArray(this String s)
    {
        // Method Code
    }
}
3
ответ дан Tommaso Belluzzo 15 янв. '13 в 14:43
источник поделиться

простой код с LINQ

string s = "abc"
byte[] b = s.Select(e => (byte)e).ToArray();

EDIT: как указано ниже, это не очень хорошо.

но вы все равно можете использовать его для понимания LINQ с более подходящим кодированием:

string s = "abc"
byte[] b = s.Cast<byte>().ToArray();
2
ответ дан Avlin 11 окт. '12 в 12:45
источник поделиться

Два способа:

public static byte[] StrToByteArray(this string s)
{
    List<byte> value = new List<byte>();
    foreach (char c in s.ToCharArray())
        value.Add(c.ToByte());
    return value.ToArray();
}

и

public static byte[] StrToByteArray(this string s)
{
    s = s.Replace(" ", string.Empty);
    byte[] buffer = new byte[s.Length / 2];
    for (int i = 0; i < s.Length; i += 2)
        buffer[i / 2] = (byte)Convert.ToByte(s.Substring(i, 2), 16);
    return buffer;
}

Я предпочитаю использовать нижнюю часть чаще, чем верхнюю, не сравнивая их по скорости.

2
ответ дан harmonik 20 февр. '09 в 0:03
источник поделиться

Просто используйте это:

byte[] myByte= System.Text.ASCIIEncoding.Default.GetBytes(myString);
2
ответ дан alireza amini 30 июня '15 в 17:39
источник поделиться
bytes[] buffer = UnicodeEncoding.UTF8.GetBytes(string something); //for converting to UTF then get its bytes

bytes[] buffer = ASCIIEncoding.ASCII.GetBytes(string something); //for converting to ascii then get its bytes
2
ответ дан user1120193 02 янв. '12 в 14:07
источник поделиться

Строка может быть преобразована в массив байтов несколькими способами, из-за следующего факта:.NET поддерживает Unicode, а Unicode стандартизирует несколько разностных кодировок, называемых UTF. Они имеют различную длину байтового представления, но эквивалентны в этом смысле, что при кодировании строки он может быть закодирован обратно в строку, но если строка кодируется одним UTF и декодируется в предположении о разном UTF, если его можно навинтить вверх.

Кроме того,.NET поддерживает кодировки, отличные от Unicode, но они недействительны в общем случае (будут действительны только в том случае, если ограниченный подмножество кодовой точки Unicode используется в реальной строке, такой как ASCII). Внутренне .NET поддерживает UTF-16, но для представления потока обычно используется UTF-8. Это также стандартно-де-факто для Интернета.

Неудивительно, что сериализация строки в массив байтов и десериализация поддерживается классом System.Text.Encoding, который является абстрактным классом; его производные классы поддерживают конкретные кодировки: ASCIIEncoding и четыре UTF (System.Text.UnicodeEncoding поддерживает UTF-16)

Ref эта ссылка.

Для сериализации массива байтов с помощью System.Text.Encoding.GetBytes. Для обратной операции используйте System.Text.Encoding.GetChars. Эта функция возвращает массив символов, поэтому для получения строки используйте конструктор строк System.String(char[]).
Ссылка на эту страницу.

Пример:

string myString = //... some string

System.Text.Encoding encoding = System.Text.Encoding.UTF8; //or some other, but prefer some UTF is Unicode is used
byte[] bytes = encoding.GetBytes(myString);

//next lines are written in response to a follow-up questions:

myString = new string(encoding.GetChars(bytes));
byte[] bytes = encoding.GetBytes(myString);
myString = new string(encoding.GetChars(bytes));
byte[] bytes = encoding.GetBytes(myString);

//how many times shall I repeat it to show there is a round-trip? :-)
1
ответ дан Vijay Singh Rana 11 июня '14 в 14:29
источник поделиться

Если вам действительно нужна копия базовых байтов строки, вы можете использовать такую ​​функцию, как следующая. Однако вы не должны читать, чтобы узнать, почему.

[DllImport(
        "msvcrt.dll",
        EntryPoint = "memcpy",
        CallingConvention = CallingConvention.Cdecl,
        SetLastError = false)]
private static extern unsafe void* UnsafeMemoryCopy(
    void* destination,
    void* source,
    uint count);

public static byte[] GetUnderlyingBytes(string source)
{
    var length = source.Length * sizeof(char);
    var result = new byte[length];
    unsafe
    {
        fixed (char* firstSourceChar = source)
        fixed (byte* firstDestination = result)
        {
            var firstSource = (byte*)firstSourceChar;
            UnsafeMemoryCopy(
                firstDestination,
                firstSource,
                (uint)length);
        }
    }

    return result;
}

Эта функция быстро доставит вам копию байтов, лежащих в основе вашей строки. Вы получите эти байты любым способом, который они кодируют в вашей системе. Эта кодировка почти наверняка является UTF-16LE, но это деталь реализации, которую вам не нужно заботиться.

Чтобы просто позвонить, безопаснее, проще и надежнее,

System.Text.Encoding.Unicode.GetBytes()

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

System.Text.Encoding.Unicode.GetString()
1
ответ дан Jodrell 25 нояб. '14 в 13:29
источник поделиться

С появлением Span<T>, выпущенного с помощью С# 7.2, канонический метод для захвата основного представления памяти строки в управляемый массив байтов:

byte[] bytes = "rubbish_\u9999_string".AsSpan().AsBytes().ToArray();

Преобразование его должно быть не стартером, потому что это означает, что вы на самом деле интерпретируете данные как-то, но ради полноты:

string s;
unsafe
{
    fixed (char* f = &bytes.AsSpan().NonPortableCast<byte, char>().DangerousGetPinnableReference())
    {
        s = new string(f);
    }
}

Имена NonPortableCast и DangerousGetPinnableReference должны дополнять аргумент, который вы, вероятно, не должны делать.

Обратите внимание, что для работы с Span<T> требуется установка пакета System.Memory NuGet.

Независимо от того, что фактический исходный вопрос и последующие комментарии подразумевают, что базовая память не "интерпретируется" (которая, как я полагаю, не изменена или не читается за пределами необходимости писать ее как есть), что указывает на то, что некоторая реализация класса Stream следует использовать вместо того, чтобы рассуждать о данных как строки вообще.

1
ответ дан John Rasch 10 янв. '18 в 23:21
источник поделиться

Это зависит от того, что вы хотите байтов FOR

Это потому, что, поскольку Тайлер так метко сказал, "Строки не являются чистыми данными, у них также есть information." В этом случае информация представляет собой кодировку, которая была принята при создании строки.

Предполагая, что у вас есть двоичные данные (а не текст), хранящиеся в строке

Это основано на комментариях OP по его собственному вопросу, и это правильный вопрос, если я понимаю подсказки OP в прецеденте.

Сохранение двоичных данных в строках, вероятно, является неправильным подходом из-за предполагаемого кодирования, упомянутого выше! Независимо от того, какая программа или библиотека хранит эти двоичные данные в string (вместо массива byte[], который был бы более уместным), он уже проиграл битву до ее начала. Если они отправляют вам байты в запросе/ответе REST или что-либо, что должно передавать строки, Base64 будет правильным подходом.

Если у вас есть текстовая строка с неизвестной кодировкой

Все остальные неверно ответили на этот неправильный вопрос.

Если строка выглядит хорошо как-есть, просто выберите кодировку (желательно, начиная с UTF), используйте соответствующую функцию System.Text.Encoding.???.GetBytes() и сообщите, кто бы вы ни отправили байты, в которые вы выбрали кодировку.

0
ответ дан NH. 08 нояб. '17 в 21:21
источник поделиться

От byte[] до string:

        return BitConverter.ToString(bytes);
0
ответ дан Piero Alberto 21 янв. '15 в 17:05
источник поделиться
  • 1
  • 2

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