1 InputStream
InputStream是字符输入流的基类,按字符将文件或磁盘中的内容读取到内存中。
1.1 使用
InputStream 最重要的方法为 read 方法,读取磁盘内容为字节,并返回字节内容,如果读到末尾,则返回 -1 表示结束。
public abstract int read() throws IOException;1.1.1 获取流
FileInputStream 是 InputStream 提供的读取文件流的子类,可以读取这个类通过字节流获取文件内容。
public static void main(String[] args) throws IOException {
InputStream inputStream = new FileInputStream("F:\\downloade\\1.txt");
for (;;){
int read = inputStream.read(); // 反复调用read()方法,直到返回-1
if (read == -1){
break;
}
System.out.println(read); //打印byte字节
}
inputStream.close(); //关闭流1.1.2 关闭流
计算机中,流的开启会占用文件或磁盘资源,如果不关闭资源,JVM 不退出资源无法关闭,程序占用资源会越来越多,影响其他程序的运行。
InputStream 和 OutputStream 都是用 close 方法关闭流释放底层资源。
在进行 IO 操作时,如果代码过程中发生异常,会导致 close 方法无法执行,资源没有释放,所以需要对 IO 操作进行异常捕获及处理。
public static void main(String[] args) throws IOException {
InputStream inputStream = null;
try {
inputStream = new FileInputStream("F:\\downloade\\1.txt");
for (;;){
int read = inputStream.read();
if (read == -1){
break;
}
System.out.println(read);
}
} catch (IOException e) {
throw new RuntimeException(e);
}finally {
if (inputStream!= null) {
inputStream.close();
}
}
}也可以用 JDK7 的 try(resource) 语法实现:
try(InputStream inputStream1 = new FileInputStream("F:\\downloade\\1.txt")){
for (;;){
int read = inputStream1.read();
if (read == -1){
break;
}
System.out.println(read);
}
}//编译器在此处自动写入finally并调用close方法原理: 编译器会根据 try(resource) 中对象是否实现了 Closeable 接口,如果实现了该接口,就回自动加上 finally 语句并调用 close 方法。
1.2 缓冲
读取流的时候,按字节读取效率太低,很多流支持一次性将多个字符串读取到缓冲区从而提高效率。InputStream 提供了两个 read 重载方法支持多个字符读取。
- public int read(byte b[]) throws IOException;//读取若干字节并填充到
byte[]数组,并返回读取的字节数。 - public int read(byte b[], int off, int len) throws IOException;//指定
byte[]数组的偏移量和最大填充数
//缓冲流
try(InputStream inputStream2 = new FileInputStream("F:\\downloade\\1.txt")){
byte[] bytes = new byte[1024];
while (inputStream2.read(bytes) != -1){
System.out.println(new String(bytes));
}
}1.3 阻塞
InputStream 的 read 方法是阻塞的,必须完成当前读取操作后才能进行下一个语句。所以执行速度较慢,无法确定 read 方法需要执行多久。
1.4 实现类
1.4.1 FileInputStream
用 FileInputStream 可以从文件获取输入流,这是 InputStream 常用的一个实现类。
//模拟字节流
byte[] data = { 72, 101, 108, 108, 111, 33 };
try (InputStream input = new ByteArrayInputStream(data)) {
int n;
while ((n = input.read()) != -1) {
System.out.println((char)n);
}
}1.4.2 ByteArrayInputStream
此外,ByteArrayInputStream 可以在内存中模拟一个 InputStream
2 OutputStream
OutputStream(输出字节流) 与InputStream相反,是将字符从磁盘中写入到文件中。
2.1 使用
OutputStream中提供了write(int b )方法写入一个字节到输出流。
2.1.1 写入流
File file = new File("F:\\allFile\\01 temp\\1.txt");
FileOutputStream outputStream = new FileOutputStream( file);
outputStream.write(97);
outputStream.write(98);
outputStream.write(99);
//abc2.1.2 关闭流
OutputStream也需要对流进行关闭操作,防止资源被占用导致无法复用。
File file = new File("F:\\allFile\\01 temp\\1.txt");
//abc
try(FileOutputStream outputStream = new FileOutputStream(file)){
outputStream.write(97);
outputStream.write(98);
outputStream.write(99);
}2.1.3 刷新流
输出流提供了
flush()方法刷新输出流强制写出所有缓冲的输出字节。
在向磁盘、网络写入数据时,出于效率的考虑,操作系统并不是每次 write 操作后将数据写入,而是先把数据存放再缓冲区,等缓冲区域写满后再一次性将数据写入目标设备中。flsh() 方法在进行 close 操作时会自动调用,不必手动调用。
2.2 实现类
2.2.1 FileOutputStream
File file = new File("F:\\allFile\\01 temp\\1.txt");
//abcd
try(FileOutputStream outputStream = new FileOutputStream(file)){
outputStream.write("abcd".getBytes());
}2.2.2 ByteArrayOutputStream
模拟输出流,测试时使用。
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
outputStream.write(97);
outputStream.write(98);
outputStream.write(99);
System.out.println(Arrays.toString(outputStream.toByteArray()));