Получение исключения OutOfMemory при преобразовании файла tif в кодировку base64

Мы создали консольное приложение на C#, где будут считываться многостраничные файлы tif/tiff, разбиваться по страницам, а затем преобразовываться в кодировку base64 для загрузки файла в другое целевое приложение (поскольку оно принимает только кодировку base64 для загрузки документов), и мы получение этого исключения из памяти всякий раз, когда размер файла превышает 500 МБ. Исключение типа «System.OutOfMemoryException» было выбрано

Exception at System.Convert.ToBase64String(Byte[] inArray, Int32 offset, Int32 length, Base64FormattingOptions options)
   at System.Convert.ToBase64String(Byte[] inArray)

Фрагмент кода:

Byte[] bytes = File.ReadAllBytes(filepath);
String base64stringofdocument = Convert.ToBase64String(bytes);

Вышеупомянутый путь к файлу относится › к абсолютному пути к файлу


person Sheik    schedule 07.08.2020    source источник
comment
Вероятно, вам придется провести анализ использования памяти. с Visual Studio, чтобы найти основную причину этого.   -  person Matthew Watson    schedule 07.08.2020
comment
Длина одного строкового объекта в .NET не может превышать 2^31-1 символов. Кодировка Base64 занимает не менее 4/3 места относительно размера ввода. Это дает вам верхнюю теоретическую границу размера файла ~ 805 МБ, хотя на практике она, вероятно, ниже. Вероятно, вы хотите сжать ввод перед преобразованием в base64.   -  person Mathias R. Jessen    schedule 07.08.2020
comment
Рассматривали ли вы потоковую передачу данных вместо чтения всего файла в память?   -  person Charleh    schedule 07.08.2020
comment
Проект › Свойства › вкладка «Сборка», снимите флажок «Предпочитать 32-разрядную версию». Вы не предпочитаете это.   -  person Hans Passant    schedule 07.08.2020
comment
@Charleh Просто обратитесь к приведенному выше фрагменту кода, конвертируя в массив байтов из файла перед переходом в кодировку base64. Как это улучшить? Пожалуйста, помогите нам   -  person Sheik    schedule 07.08.2020
comment
Приложение x86 или x64? Cosider чистая сборка x64 для расширения лимита памяти. Но определенно Streaming - это решение - этот ответ может помочь.   -  person aepot    schedule 07.08.2020


Ответы (1)


При работе со строками возникают накладные расходы. Для очень больших объемов данных вам лучше работать с массивами или потоками. В этом случае вы можете начать с переписывания кода для использования Convert.ToBase64CharArray. Таким образом, ваш код изменится на что-то вроде этого:

Byte[] bytes = File.ReadAllBytes(filePath);
// Compute the number of Base64 converted characters required (must be divisible by 4)
long charsRequired = (long)((4.0d/3.0d) * bytes.Length);
if (charsRequired % 4 != 0) {
    charsRequired += 4 - charsRequired % 4;
}
// Allocate buffer for characters, and write converted data into the array
Char[] chars = new Char[charsRequired];
Convert.ToBase64CharArray(bytes, 0, bytes.Length, chars, 0);

Затем вы можете загрузить массив chars в целевое приложение.

person Jack A.    schedule 07.08.2020
comment
Привет, Джек. Пробовал с приведенным выше предложением, но если снова преобразовать массив символов в строковый объект, может возникнуть та же проблема, поскольку целевое приложение принимает строковый объект только для загрузки документа. Есть ли лучший способ обрабатывать большие файлы. Пожалуйста, поделитесь фрагментом кода. - person Sheik; 07.08.2020
comment
@Sheik Кажется маловероятным, что ваше целевое приложение может принимать только строки .NET. Если вы отредактируете свое сообщение, включив в него код, используемый для загрузки в ваше целевое приложение, возможно, вы сможете прокомментировать его дальше. - person Jack A.; 07.08.2020
comment
После приведенных выше строк кода мы просто передадим закодированную строку base64 в вызов веб-службы целевого приложения. Ничего особенного после этого шага. - person Sheik; 07.08.2020