副标题#e#
由于流是单向的,简单文件写可使用FileOutputStream,而读文件则使用FileInputStream。
任何数据输出到文件都是以字节为单位输出,包括图片、音频、视频。以图片为例,如果没有图片格式解析器,那么图片文件其实存储的就只是按某种格式存储的字节数据罢了。
FileOutputStream指文件字节输出流,用于将字节数据输出到文件,仅支持顺序写入、支持以追加方式写入,但不支持在指定位置写入。
打开一个文件输出流并写入数据的示例代码如下。
public class FileOutputStreamStu{
public void testWrite(byte[] data) throws IOException {
try(FileOutputStream fos = new FileOutputStream("/tmp/test.file",true)) {
fos.write(data);
fos.flush();
}
}
}
注意,如果不指定追加方式打开流,new FileOutputStream时会导致文件内容被清空,而FileOutputStream的默认构建函数是以非追加模式打开流的。
FileOutputStream的参数1为文件名,参数2为是否以追加模式打开流,如果为true,则字节将写入文件的尾部而不是开头。
调用flush方法目的是在流关闭之前清空缓冲区数据,实际上使用FileOutputStream并不需要调用flush方法,此处的刷盘指的是将缓存在JVM内存中的数据调用系统函数write写入。如BufferedOutputStream,在调用BufferedOutputStream方法时,如果缓存未满,实际上是不会调用系统函数write的,如下代码所示。
public class BufferedOutputStream extends FilterOutputStream {
public synchronized void write(byte b[], int off, int len) throws IOException {
if (len >= buf.length) {
flushBuffer();
out.write(b, off, len);
return;
}
if (len > buf.length – count) {
flushBuffer();
}
System.arraycopy(b, off, buf, count, len); // 只写入缓存
count += len;
}
}
FileInputStream
FileInputStream指文件字节输入流,用于将文件中的字节数据读取到内存中,仅支持顺序读取,不可跳跃读取。
打开一个文件输入流读取数据的案例代码如下。
public class FileInputStreamStu{
public void testRead() throws IOException {
try (FileInputStream fis = new FileInputStream("/tmp/test/test.log")) {
byte[] buf = new byte[1024];
int realReadLength = fis.read(buf);
}
}
}
其中buf数组中下标从0到realReadLength的字节数据就是实际读取的数据,如果realReadLength返回-1,则说明已经读取到文件尾并且未读取到任何数据。
当然,我们还可以一个字节一个字节的读取,如下代码所示。
public class FileInputStreamStu{
public void testRead() throws IOException {
#p#副标题#e#
try (FileInputStream fis = new FileInputStream("/tmp/test/test.log")) {
int byteData = fis.read(); // 返回值取值范围:[-1,255]
if (byteData == -1) {
return; // 读取到文件尾了
}
byte data = (byte) byteData;
// data为读取到的字节数据
}
}
}
至于读取到的字节数据如何使用就需要看你文件中存储的是什么数据了。
如果整个文件存储的是一张图片,那么需要将整个文件读取完,再按格式解析成图片,而如果整个文件是配置文件,则可以一行一行读取,遇到\n换行符则为一行,代码如下。
public class FileInputStreamStu{
@Test
public void testRead() throws IOException {
try (FileInputStream fis = new FileInputStream("/tmp/test/test.log")) {
ByteBuffer buffer = ByteBuffer.allocate(1024);
int byteData;
while ((byteData = fis.read()) != -1) {
if (byteData == '\n') {
buffer.flip();
#p#副标题#e##p#分页标题#e#
String line = new String(buffer.array(), buffer.position(), buffer.limit());
System.out.println(line);
buffer.clear();
continue;
}
buffer.put((byte) byteData);
}
}
}
}
Java基于InputStream、OutputStream还提供了很多的API方便读写文件,如BufferedReader,但如果懒得去记这些API的话,只需要记住FileInputStream与FileOutputStream就够了。