Преобразование строки в байтовый массив в С#
Я конвертирую что-то из VB в С#. Возникла проблема с синтаксисом этого оператора:
if ((searchResult.Properties["user"].Count > 0))
{
profile.User = System.Text.Encoding.UTF8.GetString(searchResult.Properties["user"][0]);
}
Затем я вижу следующие ошибки:
Аргумент 1: невозможно преобразовать объект из объекта в байт [].
Лучший перегруженный метод соответствует System.Text.Encoding.GetString(byte []) имеет недопустимые аргументы
Я пытался исправить код, основанный на этом сообщении, но все равно безуспешно
string User = Encoding.UTF8.GetString("user", 0);
Есть предложения?
Ответы
Ответ 1
Если у вас уже есть байтовый массив, вам нужно знать, какой тип кодирования использовался для его преобразования в этот массив байтов.
Например, если массив байтов был создан следующим образом:
byte[] bytes = Encoding.ASCII.GetBytes(someString);
Вам нужно будет повернуть его обратно в строку следующим образом:
string someString = Encoding.ASCII.GetString(bytes);
Если вы можете найти в коде, который вы унаследовали, кодировку, используемую для создания массива байтов, тогда вы должны быть установлены.
Ответ 2
Прежде всего добавьте пространство имен System.Text
using System.Text;
Затем используйте этот код
string input = "some text";
byte[] array = Encoding.ASCII.GetBytes(input);
Надеюсь исправить это!
Ответ 3
Также вы можете использовать метод расширения, чтобы добавить метод к 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();
Ответ 4
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);
}
Ответ 5
var result = System.Text.Encoding.Unicode.GetBytes(text);
Ответ 6
используйте этот
byte[] myByte= System.Text.ASCIIEncoding.Default.GetBytes(myString);
Ответ 7
Следующий подход будет работать только в том случае, если символы 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;
}
Простота
Ответ 8
Основываясь на ответе Али, я бы порекомендовал метод расширения, который позволяет при желании передать кодировку, которую вы хотите использовать:
using System.Text;
public static class StringExtensions
{
/// <summary>
/// Creates a byte array from the string, using the
/// System.Text.Encoding.Default encoding unless another is specified.
/// </summary>
public static byte[] ToByteArray(this string str, Encoding encoding = Encoding.Default)
{
return encoding.GetBytes(str);
}
}
И используйте его, как показано ниже:
string foo = "bla bla";
// default encoding
byte[] default = foo.ToByteArray();
// custom encoding
byte[] unicode = foo.ToByteArray(Encoding.Unicode);
Ответ 9
Уточнение для редактирования 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;
}
}
Ответ 10
Кто-нибудь видит, почему бы не сделать это?
mystring.Select(Convert.ToByte).ToArray()
Ответ 11
На этот вопрос был дан ответ достаточно много раз, но с С# 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(...).
Ответ 12
Если результатом '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 () )
Ответ 13
Эта работа для меня, после этого я смог преобразовать свою картинку в поле bytea в моей базе данных.
using (MemoryStream s = new MemoryStream(DirEntry.Properties["thumbnailphoto"].Value as byte[]))
{
return s.ToArray();
}
Ответ 14
Вы можете использовать MemoryMarshal API для выполнения очень быстрого и эффективного преобразования. String
будет неявно приведен к ReadOnlySpan<byte>
, поскольку MemoryMarshal.Cast
принимает либо Span<byte>
, либо ReadOnlySpan<byte>
в качестве входного параметра.
public static class StringExtensions
{
public static byte[] ToByteArray(this string s) => s.ToByteSpan().ToArray(); // heap allocation, use only when you cannot operate on spans
public static ReadOnlySpan<byte> ToByteSpan(this string s) => MemoryMarshal.Cast<char, byte>(s);
}
Следующий тест показывает разницу:
Input: "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry standard dummy text ever since the 1500s,"
| Method | Mean | Error | StdDev | Gen 0 | Gen 1 | Gen 2 | Allocated |
|----------------------------- |-----------:|----------:|----------:|-------:|------:|------:|----------:|
| UsingEncodingUnicodeGetBytes | 160.042 ns | 3.2864 ns | 6.4099 ns | 0.0780 | - | - | 328 B |
| UsingMemoryMarshalAndToArray | 31.977 ns | 0.7177 ns | 1.5753 ns | 0.0781 | - | - | 328 B |
| UsingMemoryMarshal | 1.027 ns | 0.0565 ns | 0.1630 ns | - | - | - | - |