#c#
#c#
Вопрос:
У меня есть программа, которая преобразует байт [] в строку шестнадцатеричного:
byte[] bytes = File.ReadAllBytes(infile);
try
{
StringBuilder sb = new StringBuilder(BitConverter.ToString(bytes)); // <--exception
hexfield.Text = sb.ToString();
}
catch(Exception e)
{
MessageBox.Show(e.ToString());
}
В большинстве случаев это работает нормально. Но когда я использую огромный файл, например, видеофайл размером 103 МБ.flv, у него заканчивается память, и он выдает исключение:
System.OutOfMemoryException: Exception of type 'System.OutOfMemoryException' was thrown.
at System.String.CtorCharArrayStartLength(Char[] value, Int32 startIndex, Int32 length)
at System.BitConverter.ToString(Byte[] value, Int32 startIndex, Int32 length)
at System.BitConverter.ToString(Byte[] value)
at shex.shexx.hexfield_Dragrop(Object sender, DragEventArgs e)**
Комментарии:
1. Что вам нужно делать с прочитанными байтами?
2. Реальный вопрос, конечно, таков: ПОЧЕМУ. Вы не можете с пользой присвоить это значение элементу управления вводом (при условии, что шестнадцатеричное поле равно одному). Вы должны просто обрезать его до полезного объема.
3. @sll с байтами или шестнадцатеричной строкой? В вопросе говорится:
"a program that converts a byte[] to a string of hex"
4. Что не так с
File.ReadAllText()
методом?5. @ShadowWizard Файл представляет собой двоичные данные, а не текст, поэтому байты в файле не должны интерпретироваться как символы в определенной кодировке, что
File.ReadAllText()
и было бы сделано.
Ответ №1:
Я бы использовал BinaryReader для чтения файла по частям и добавления каждой части в stringbuilder вместо того, чтобы читать весь файл сразу и преобразовывать его в строку.
Взгляните на эту документацию.
Ответ №2:
Ну, тогда не загружайте BitConverter.ToString
такие большие массивы. Делайте это порциями, скажем, по 1 МБ за раз.
Используйте a BinaryReader
для примера.
Ответ №3:
BitConverter.ToString
Метод сначала создает char
массив, затем создает из него строку, поэтому вам потребуется место для строки дважды в памяти.
Вы можете преобразовать данные в более мелкие фрагменты и создать StringBuilder
с начальным размером, чтобы в нем было все необходимое пространство. Таким образом, большая строка существует в памяти только один раз:
StringBuilder b = new StringBuilder(bytes.Length * 3 - 1);
int pos = 0;
while (pos < bytes.Length - 1000) {
b.Append(BitConverter.ToString(bytes, pos, 1000)).Append('-');
pos = 1000;
}
b.Append(BitConverter.ToString(bytes, pos));
hexfield.Text = b.ToString();
Однако обратите внимание на комментарий sehe о полезности такой огромной строки. На самом деле лучшим решением может быть вообще не создавать всю строку целиком.
Ответ №4:
Рассматривали ли вы, например, потоковую передачу? Это зависит от того, что вы хотите сделать с этой строкой, если вы отправляете ее, что является наиболее вероятным сценарием, когда вы можете отправлять ее небольшими порциями, для чего и предназначена потоковая передача. Некоторые реализации протокола также позволяют создавать патрон и очищать его, поэтому я бы предложил этот путь.
В вашем случае вы можете прочитать только некоторую часть файла, а затем проанализировать ее. Проверка двоичного файла, классов FileStream и потоковой передачи в целом