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

StackOverflow https://stackoverflow.com/questions/1422314

  •  07-07-2019
  •  | 
  •  

Вопрос

Итак, вот в чем дело:Я пытаюсь открыть файл (из байт), преобразовать его в строку, чтобы я мог перепутать некоторые метаданные в заголовке, преобразовать их обратно в байты и сохранить.Проблема, с которой я сталкиваюсь прямо сейчас, связана с этим кодом.Когда я сравниваю строку, которая была преобразована туда и обратно (но не изменена иным образом), с исходным массивом байтов, получается неравенство.Как я могу заставить это работать?

public static byte[] StringToByteArray(string str)
{
    UTF8Encoding encoding = new UTF8Encoding();
    return encoding.GetBytes(str);
}

public string ByteArrayToString(byte[] input)
{
    UTF8Encoding enc = new UTF8Encoding();
    string str = enc.GetString(input);
    return str;
}

Вот как я их сравниваю.

byte[] fileData = GetBinaryData(filesindir[0], Convert.ToInt32(fi.Length));
string fileDataString = ByteArrayToString(fileData);
byte[] recapturedBytes = StringToByteArray(fileDataString);
Response.Write((fileData == recapturedBytes));

Я уверен, что это UTF-8, использующий:

StreamReader sr = new StreamReader(filesindir[0]);
Response.Write(sr.CurrentEncoding);

который возвращает "System.Text.UTF8Encoding".

Это было полезно?

Решение

Попробуйте статические функции на Encoding класс, который предоставляет вам экземпляры различных кодировок.Вам не нужно создавать экземпляр Encoding просто для преобразования в / из массива байтов.Как вы сравниваете строки в коде?

Редактировать

Вы сравниваете массивы, а не строки.Они неравны, потому что ссылаются на два разных массива;используя == operator будет сравнивать только их ссылки, а не их значения.Вам нужно будет проверить каждый элемент массива, чтобы определить, эквивалентны ли они.

public bool CompareByteArrays(byte[] lValue, byte[] rValue)
{
    if(lValue == rValue) return true; // referentially equal
    if(lValue == null || rValue == null) return false; // one is null, the other is not
    if(lValue.Length != rValue.Length) return false; // different lengths

    for(int i = 0; i < lValue.Length; i++)
    {
        if(lValue[i] != rValue[i]) return false;
    }

    return true;
}

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

Если у вас есть необработанные байты (8-битные символы, которые невозможно распечатать) и вы хотите манипулировать ими как строкой .NET и превратить их обратно в байты, вы можете сделать это с помощью

Encoding.GetEncoding(1252)

вместо UTF8Encoding. Эта кодировка позволяет получить любое 8-разрядное значение и преобразовать его в 16-разрядный символ .NET и обратно без потери какой-либо информации.

В описанном выше конкретном случае с двоичным файлом вы не сможете & связываться с метаданными в заголовке " и все должно работать правильно, если длина данных, с которыми вы связываетесь, не изменяется. Например, если заголовок содержит

{any}{any}ABC{any}{any}

и вы хотите изменить ABC на DEF, это должно работать так, как вы хотите. Но если вы хотите изменить ABC на WXYZ, вам придется переписать байт, следующий за & Quot; C & Quot; или вы (по сути) переместите все на один байт дальше вправо. В типичном двоичном файле это сильно испортит.

Если байты после " ABC " являются пробелами или нулевыми символами, есть большая вероятность того, что запись больших замещающих данных не вызовет проблем - но вы все равно не можете просто заменить ABC на WXYZ в строке .NET, делая его длиннее - вам придется заменить ABC {what_follows_it} с WXYZ. Учитывая это, вы можете обнаружить, что проще оставить данные в виде байтов и записать замещающие данные по одному байту за раз.

Из-за того, что в .NET-строках используются строки Unicode, вы больше не можете делать это, как это делали люди в C. В большинстве случаев вам даже не следует пытаться переходить назад и вперед от строки < ; - > байтовый массив, если только содержимое не является текстовым .

Я должен прояснить этот момент: в .NET, если данные byte [] не текст , не пытайтесь преобразовать его в строку , за исключением специальной Base64 кодировки для двоичные данные по текстовому каналу. Это широко распространенное недоразумение среди людей, работающих в .NET.

Возможно, ваша проблема заключается в том, как вы сравниваете массив байтов:

Response.Write((fileData == recapturedBytes));

Это всегда будет возвращать false, поскольку вы сравниваете адрес байтового массива, а не значения, которые он содержит. Сравните строковые данные или используйте метод сравнения байтовых массивов. Вы также можете сделать это вместо этого:

Response.Write(Convert.ToBase64String(fileData) == Convert.ToBase64String(recapturedBytes));
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top