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

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

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

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

вопрос задан 23.01.2009
Agnel Kurian
27094 репутация

38 ответов


  • 1731 рейтинг

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

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

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

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

    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);
    }
    

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

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

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

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

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

    ответ дан Mehrdad, с репутацией 124482, 30.04.2012
  • 1059 рейтинг

    Это зависит от кодировки вашей строки ( 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 Framework использует UTF-16 для представления строк, так что если вы просто хотите получить точные байты, которые. NET использует, используйте System.Text.Encoding.Unicode.GetBytes (...).

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

    ответ дан bmotmans, с репутацией 13370, 23.01.2009
  • 250 рейтинг

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

    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);
    

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

    ответ дан Erik A. Brandstadmoen, с репутацией 7902, 30.04.2012
  • 106 рейтинг
    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());
    
    ответ дан Michael Buen, с репутацией 30527, 23.01.2009
  • 82 рейтинг

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

    Джоэл имеет сообщение на это:

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

    ответ дан Zhaph - Ben Duguid, с репутацией 23779, 23.01.2009
  • 77 рейтинг

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

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

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

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

    Конкретная потребность

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

    Он не хочет никакого преобразования.

    Из C # spec :

    Обработка символов и строк в C # использует кодировку Unicode. Чарс тип представляет кодовую единицу 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 #:

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

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

    ответ дан Tom Blodget, с репутацией 15565, 2.12.2013
  • 37 рейтинг

    Просто чтобы продемонстрировать, что звук Мехрадра ответ работает, его подход может даже сохранить непарных суррогатных персонажей (из которых многие выровнялись против моего ответа, но в которых все одинаково виновны, например. г. 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
    

    Попробуйте это с системой . Текст. Кодирование. UTF8. Система GetBytes или . Текст. Кодирование. Unicode. GetBytes , они просто заменят старшие суррогатные символы значением fffd

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

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

    !!

    ответ дан Michael Buen, с репутацией 30527, 30.04.2012
  • 36 рейтинг

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

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

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

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

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

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

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

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

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

    ответ дан Joel Coehoorn, с репутацией 299287, 23.01.2009
  • 36 рейтинг

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

    System.Text.Encoding.UTF8.GetBytes("TEST String");
    
    ответ дан Nathan, с репутацией 501, 25.07.2011
  • 22 рейтинг

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

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

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

    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);
    }
    
    ответ дан Gman, с репутацией 1040, 10.03.2011
  • 19 рейтинг

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

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

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

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

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

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

    ответ дан Konamiman, с репутацией 41692, 16.07.2009
  • 18 рейтинг

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

    public static byte[] StrToByteArray(string str)
    {
       System.Text.UTF8Encoding  encoding=new System.Text.UTF8Encoding();
       return encoding.GetBytes(str);
    }
    
    ответ дан Shyam sundar shah, с репутацией 1862, 5.06.2013
  • 16 рейтинг
    byte[] strToByteArray(string str)
    {
        System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding();
        return enc.GetBytes(str);
    }
    
    ответ дан gkrogers, с репутацией 6813, 23.01.2009
  • 15 рейтинг

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

    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);
    
    ответ дан Jarvis Stark, с репутацией 503, 9.09.2014
  • 11 рейтинг

    Я не уверен, но я думаю, что строка хранит информацию в виде массива символов, что неэффективно с байтами В частности, определение 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, но это будет неэффективно с пространством хранения.

    ответ дан Ed Marty, с репутацией 34936, 23.01.2009
  • 9 рейтинг

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

    Utf8 - это популярная кодировка, она компактна и без потерь.

    ответ дан Hans Passant, с репутацией 772347, 23.01.2009
  • 8 рейтинг

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

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

    РЕДАКТИРОВАТЬ Как прокомментировал Макотосан, теперь это лучший способ:

    Encoding.UTF8.GetBytes(text)
    
    ответ дан Sunrising, с репутацией 1103, 22.03.2010
  • 7 рейтинг

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

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

    Результат:

    [0] = 115
    [1] = 116
    [2] = 114
    [3] = 105
    [4] = 110
    [5] = 103
    
    ответ дан mashet, с репутацией 508, 22.10.2013
  • 5 рейтинг

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

    string s_unicode = "abcéabc";
    byte[] utf8Bytes = System.Text.Encoding.UTF8.GetBytes(s_unicode);
    
    ответ дан Shyam sundar shah, с репутацией 1862, 2.09.2013
  • 4 рейтинг

    С появлением Span выпущен с C # 7. 2, канонический метод для захвата основного представления памяти строки в массиве управляемых байтов:

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

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

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

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

    Обратите внимание, что работа с Span требует установки системы . Память NuGet .

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

    ответ дан John Rasch, с репутацией 46839, 10.01.2018
  • 4 рейтинг

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

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

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

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

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

    "Why is there a dependency on character encodings?"
    

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

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

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

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


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

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

    ответ дан Gerard ONeill, с репутацией 2236, 18.08.2015
  • 3 рейтинг

    Вот моя небезопасная реализация преобразования 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;
    }
    

    Это намного быстрее, чем принятый ответ, даже если не так элегантно, как это. Вот мои тесты секундомера за 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
        }
    }
    
    ответ дан Tommaso Belluzzo, с репутацией 17071, 15.01.2013
  • 2 рейтинг

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

    [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()
    
    ответ дан Jodrell, с репутацией 25661, 25.11.2014
  • 2 рейтинг

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

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

    РЕДАКТИРОВАТЬ: как прокомментировано ниже, это не очень хороший способ.

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

    string s = "abc"
    byte[] b = s.Cast().ToArray();
    
    ответ дан Avlin, с репутацией 397, 11.10.2012
  • 2 рейтинг

    Два пути:

    public static byte[] StrToByteArray(this string s)
    {
        List value = new List();
        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;
    }
    

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

    ответ дан Michael Buen, с репутацией 30527, 19.02.2009
  • 2 рейтинг

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

    Строка дюйма NET представляет текст как последовательность кодовых блоков UTF-16, поэтому байты кодируются в памяти уже в UTF-16.

    Ответ Мехрада

    Вы можете использовать Mehrdad's answer , но на самом деле он использует кодировку, потому что символы - UTF-16. Он вызывает ToCharArray, который при поиске источника создает char[] и копирует память в него напрямую. Затем он копирует данные в байтовый массив, который также выделяется. Таким образом, под капотом он копирует базовые байты дважды и выделяет массив символов, который не используется после вызова.

    Ответ Тома Блоджет

    Tom Blodget отвечает на 20-30% быстрее, чем Mehrdad, поскольку он пропускает промежуточный этап выделения массива char и копирования в него байтов, но требует компиляции с параметром /unsafe. Если вы абсолютно не хотите использовать кодирование, я думаю, что это путь. Если вы поместите свой логин шифрования в блок fixed, вам даже не нужно выделять отдельный массив байтов и копировать в него байты.

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

    Потому что это правильный способ сделать это. string - это абстракция.

    Использование кодировки может создать проблемы, если у вас есть «строки» с недопустимыми символами, но этого не должно происходить. Если вы вводите данные в строку с недопустимыми символами, вы делаете это неправильно. Для начала вам, вероятно, следует использовать байтовый массив или кодировку Base64.

    Если вы используете System.Text.Encoding.Unicode, ваш код будет более устойчивым. Вам не нужно беспокоиться о порядке 3515458709 системного кода, в котором будет выполняться код, по Вам не нужно беспокоиться, если в следующей версии CLR будет использоваться другая внутренняя кодировка символов.

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

    ответ дан Jason Goemaat, с репутацией 20584, 2.07.2018
  • 2 рейтинг
    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
    
    ответ дан user1120193, с репутацией 179, 2.01.2012
  • 2 рейтинг

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

    byte[] myByte= System.Text.ASCIIEncoding.Default.GetBytes(myString);
    
    ответ дан alireza amini, с репутацией 1006, 30.06.2015
  • 1 рейтинг

    Строка может быть преобразована в байтовый массив несколькими различными способами из-за следующего факта:. 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)

    Ссылка по этой ссылке.

    Для сериализации в массив байтов используется 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? :-)
    
    ответ дан Vijay Singh Rana, с репутацией 645, 11.06.2014
  • 0 рейтинг

    С byte[] по string:

            return BitConverter.ToString(bytes);
    
    ответ дан Piero Alberto, с репутацией 1806, 21.01.2015
  • 0 рейтинг

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

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

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

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

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

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

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

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

    ответ дан NH., с репутацией 744, 8.11.2017
  • -1 рейтинг

    Символ является одновременно ключом поиска в таблице шрифтов и лексической традицией, такой как упорядочение, прописные и строчные буквы и т. Д.

    Следовательно, символ не является байтом (8 бит), а байт не является символом. В частности, 256 перестановок байта не могут вместить тысячи символов в некоторых письменных языках, тем более во всех языках. Следовательно, были разработаны различные способы кодирования символов. Некоторые кодируют для определенного класса языков (кодировка ASCII); несколько языков с использованием кодовых страниц (расширенный ASCII); или, амбициозно, все языки путем выборочного включения дополнительных байтов, если необходимо, Unicode.

    Внутри системы, такой как. NET Framework, String подразумевает определенную кодировку символов. В . NET это кодировка Unicode. Поскольку платформа читает и записывает Unicode по умолчанию, в кодировке символов обычно нет необходимости. СЕТЬ.

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

    ответ дан George, с репутацией 704, 28.08.2014
  • -1 рейтинг
    // C# to convert a string to a byte array.
    public static byte[] StrToByteArray(string str)
    {
        System.Text.ASCIIEncoding  encoding=new System.Text.ASCIIEncoding();
        return encoding.GetBytes(str);
    }
    
    
    // C# to convert a byte array to a string.
    byte [] dBytes = ...
    string str;
    System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding();
    str = enc.GetString(dBytes);
    
    ответ дан cyberbobcat, с репутацией 753, 23.01.2009
  • -1 рейтинг
    string s = "abcdefghijklmnopqrstuvwxyz";
    byte[] b = new System.Text.UTF32Encoding().GetBytes(s); 
    
    ответ дан Knickerless-Noggins, с репутацией 4702, 9.04.2014
  • -1 рейтинг

    Я написал расширение Visual Basic, подобное принятому ответу, но непосредственно использующее. NET память и Marshalling для преобразования, и он поддерживает диапазоны символов, не поддерживаемые другими методами, такими как UnicodeEncoding.UTF8.GetString или UnicodeEncoding.UTF32.GetString или даже MemoryStream and BinaryFormatter (недопустимые символы, такие как:

    ответ дан Mojtaba Rezaeian, с репутацией 2738, 11.02.2016
  • -4 рейтинг

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

    string message = "This is a message.";
    byte[] bytes = new byte[message.Length];
    for (int i = 0; i < message.Length; i++)
        bytes[i] = (byte)message[i];
    
    ответ дан IgnusFast, с репутацией 23, 21.01.2016
  • -4 рейтинг

    Вот код:

    // Input string.
    const string input = "Dot Net Perls";
    
    // Invoke GetBytes method.
    // ... You can store this array as a field!
    byte[] array = Encoding.ASCII.GetBytes(input);
    
    // Loop through contents of the array.
    foreach (byte element in array)
    {
        Console.WriteLine("{0} = {1}", element, (char)element);
    }
    
    ответ дан sagardhavale, с репутацией 1, 23.01.2013
  • -14 рейтинг

    Вопрос OP: «Как преобразовать string в массив byte в NET (C #)? "[sic]

    Вы можете использовать следующий код:

    static byte[] ConvertString (string s) {
        return new byte[0];
    }
    

    В качестве преимущества кодирование не имеет значения! Ой, подождите, это кодировка. , , это просто тривиально и с большими потерями

    ответ дан Thomas Eding, с репутацией 22142, 27.09.2013