【问题标题】:Subtleties in Reading/ Writing Binary Data with Java使用 Java 读取/写入二进制数据的技巧
【发布时间】:2021-12-26 22:39:49
【问题描述】:

我注意到使用字节数组缓冲区读取 Java 文件的一个现象是,就像 C 的 fread(),如果我不动态控制最终读取的长度,并且数据的总大小正在read 不是缓冲区大小的倍数,则可能会将多余的垃圾数据读入文件。执行二进制 I/O 时,一些复制的文件会有点损坏。

垃圾值可能是先前存储在缓冲区中的值,但由于最终读取的缓冲区长度未满,因此未被覆盖。 翻看各种教程,所有读取二进制数据的方法都类似于下面的代码:

InputStream inputStream = new FileInputStream("prev_font.ttf");;
OutputStream outputStream = new FileOutputStream("font.ttf");
byte buffer[] = new byte[512];
while((read = inputStream.read(buffer)) != -1)
{
    outputStream.write(buffer, 0, read);
}
outputStream.close();
inputStream.close();

但是,在从 JAR 中打包的文件中读取输入流时,我无法正确复制该文件。我会输出为该类型的无效文件。

由于我对 JAR 访问非常陌生,因此我无法确定问题出在我的资源文件路径还是其他问题上。所以花了相当长的时间才意识到发生了什么。 我遇到的所有代码都有一个重要的缺失部分。读取量不应该是整个缓冲区,而只是读取的量:

InputStream inputStream = new FileInputStream("prev_font.ttf");
OutputStream outputStream = new FileOutputStream(font.ttf");
byte dataBuffer[] = new byte[512];
int read;
while((read = inputStream.read(dataBuffer)) != -1)
{
    outputStream.write(dataBuffer, 0, read);
}
outputStream.close();
inputStream.close();

现在一切都很好,但是为什么在任何教程中都没有提到如此重要的东西?我只是看了不好的教程,还是 Java 应该处理 oveflow 读取,而我的实现不知何故关闭了?这简直是​​出乎意料。

如果我的任何陈述有错误,请纠正我,如果有任何问题,请提供处理问题的替代解决方案。

【问题讨论】:

    标签: file-io java-io fileinputstream fileoutputstream


    【解决方案1】:

    您提供的代码块之间没有太大区别,除了一些小错别字,这意味着它们无法编译。缓冲区不会被读取损坏,但如果没有为循环的每次迭代提供读取的字节数,则输出文件会损坏。

    要复制文件 - 比如说 src -> dst 只需使用资源和内置 transferTo 的 try:

    Path src = Path.of("prev_font.ttf");
    Path dst = Path.of("font.ttf");
    try(InputStream in  = Files.newInputStream(src);
       OutputStream out = Files.newOutputStream(dst)) {
        in.transferTo(out);
    }
    

    或者调用Files的内置方法之一:

    Files.copy(src, dst);
    // or
    Files.copy(src, dst, StandardCopyOption.REPLACE_EXISTING);
    

    【讨论】:

    • 您好,很抱歉回复晚了,但感谢您对这个问题有所了解。感谢您指出文件损坏的原因。
    猜你喜欢
    • 2017-05-05
    • 2015-09-27
    • 2013-03-22
    • 2021-07-02
    • 1970-01-01
    • 1970-01-01
    • 2012-07-23
    • 2014-02-09
    • 2015-05-06
    相关资源
    最近更新 更多