Преобразование строки в байтовый массив в C #

430

Я новичок в С#. Я конвертирую что-то из VB в С#. Имея проблему с синтаксисом этого утверждения:

if ((searchResult.Properties["user"].Count > 0))
{
    profile.User = System.Text.Encoding.UTF8.GetString(searchResult.Properties["user"][0]);
}

Затем я вижу следующие ошибки:

Аргумент 1: невозможно преобразовать из 'объекта' в 'byte []'

Наилучшее перегруженное соответствие метода для 'System.Text.Encoding.GetString(byte [])' имеет некоторые недопустимые аргументы

Я попытался исправить код, основанный на этом, но все равно не успел

string User = Encoding.UTF8.GetString("user", 0);

Любые предложения?

  • 1
    Какой тип searchResult.Properties["user"][0] ? Попробуйте сначала привести его к byte[]
  • 0
    мшсаем пошел туда, куда я шел. Вы пропустили приведение к (byte[]) в searchResult?
Показать ещё 6 комментариев
Теги:
string
encoding
byte

12 ответов

660

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

Например, если массив байтов был создан следующим образом:

byte[] bytes = Encoding.ASCII.GetBytes(someString);

Вам нужно будет повернуть его обратно в строку следующим образом:

string someString = Encoding.ASCII.GetString(bytes);

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

  • 2
    Тимоти, я просмотрел код VB и не могу найти байтовый массив, как вы упомянули.
  • 0
    Каков тип свойства Properties в результатах поиска?
Показать ещё 7 комментариев
77

Прежде всего добавьте пространство имен System.Text

using System.Text;

Затем используйте этот код

string input = "some text"; 
byte[] array = Encoding.ASCII.GetBytes(input);

Надеюсь исправить это!

34

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

static class Helper
{
   public static byte[] ToByteArray(this string str)
   {
      return System.Text.Encoding.ASCII.GetBytes(str);
   }
}

И используйте это как ниже:

string foo = "bla bla";
byte[] result = foo.ToByteArray();
  • 5
    Я бы переименовал этот метод, чтобы включить тот факт, что он использует кодировку ASCII. Что-то вроде ToASCIIByteArray . Ненавижу, когда узнаю, что какая-то библиотека, которую я использую, использует ASCII, и я предполагаю, что она использует UTF-8 или что-то более современное.
19
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);
}
  • 0
    Это не удастся для символов, попадающих в диапазон суррогатных пар. GetBytes будет иметь байтовый массив, который пропускает один нормальный символ на суррогатную пару с конца. GetString будет иметь пустые символы в конце. Единственный способ, которым это будет работать, - это если по умолчанию Microsoft использует UTF32 или если символы в диапазоне суррогатных пар не разрешены. Или я что-то не вижу? Правильный способ - «закодировать» строку в байты.
  • 0
    Правильно, для более широкого диапазона вы можете использовать что-то похожее на решение # Тимоти Рэндалла: using System; использование System.Text; namespace Example {открытый класс Program {public static void Main (string [] args) {string s1 = "Hello World"; string s2 = "שלום עולם"; строка s3 = "你好 , 世界!"; Console.WriteLine (Encoding.UTF8.GetString (Encoding.UTF8.GetBytes (S1))); Console.WriteLine (Encoding.UTF8.GetString (Encoding.UTF8.GetBytes (с2))); Console.WriteLine (Encoding.UTF8.GetString (Encoding.UTF8.GetBytes (s3))); }}}
14
var result = System.Text.Encoding.Unicode.GetBytes(text);
  • 1
    Это должен быть принятый ответ, так как другие ответы предполагают ASCII, но кодировка - это Unicode (это UTF16) или UTF8.
10

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

byte[] myByte= System.Text.ASCIIEncoding.Default.GetBytes(myString);
9

Следующий подход будет работать только в том случае, если символы 1 байт. (Unicode по умолчанию не работает, так как он равен 2 байтам)

public static byte[] ToByteArray(string value)
{            
    char[] charArr = value.ToCharArray();
    byte[] bytes = new byte[charArr.Length];
    for (int i = 0; i < charArr.Length; i++)
    {
        byte current = Convert.ToByte(charArr[i]);
        bytes[i] = current;
    }

    return bytes;
}

Простота

  • 0
    char и string являются UTF-16 по определению.
  • 0
    Да, по умолчанию используется UTF-16. Я не делаю никаких предположений о кодировании входной строки.
Показать ещё 4 комментария
6

Уточнение для редактирования JustinStolle (использование блоком BlockCopy Эраном Йогевым).

Предлагаемое решение действительно быстрее, чем использование Encoding. Проблема в том, что он не работает для кодирования байтовых массивов неравномерной длины. Как указано, он вызывает исключение из-за границы. Увеличение длины на 1 оставляет конечный байт при декодировании из строки.

Для меня возникла необходимость, когда я хотел кодировать от DataTable до JSON. Я искал способ кодирования двоичных полей в строки и декодирования из строки обратно в byte[].

Поэтому я создал два класса: один, который обертывает вышеупомянутое решение (при кодировании из строк это хорошо, потому что длины всегда четные), а другой, который обрабатывает byte[] кодировку.

Я решил проблему с неравномерной длиной, добавив один символ, который говорит мне, что исходная длина двоичного массива была нечетной ('1') или даже ('0')

Как следует:

public static class StringEncoder
{
    static byte[] EncodeToBytes(string str)
    {
        byte[] bytes = new byte[str.Length * sizeof(char)];
        System.Buffer.BlockCopy(str.ToCharArray(), 0, bytes, 0, bytes.Length);
        return bytes;
    }
    static string DecodeToString(byte[] bytes)
    {
        char[] chars = new char[bytes.Length / sizeof(char)];
        System.Buffer.BlockCopy(bytes, 0, chars, 0, bytes.Length);
        return new string(chars);
    }
}

public static class BytesEncoder
{
    public static string EncodeToString(byte[] bytes)
    {
        bool even = (bytes.Length % 2 == 0);
        char[] chars = new char[1 + bytes.Length / sizeof(char) + (even ? 0 : 1)];
        chars[0] = (even ? '0' : '1');
        System.Buffer.BlockCopy(bytes, 0, chars, 2, bytes.Length);

        return new string(chars);
    }
    public static byte[] DecodeToBytes(string str)
    {
        bool even = str[0] == '0';
        byte[] bytes = new byte[(str.Length - 1) * sizeof(char) + (even ? 0 : -1)];
        char[] chars = str.ToCharArray();
        System.Buffer.BlockCopy(chars, 2, bytes, 0, bytes.Length);

        return bytes;
    }
}
4

Кто-нибудь видит, почему бы не сделать это?

mystring.Select(Convert.ToByte).ToArray()
  • 7
    Convert.ToByte(char) не работает так, как вы думаете. Символ '2' преобразуется в байт 2 , а не в байт, представляющий символ '2' . mystring.Select(x => (byte)x).ToArray() используйте mystring.Select(x => (byte)x).ToArray() .
3

Если результатом 'searchResult.Properties ["user"] [0]' является строка:

if ( ( searchResult.Properties [ "user" ].Count > 0 ) ) {

   profile.User = System.Text.Encoding.UTF8.GetString ( searchResult.Properties [ "user" ] [ 0 ].ToCharArray ().Select ( character => ( byte ) character ).ToArray () );

}

Ключевым моментом является то, что преобразование строки в byte [] может быть сделано с помощью LINQ:

.ToCharArray ().Select ( character => ( byte ) character ).ToArray () )

И обратное:

.Select ( character => ( char ) character ).ToArray () )
1

На этот вопрос был дан ответ достаточно много раз, но с С# 7.2 и внедрением типа Span существует быстрый способ сделать это в небезопасном коде:

public static class StringSupport
{
    private static readonly int _charSize = sizeof(char);

    public static unsafe byte[] GetBytes(string str)
    {
        if (str == null) throw new ArgumentNullException(nameof(str));
        if (str.Length == 0) return new byte[0];

        fixed (char* p = str)
        {
            return new Span<byte>(p, str.Length * _charSize).ToArray();
        }
    }

    public static unsafe string GetString(byte[] bytes)
    {
        if (bytes == null) throw new ArgumentNullException(nameof(bytes));
        if (bytes.Length % _charSize != 0) throw new ArgumentException($"Invalid {nameof(bytes)} length");
        if (bytes.Length == 0) return string.Empty;

        fixed (byte* p = bytes)
        {
            return new string(new Span<char>(p, bytes.Length / _charSize));
        }
    }
}

Имейте в виду, что байты представляют кодированную кодировку UTF-16 (называемую "Unicode" на земле С#).

Некоторые быстрые бенчмаркинга показывают, что вышеупомянутые методы примерно в 5 раз быстрее, чем их реализации Encoding.Unicode.GetBytes(...)/GetString (...) для строк среднего размера (30-50 символов) и даже быстрее для больших строк. Эти методы также кажутся быстрее, чем использование указателей с маршалом. Копи (..) или Buffer.MemoryCopy(...).

0

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

using (MemoryStream s = new MemoryStream(DirEntry.Properties["thumbnailphoto"].Value as byte[]))
{
    return s.ToArray();
}

Ещё вопросы

Сообщество Overcoder
Наверх
Меню