在Java中读写二进制文件(看到文件的一半损坏)

6
我有一些Python的工作代码需要转换为Java。
我已经在这个论坛上阅读了很多帖子,但没有找到答案。我正在读取一个JPG图像并将其转换为字节数组。然后我将这个缓冲区写入另一个文件。当我比较Java和Python代码写入的文件时,末尾的字节不匹配。如果您有建议,请告诉我。我需要使用字节数组将图像打包到需要发送到远程服务器的消息中。
Java代码(在Android上运行)

读取文件:

File queryImg = new File(ImagePath);
int imageLen = (int)queryImg.length();
byte [] imgData = new byte[imageLen];
FileInputStream fis = new FileInputStream(queryImg);
fis.read(imgData);

写入文件:

FileOutputStream f = new FileOutputStream(new File("/sdcard/output.raw"));
f.write(imgData);
f.flush();
f.close();

谢谢!


你能更具体地说明输出有什么问题吗?它的大小是否正确;哪些字节是错误的;Python 输出与 Java 输出有何不同?Python 部分到底在做什么? - Cameron Skinner
看起来文件没有损坏。我想我错了,期望Python Windows输出与Java Android输出是位精确的。 - smitten
2个回答

5

InputStream.read 并不能保证读取任何特定数量的字节,可能会读取少于您要求的数量。它返回实际读取的字节数,因此您可以编写一个循环来跟踪进度:

public void pump(InputStream in, OutputStream out, int size) {
    byte[] buffer = new byte[4096]; // Or whatever constant you feel like using
    int done = 0;
    while (done < size) {
        int read = in.read(buffer);
        if (read == -1) {
            throw new IOException("Something went horribly wrong");
        }
        out.write(buffer, 0, read);
        done += read;
    }
    // Maybe put cleanup code in here if you like, e.g. in.close, out.flush, out.close
}

我相信Apache Commons IO有类可以完成这种操作,因此您不需要自己编写。

我仍然看到相同的问题。我打印了 FileInputStream.read 的返回值,它与文件长度相同。我无论如何都改变了我的代码,循环确保我始终读取整个文件。 - smitten
嗯。那么输出文件的大小是否正确?如果正确,有多少个字节被损坏了?是仅在文件末尾出现问题还是整个输出都有问题? - Cameron Skinner
非常准确地说,我在第757个字节看到一个错误的值。然后,在第876个字节之后,数据大多是错误的! - smitten
如果你只是在不同的地方复制数据,那么根本没有必要将数据加载到缓冲区中,除非你需要以某种方式对其进行操作。只需使用nio文件通道接口和transferTo即可。 - time4tea

0

你的文件长度可能超过了int所能容纳的范围,这样就会导致数组长度错误,因此无法将整个文件读入缓冲区。


我正在使用一个大小为6406字节的文件测试这段代码。目前,我还没有遇到这个问题。不过,我应该添加一个检查来防止这种情况发生。谢谢。 - smitten

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