Подтвердить что ты не робот

Возможно ли base64-кодировать файл в кусках?

Я пытаюсь base64 кодировать огромный входной файл и заканчивать текстовым выходным файлом, и я пытаюсь выяснить, возможно ли кодировать входной файл побито, или мне нужно закодируйте всю вещь сразу.

Это будет сделано в AS/400 (iSeries), если это имеет значение. Я использую свою собственную процедуру кодирования base64 (написанную в RPG), которая отлично работает и, если бы это был не случай ограничений по размеру, было бы хорошо.

4b9b3361

Ответ 1

Невозможно побитовое, но 3 байта за раз, или кратные 3 байта в момент времени будут!.

Другими словами, если вы разделите свой входной файл на "куски", размер которого (являются) кратными 3 байтам, вы можете закодировать куски отдельно и объединить полученные в результате фрагменты, закодированные в B64 (в соответствующем orde, конечно. Обратите внимание, что последний chuink не должен быть точно кратным 3 байтам в зависимости от значения по модулю 3 его соответствующего значения B64 будет иметь несколько из этих дополняющих символов (как правило, знак равенства) но это нормально, так как это будет единственный кусок, который имеет (и нуждается) такое дополнение.

В направлении декодирования это та же идея, за исключением того, что вам нужно разбить данные, закодированные в B64, в кратном размере 4 байта. Декодируйте их параллельно/индивидуально по желанию и перекомпоновите исходные данные, добавив декодированные части вместе (снова в том же порядке).

Пример:

Содержимое "Файл" = "Never argue with the data." (Jimmy Neutron).
Прямое кодирование = Ik5ldmVyIGFyZ3VlIHdpdGggdGhlIGRhdGEuIiAoSmltbXkgTmV1dHJvbik=

Теперь, в кусках:
"Never argue   →   Ik5ldmVyIGFyZ3Vl
with the     →     IHdpdGggdGhl
data." (Jimmy Neutron)IGRhdGEuIiAoSmltbXkgTmV1dHJvbik=

Как вы видите фрагмент в этом порядке, 3 кодированных фрагмента совпадают с кодом, созданным для всего файла.

Декодирование выполняется аналогичным образом с произвольным размером chuncked при условии, что они кратны 4 байтам. Абсолютно не нужно иметь никакого соответствия между размерами, используемыми для кодирования. (хотя стандартизация до одного размера для каждого направления (скажем, 300 и 400) может сделать вещи более однородными и удобными в управлении.

Ответ 2

Хммм, если вы сами написали преобразование base64, вы должны были заметить очевидную вещь: каждая последовательность из 3 октетов представлена ​​4 символами в base64.

Таким образом, вы можете разделить данные base64 на каждый кратный четыре символа, и будет возможно преобразовать эти куски обратно в исходные биты.

Я не знаю, как файлы символов и байтовые файлы обрабатываются в AS/400, но если у них есть обе концепции, это должно быть очень просто.

  • - текстовые файлы, ограниченные длиной каждой строки?
  • являются текстовыми файлами, ориентированными на линию, или они являются просто символьными потоками?
  • Сколько битов имеет один байт?
  • - это байтовые файлы, дополненные в конце, так что можно создавать только файлы, которые охватывают целые сектора диска.

Если вы можете ответить на все эти вопросы, какие точные трудности у вас остались?

Ответ 3

Это тривиальное усилие разбивать любой заданный поток на куски.

Вы можете без проблем использовать base64 любой фрагмент байтов.

Проблема, с которой вы столкнулись, заключается в том, что, если вы не зададите конкретные требования к вашим кускам (кратные 3 байтам), последовательность блоков с кодировкой base64 будет отличаться от того, какой вы хотите.

В С# это один (неряшливый) способ сделать это лениво. Выполнение фактически отложено до тех пор, пока не будет выведена строка. Concat вызывается, поэтому вы можете делать все, что хотите, с чередующимися строками. (Если вы подключите это в LINQPad, вы увидите вывод)

void Main()
{
    var data = "lorum ipsum etc lol this is an example!!";
    var bytes = Encoding.ASCII.GetBytes(data);
    var testFinal = Convert.ToBase64String(bytes);

    var chunkedBytes = bytes.Chunk(3);
    var base64chunks = chunkedBytes.Select(i => Convert.ToBase64String(i.ToArray()));
    var final = string.Concat(base64chunks);

    testFinal.Dump(); //output
    final.Dump(); //output
}
public static class Extensions
{
    public static IEnumerable<IEnumerable<T>> Chunk<T>(this IEnumerable<T> list, int chunkSize)
    {
        while(list.Take(1).Count() > 0)
        {
            yield return list.Take(chunkSize);
            list = list.Skip(chunkSize);
        }
    }
}

Выход

bG9ydW0gaXBzdW0gZXRjIGxvbCB0aGlzIGlzIGFuIGV4YW1wbGUhIQ==
bG9ydW0gaXBzdW0gZXRjIGxvbCB0aGlzIGlzIGFuIGV4YW1wbGUhIQ==