GOLANG Base64 кодирует и декодирует несоответствующий размер для больших файлов

#go #base64

#Вперед #base64

Вопрос:

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

Во время моего тестирования текстовый файл не соответствовал (1 байт) новой строке, а двоичный файл не соответствовал (2 байта).

Что может быть причиной отсутствия этих байтов?

 package main

import (
    "encoding/base64"
    "io"
    "os"
    "log"
)

func Encode(infile, outfile string) error {
    input, err := os.Open(infile)
    if err != nil {
        return err
    }
    // Close input file
    defer input.Close()

    // Open output file
    output, err := os.Create(outfile)
    if err != nil {
        return err
    }
    // Close output file
    defer output.Close()

    encoder := base64.NewEncoder(base64.StdEncoding, output)
    l, err := io.Copy(encoder, input)
    if err!=nil {
        log.Printf("Failed to encode file:%v",err)
        return err
    } else {
        log.Printf("Wrote %v bytes",l)
    }

    return nil
}

func Decode(infile, outfile string) error {
    input, err := os.Open(infile)
    if err != nil {
        return err
    }
    // Close input file
    defer input.Close()

    // Open output file
    output, err := os.Create(outfile)
    if err != nil {
        return err
    }
    // Close output file
    defer output.Close()

    decoder := base64.NewDecoder(base64.StdEncoding, input)
    l, err := io.Copy(output, decoder)
    if err!=nil {
        log.Printf("Failed to encode file:%v",err)
        return err
    } else {
        log.Printf("Wrote %v bytes",l)
    }

    return nil
}
 

Ответ №1:

вы этого не Close() encoder делаете, поэтому он не удаляет все данные. из документов (выделение мое):

функция NewEncoder(enc *Encoding, w io.Запись) ввод-вывод.WriteCloser

NewEncoder возвращает новый кодировщик потока base64. Данные, записанные на возвращенный writer, будут закодированы с использованием enc, а затем записаны в w. Кодировки Base64 работают в 4-байтовых блоках; по завершении записи вызывающий должен закрыть возвращенный кодировщик, чтобы очистить все частично записанные блоки.

Я также цитирую пример из документов, в котором есть хороший комментарий:

 package main

import (
    "encoding/base64"
    "os"
)

func main() {
    input := []byte("foox00bar")
    encoder := base64.NewEncoder(base64.StdEncoding, os.Stdout)
    encoder.Write(input)
    // Must close the encoder when finished to flush any partial blocks.
    // If you comment out the following line, the last partial block "r"
    // won't be encoded.
    encoder.Close()
}