使用 Java 读取/写入二进制数据的精妙之处
Subtleties in Reading/ Writing Binary Data with Java
我注意到 Java 使用字节数组缓冲区读取文件的一个现象,就像 C 的 fread()
一样,如果我不动态控制最终读取的长度,并且正在读取的数据的总大小不是缓冲区大小的倍数,那么多余的垃圾数据可能会被读入文件。执行二进制 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 应该处理溢出读取而我的实现不知何故关闭了?简直是出乎意料。
如果我的任何陈述有误,请纠正我,如果有任何问题,请提供替代解决方案来处理问题。
您提供的代码块之间没有太大区别,只是有一些小错别字,这意味着它们无法编译。缓冲区不会被读取损坏,但如果没有为循环的每次迭代提供读取的字节数,则输出文件会损坏。
要复制文件 - 例如 src -> dst 只需使用 try with resources 和内置 transferTo
:
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);
我注意到 Java 使用字节数组缓冲区读取文件的一个现象,就像 C 的 fread()
一样,如果我不动态控制最终读取的长度,并且正在读取的数据的总大小不是缓冲区大小的倍数,那么多余的垃圾数据可能会被读入文件。执行二进制 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 应该处理溢出读取而我的实现不知何故关闭了?简直是出乎意料。
如果我的任何陈述有误,请纠正我,如果有任何问题,请提供替代解决方案来处理问题。
您提供的代码块之间没有太大区别,只是有一些小错别字,这意味着它们无法编译。缓冲区不会被读取损坏,但如果没有为循环的每次迭代提供读取的字节数,则输出文件会损坏。
要复制文件 - 例如 src -> dst 只需使用 try with resources 和内置 transferTo
:
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);