Java - 将图像转换为Base64

24

我在将gif图像转换为base 64字符串时遇到了问题。

转换后,我的代码添加了大约100,000个“AAAAAA”,而图像实际上非常小!

这是我的代码:

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.util.ArrayList;

public class Main
{

    public static void main(String[] args)
    {
        try
        {
            FileWriter fstream = new FileWriter("./out.txt");
            BufferedWriter out = new BufferedWriter(fstream);

            File folder = new File("./flags/");
            File[] listOfFiles = folder.listFiles();

            for (int i = 0; i < listOfFiles.length; i++)
            {
                if (listOfFiles[i].isFile())
                {
                    Main.readFile(out, listOfFiles[i]);
                }
            }

            out.close();
            System.out.println("Done");
        }
        catch (Exception e) {}
    }

    public static void readFile(BufferedWriter out, File file)
    {
        try
        {
            byte[] byteArray = new byte[102400];
            FileInputStream fis = new FileInputStream(file);
            String base64String;
            int bytesRead = 0;
            while ((bytesRead = fis.read(byteArray)) != -1)
            {
                new String(byteArray, 0, bytesRead);
                base64String = Base64.encode(byteArray);
                out.write("public static ImageIcon getFlag" + file.getName() + "()");
                out.newLine();
                out.write("{");
                out.newLine();
                ArrayList<String> array = Main.cut(base64String);
                out.write("return Utils.toImage(\"" + array.get(0) + "\"");
                for (int i=1; i<array.size()-1; i++)
                {
                    out.write("<tab>+\"" + array.get(i) + "\"");
                }
                out.write("<tab>\"" + array.get(array.size() - 1) + "\");");
                out.newLine();
                out.write("}");
                out.newLine();
                out.newLine();
            }
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }

    public static ArrayList<String> cut(String in)
    {
        ArrayList<String> array = new ArrayList<String>();
        while (in.length() > 76)
        {
            array.add( in.substring(0, 77) );
            in = in.substring(77);
        }
        return array;
    }
}

基本上,它将一堆带有 base64 代码的 Java 方法写入文本文件 out.txt 中。

以下是输出结果的(一部分)示例:

return Utils.toImage("R0lGODlhEAALANUAANPTAPZva/n5AfLySPz8iYqY3O01NgoksbGZa+kYGOskJKi05vb2XZ+r4+05O"<tab>+"Pv7eO3tKPv7bZak4dSvebC76tC2iPNISPX1UMkAAMm6U/NWTeYAAF5y1LqlevNaWpSh3e7uQ+1CQt"<tab>+"gAAKOv5Vds1C1IvpGf37a/7OnTYZ6q6NGkamd71/LyPusvLvFiTEFbx9rPb/HuaczATd7eAPAAAH2"<tab>+"N2vE+PMqiYuXQUsKufJqn4jlRxUlhy+CpelFnz/PxbyH5BAAAAAAALAAAAAAQAAsAAAaQwBVnSBIY"<tab>+"jzTaZsk5OSmEKOHxCAQ8nk1zMUo9Ir8Y42Kx2Dyi5qihi1QqkxzZZtCISBS2JNILoFQDdC0WIj4UO"<tab>+"hImDBMoLjcsBi0KISI8C4kFMB0uOAgykgkOGC8LJgUFFx0IqxAKCQkGGDsjpzUDLBkZEBCvCS0YJW"<tab>+"wfBQxjAyAgDpG/OwfOBzPRANMY1dVBADsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"<tab>+"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"<tab>+"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"<tab>+"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"<tab>+"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"<tab>+"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"<tab>+"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"<tab>+"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"<tab>+"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"<tab>+"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"<tab>+"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"<tab>+"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"<tab>+"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"<tab>+"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"<tab>+"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"<tab>+"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"<tab>+"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"<tab>+"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"<tab>+"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"<tab>+"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"<tab>+"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"<tab>+"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"<tab>+"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"<tab>+"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"<tab>+"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"<tab>+"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"<tab>+"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"<tab>+"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"<tab>+"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"<tab>+"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"<tab>+"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"<tab>+"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"<tab>+"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"<tab>+"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"<tab>+"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"<tab>+"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"<tab>+"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"<tab>+"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"<tab>+"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"<tab>+"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"<tab>+"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"<tab>+"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"<tab>

谢谢。

编辑:我正在使用来自此问题的base64代码:https://dev59.com/DXRB5IYBdhLWcg3w6bYE#4265472


你能把Utils类中toImage函数的代码粘贴过来吗? - UVM
你是否获取了整个字节数组作为图像,并将其传递给Base64编码器? - Michael-O
8个回答

52
 byte[] byteArray = new byte[102400];
 base64String = Base64.encode(byteArray);

无论你在数组中实际使用多少数据,该代码都将编码102400字节。

while ((bytesRead = fis.read(byteArray)) != -1)

你需要在某处使用bytesRead的值。

此外,这种方法可能不会一次将整个文件读入数组中(它只读取I/O缓冲区中的内容),因此你的循环可能无法正常工作,最终得到的数组中可能只有部分图像数据。

我建议在这里使用Apache Commons IOUtils:

 Base64.encode(FileUtils.readFileToByteArray(file));

1
你说byte[] byteArray = new byte[102400] 只编码了那么多字节,这是不是意味着它只读取了这个大小的字节而其余的没有被读取? - sara brown
1
我在哪里可以获取Apache Common IOUtils jar文件?我有commons-io-1.4.jar。当我将其导入到eclipse并使用您的代码:Base64.encode(FileUtils.readFileToByteArray(f));时,没有这样的方法,并且我得到以下错误信息:“类型Base64中的方法encode(byte [],int)不适用于参数(byte [])”。 - Rethinavel
@RethinavelVelu Base64 不是 Commons IO 的一部分(只有 FileUtils)。请尝试使用 Commons Codec。 - Thilo
@Thilo 我已经使用了编解码器并导入了 import org.apache.commons.codec.binary.Base64; 但是问题仍然存在。FileUtils无法解析,我做错了什么? - Rethinavel
1
Base64编码Base64.encodeBase64(FileUtils.readFileToByteArray(file));或者在Java 8中使用:String encoded = Base64.getEncoder().withoutPadding().encodeToString(FileUtils.readFileToByteArray(file)); - Xdg
显示剩余3条评论

5

首先,这行代码:

while ((bytesRead = fis.read(byteArray)) != -1)

等同于

while ((bytesRead = fis.read(byteArray, 0, byteArray.length)) != -1)

因此它是从偏移量0开始向byteArray中写入,而不是从之前写入的位置开始。

你需要像这样:

int offset = 0;
int bytesRead = 0;

while ((bytesRead = fis.read(byteArray, offset, byteArray.length - offset) != -1) {
    offset += bytesRead;
}

读取数据(字节)后,您可以将其转换为Base64。

然而,存在更大的问题 - 您正在使用固定大小的数组,因此太大的文件将无法正确转换,并且代码也会因此变得更加棘手。

我建议放弃字节数组并改用类似于以下内容:

ByteArrayOutputStream buffer = new ByteArrayOutputStream();
// commons-io IOUtils
IOUtils.copy(fis, buffer);
byte [] data = buffer.toByteArray();
Base64.encode(data);

或者像Thilo一样使用FileUtils进一步压缩它。

我不理解这个,fis 是一个 FileInputStream,所以如果你从中读取,那么读取的字节应该会从流中删除,这样下一次的 read 才能获取新的字节吧? - Carlo Moretti

2

这条线

base64String = Base64.encode(byteArray);

将整个数组(102400字节)转换为Base64,而不仅仅是您读取的字节数。您需要传递它字节数。


1

new String(byteArray, 0, bytesRead); 不会修改数组。你需要使用 System.arrayCopy 将数组裁剪到实际数据大小。否则,你将处理大部分为零的102400字节。


0

迟到的 GraveDig ... 只需将您的字节数组限制为文件大小。

FileInputStream fis = new FileInputStream( file );
byte[] byteArray= new byte[(int) file.length()];

0

您可以使用文件对象来获取文件长度以初始化数组:

int length = Long.valueOf(file.length()).intValue();
byte[] byteArray = new byte[length];

0
你可以创建一个大数组,然后使用 System.arrayCopy 将其复制到一个新数组中。
        int contentLength = 100000000;
        byte[] byteArray = new byte[contentLength];

        BufferedInputStream inputStream = new BufferedInputStream(connection.getInputStream());
        while ((bytesRead = inputStream.read()) != -1)
        {
            byteArray[count++] = (byte)bytesRead;
        }

        byte[] destArray = new byte[count];
        System.arraycopy(byteArray, 0, destArray , 0, count);

destArray将包含您想要的信息


0

我知道这是一个老问题,但也许有人会发现我的代码示例有用。这段代码将文件编码为Base64,然后解码并将其保存在新位置。

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;

import org.apache.commons.codec.binary.Base64;

public class Base64Example {

    public static void main(String[] args) {

        Base64Example tempObject = new Base64Example();

        // convert file to regular byte array
        byte[] codedFile = tempObject.convertFileToByteArray("your_input_file_path");

        // encoded file in Base64
        byte[] encodedFile = Base64.encodeBase64(codedFile);

        // print out the byte array
        System.out.println(Arrays.toString(encodedFile));

        // print the encoded String
        System.out.println(encodedFile);

        // decode file back to regular byte array
        byte[] decodedByteArray = Base64.decodeBase64(encodedFile);

        // save decoded byte array to a file
        boolean success = tempObject.saveFileFromByteArray("your_output_file_path", decodedByteArray);

        // print out success
        System.out.println("success : " + success);
    }

    public byte[] convertFileToByteArray(String filePath) {

        Path path = Paths.get(filePath);

        byte[] codedFile = null;

        try {
            codedFile = Files.readAllBytes(path);
        } catch (IOException e) {
            e.printStackTrace();
        }

        return codedFile;
    }

    public boolean saveFileFromByteArray(String filePath, byte[] decodedByteArray) {

        boolean success = false;

        Path path = Paths.get(filePath);

        try {
            Files.write(path, decodedByteArray);
            success = true;
        } catch (Exception e) {
            e.printStackTrace();
        }

        return success;
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接