首页 > 编程笔记 > Java笔记 阅读:5

Java字节的读取和写入(附带实例)

在 Java API 中,能够从中读取字节的源通常称为输入流(input stream)。这些字节可以来源于文件、网络连接或者内存中的数组。类似地,这些字节的目的地通常称为输出流(output stream)。

Java 程序中,从文件中获取流的最简单的方法是使用以下静态方法:
InputStream in = Files.newInputStream(path);
OutputStream out = Files.newOutputStream(path);
以上代码中的 path 是 Path 类的一个实例,它描述了文件系统中的路径。

Java字节的读取

InputStream 类提供了一个读取单个字节的方法:
InputStream in = ...;
int b = in.read();
这里的 read() 方法要么将字节作为一个 0~255 的整数返回,要么返回 −1 来表示已经到达输入的末尾。

Java 中的 byte 类型的取值范围是 −128~127。因此,可以在检查返回值不是 −1 之后,将其强制转换为 byte 类型。

更常见的情况是,希望批量读取字节,最简单的方法是使用 readAllBytes() 方法,该方法会将流中的所有字节读取到一个字节数组中:
byte[] bytes = in.readAllBytes();

如果需要读取文件中的所有字节,可以使用更加简便的方法,示例如下:
byte[] bytes = Files.readAllBytes(path);

如果只想读取部分字节而不是全部字节,那么可以提供一个字节数组并调用 readNBytes() 方法:
var bytes = new byte[len];
int bytesRead = in.readNBytes(bytes, offset, n);
该方法将一直读取,直到读取了 n 个字节,或没有更多的输入可用,并返回实际读取的字节数。如果没有可用的输入,该方法返回 −1。

Java 中还有一个 read(byte[], int, int) 方法,该方法的描述与 readNBytes() 方法完全相同。两者的区别在于 read() 方法只尝试读取字节,并且在读取失败时立即返回一个较小的字节数;而 readNBytes() 方法则会一直调用 read(),直到读取到所有请求的字节或 read() 返回 −1。

最后,也可以通过以下代码跳过字节:
long bytesToSkip = ...;
in.skipNBytes(bytesToSkip);

Java字节的写入

OutputStream 中的 write() 方法可以写入单个字节或字节数组:
OutputStream out = ...;
int b = ...;
out.write(b);
byte[] bytes = ...;
out.write(bytes);
out.write(bytes, start, length);

当完成流的写入操作后必须关闭该流,从而将缓冲区的输出提交。这里最好使用带资源的 try 语句来实现该功能:
try (OutputStream out = ...){
    out.write(bytes);
}

如果需要将输入流复制到输出流,可以使用 InputStream.transferTo() 方法:
try(InputStream in = ...; OutputStream out = ...){
    in.transferTo(out);
}
在调用 transferTo() 方法后,两个流都需要被关闭。这里也建议像以上示例中那样,使用带资源的 try 语句。

要将文件写入 OutputStream,可以调用:
Files.copy(path, out);

相反,如果要将 InputStream 保存到文件中,可以调用:
Files.copy(in, path, StandardCopyOption.REPLACE_EXISTING);

相关文章