Java|Java 学习笔记(十一)IO 流
IO 流是有起点和终点的有序的字节序列
IO 流的分类
- 输入流和输出流
程序从外面读数据就是输入流,程序把数据保存到外面就是输出流
- 字节流和字符流
以字节为单位处理流中的数据就是字节流,以字符为单位处理流中的数据就是字符流
- 节点流和处理流
直接从设备读写数据就是节点流,处理流是对节点流的包装
FileInputStream
和 FileOutputStream
FileInputStream
流以字节为单位读取文件中的内容,FileOutputStream
流以字节为单位把数据保存到文件中。这一对流类可以读写所有格式的文件import java.io.FileInputStream;
import java.io.IOException;
/**
* FileInputStream 流的基本使用
*/
public class Test01 {
public static void main(String[] args) throws IOException {
// 通过 FileInputStream 的构造方法指定要读取的文件,文件内容:abcdef
FileInputStream fis = new FileInputStream("/Users/Desktop/test");
// 调用 available() 方法可以返回还有多少个字节未读
System.out.println(fis.available());
// 调用 read() 方法可以从文件中读取一个字节
int bb = fis.read();
System.out.println(bb);
// 调用 skip() 方法可以跳过指定的字节数
// 跳过2字节
fis.skip(2);
System.out.println(fis.available());
System.out.println(fis.read());
// 关闭流
fis.close();
}
}
输出内容:
6
97
3
100
import java.io.FileInputStream;
import java.io.IOException;
/**
* 使用 FileInputStream 流读取文件的所有字节
*/
public class Test02 {
public static void main(String[] args) throws IOException {
// 通过构造方法指定要读取的文件
FileInputStream fis = new FileInputStream("/Users/Desktop/test");
// 调用 read() 方法读取一个字节,如果读到文件末尾会返回 -1
int bb = fis.read();
while (bb != -1) {
System.out.println((char)bb);
bb = fis.read();
}// 关闭流
fis.close();
}
}
输出内容:
a
b
c
d
e
f
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Arrays;
/**
* 使用 FileInputStream 流读取文件的字节,把读取到的字节保存到字节数组中
*/
public class Test03 {
public static void main(String[] args) throws IOException {
// 通过构造方法指定要读取的文件,文件内容:abcdef
FileInputStream fis = new FileInputStream("/Users/Desktop/test");
// 调用 read(byte[] b) 方法读取若干字节存储到 bytes 数组中,返回读到的字节数
byte [] bytes = new byte[4];
int len = fis.read(bytes);
// 读取到4个字节
System.out.println(len);
// 输出结果:[97, 98, 99, 100]
System.out.println(Arrays.toString(bytes));
// 再继续读取文件
len = fis.read(bytes);
// 读取到2个字节
System.out.println(len);
// 输出结果:[101, 102, 99, 100]
System.out.println(Arrays.toString(bytes));
// 再继续读取文件
len = fis.read(bytes);
// 已经读到文件末尾,返回 -1
System.out.println(len);
// 输出结果:[101, 102, 99, 100]
System.out.println(Arrays.toString(bytes));
// 关闭流
fis.close();
}
}
import java.io.FileOutputStream;
import java.io.IOException;
/**
* FileOutPutStream 流以字节为单位把数据保存到文件中
*/
public class Test04 {
public static void main(String[] args) throws IOException {
// 调用构造方法指定要写入的文件,如果文件不存则会创建该文件
// 以覆盖的形式写入文件
//FileOutputStream fos = new FileOutputStream("/Users/Desktop/test");
// 以追加的形式写入文件
FileOutputStream fos = new FileOutputStream("/Users/Desktop/test", true);
// 调用 write(int) 方法,一次写入一个字节
fos.write(97);
fos.write(98);
fos.write(99);
// 调用 write(byte[] b) 方法,把一个字节数组的所有字节写入文件
byte [] bytes = "hello FileOutPutStream".getBytes();
fos.write(bytes);
// 调用 write(byte[] b, int off, int len) 方法,把一个字节的部分字节写入文件
fos.write(bytes, 0, 5);
// 关闭流
fos.close();
}
}
文件内容:
abchello FileOutPutStreamhello
BufferedInputStream
和 BufferedOutputStream
BufferedInputStream
缓冲输入字节流,字节流有一个8192字节的数组作为缓冲区,程序从缓冲区读取数据,不直接操作文件BufferedOutputStream
缓冲输出字节流,程序把数据写入缓冲区,再由其他字节流从缓冲区把数据写入文件BufferedInputStream
和 BufferedOutputStream
属于处理流import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;
/**
* BufferedInputStream 流读取文件
*/
public class Test01 {
public static void main(String[] args) throws IOException {
m1();
}public static void m1 () throws IOException {
// 先创建字节流,文件内容:hello
FileInputStream fis = new FileInputStream("/Users/Desktop/test");
// 再创建缓冲流对字节流进行缓冲
BufferedInputStream bis = new BufferedInputStream(fis);
// 从缓冲区中读取文件
int bb = bis.read();
while (bb != -1) {
System.out.println((char)bb);
bb = bis.read();
}// 关闭缓冲流
bis.close();
}
}
输出结果:
h
e
l
l
o
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
/**
* BufferedOutputStream 流写入文件
*/
public class Test02 {
public static void main(String[] args) throws IOException {
m2();
}public static void m2 () throws IOException {
// 先创建字节流
FileOutputStream fos = new FileOutputStream("/Users/Desktop/test");
// 再创建缓冲流
BufferedOutputStream bos = new BufferedOutputStream(fos);
// 把数据写入缓冲区
bos.write(65);
bos.write(66);
bos.write(67);
// 刷新缓冲区,把数据从缓冲区写入文件
bos.flush();
// 关闭缓冲流,直接关闭也会刷新缓冲区
bos.close();
}
}
文件内容:
ABC
DataInputStream
和 DataOutputStream
之前的 FileInputStream
流从文件中读取一组 01 二进制序列,在转换成相对应的数据,FileOutputStream
把相对应的数据转换成 01 二进制序列,再写入文件DataInputStream
流可以直接中文件中读取整数,小数,字符,字符串,布尔类型类型的数据,DataOutputStream
可以直接把整数,小数,字符,字符串,布尔类型的数据写入文件import java.io.DataOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
/**
* DataOutputStream 流把带有格式的数据写入文件
*/
public class Test01 {
public static void main(String[] args) throws IOException {
// 先创建字节流
FileOutputStream fos = new FileOutputStream("/Users/Desktop/test");
// 在创建 DataOutputStream 流
DataOutputStream dos = new DataOutputStream(fos);
// 写入文件,写入的数据直接读入会显示乱码,需要使用 DataInputStream 流来读取
dos.writeInt(123);
dos.writeDouble(3.14);
dos.writeChar('汉');
dos.writeBoolean(false);
dos.writeUTF("hello");
// 关闭流
dos.close();
}
}
import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.IOException;
/**
* DataInputStream 读取数据
*/
public class Test02 {
public static void main(String[] args) throws IOException {
// 先创建字节流
FileInputStream fis = new FileInputStream("/Users/Desktop/test");
// 再创建 DataInputStream 流
DataInputStream dis = new DataInputStream(fis);
// 读取的顺序与写入的顺序需要保持一致
int i = dis.readInt();
double d = dis.readDouble();
char c = dis.readChar();
boolean b = dis.readBoolean();
String s = dis.readUTF();
// 关闭流
dis.close();
// 输出
System.out.println(i);
System.out.println(d);
System.out.println(c);
System.out.println(b);
System.out.println(s);
}
}
输出内容:
123
3.14
汉
false
hello
ObjectInputStream
和 ObjectOutputStream
ObjectOutputStream
流把对象转换为二进制序列写入到文件,称为对象序列化ObjectInputStream
流把读取到的二进制序列转换为对象,称为对象反序列化对象序列化与反序列化的前提是对象的类要实现
Serializable
接口,这个接口是一个标志接口,没有抽象方法import java.io.Serializable;
/**
* 定义一个类
*/
public class Person implements Serializable {
String name;
int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
/**
* ObjectOutputStream 流把对象写入文件
*/
public class Test01 {
public static void main(String[] args) throws IOException {
Person p = new Person("张三", 18);
// 创建字节流
FileOutputStream fos = new FileOutputStream("/Users/Desktop/test");
// 创建 ObjectOutputStream 流
ObjectOutputStream oos = new ObjectOutputStream(fos);
// 把对象写入文件,写入文件之后,需要使用 ObjectInputStream 流读取
oos.writeObject(p);
// 关闭流
oos.close();
}
}
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
/**
* ObjectInputStream 流读取对象
*/
public class Test02 {
public static void main(String[] args) throws IOException, ClassNotFoundException {
// 创建字节流
FileInputStream fis = new FileInputStream("/Users/Desktop/test");
// 创建 ObjectInputStream 流
ObjectInputStream ois = new ObjectInputStream(fis);
// 读取对象
Object o = ois.readObject();
// 关闭流
ois.close();
// 输出
System.out.println(o);
}
}
输出内容:
Person{name='张三', age=18}
PrintStream
打印内容到文件import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintStream;
/**
* PrintStream 打印字节流
*/
public class Test01 {
public static void main(String[] args) throws FileNotFoundException {
// 创建字节流
FileOutputStream fos = new FileOutputStream("/Users/Desktop/test");
// 创建打印流
PrintStream ps = new PrintStream(fos);
// 打印字节流常用的方法,print() 和 println(),打印信息到文件中
ps.print("打印完不换行");
ps.println("打印完换行");
// 设置 system.out.println 方法,通过打印流打印到文件中
System.setOut(ps);
System.out.println("现在打印的内容不显示在屏幕上,而是打印到 test 文件中");
// 把异常信息打印到文件中
try {
FileInputStream fis = new FileInputStream("不存在的文件");
}catch (FileNotFoundException e) {
// 把异常信息打印到 test 文件中
e.printStackTrace(ps);
}// 关闭流
ps.close();
}
}
文件内容:
打印完不换行打印完换行
现在打印的内容不显示在屏幕上,而是打印到 test 文件中
java.io.FileNotFoundException: 不存在的文件 (No such file or directory)
at java.base/java.io.FileInputStream.open0(Native Method)
at java.base/java.io.FileInputStream.open(FileInputStream.java:219)
at java.base/java.io.FileInputStream.(FileInputStream.java:157)
at java.base/java.io.FileInputStream.(FileInputStream.java:112)
at printio.Test01.main(Test01.java:28)
FileReader
和 FileWriter
IO 流类中以 Reader 和 Writer 结尾的是字符流,用于读写只有字符的纯文本文件FileReader
和 FileWriter
只能读写与当前环境编码兼容的文件import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
/**
* FileReader 和 FileWriter
*/
public class Test01 {
public static void main(String[] args) throws IOException {
readChar();
readChar2();
writeChar();
}// 读取字符文件
public static void readChar () throws IOException {
// 创建字符流
FileReader fr = new FileReader("/Users/Desktop/test");
// 调用 read() 方法读取一个字符,返回读到的字符的码值,如果读到末尾返回 -1
int code = fr.read();
while (code != -1) {
System.out.print((char)code);
code = fr.read();
}
// 关闭流
fr.close();
}// 读取若干字符保存到字符数组
public static void readChar2 () throws IOException {
// 创建字符流
FileReader fr = new FileReader("/Users/Desktop/test");
// 定义一个数组
char [] chars = new char[1024];
// 读取若干字符存储到字符数组 chars 中,返回读到的字节数
int len = fr.read(chars);
while (len != -1) {
System.out.print(String.valueOf(chars, 0, len));
len = fr.read(chars);
}
// 关闭流
fr.close();
}// 写入字符文件
public static void writeChar () throws IOException {
// 创建字符流
FileWriter fw = new FileWriter("/Users/Desktop/test");
// 写入字符文件
// 一次写入一个字符
fw.write('1');
fw.write('a');
fw.write('汉');
fw.write('#');
// 写入字符数组
char [] chars = "hello charArray".toCharArray();
fw.write(chars);
// 写入字符串
fw.write("hello str")// 关闭流
fw.close();
}
}
InputStreamReader
和 OutputStreamWriter
如果想要读写编码不一致的文本文件,可以使用 InputStreamReader
和 OutputStreamWriter
InputStreamReader
可以把字节流转换为字符流OutputStreamWriter
可以把字符流转换为字节流import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.IOException;
/**
* InputStreamReader 和 OutputStreamWriter
*/
public class Test02 {
public static void main(String[] args) throws IOException {
readGBKFile();
writeGBKFile();
}// 在 UTF8 环境读取 GBK 文件
public static void readGBKFile () throws IOException {
// 创建字节流
FileInputStream fis = new FileInputStream("/Users/Desktop/test");
// 创建转换流,把字节流以 GBK 格式转换为字符流
InputStreamReader isr = new InputStreamReader(fis, "GBK");
// 读取文件内容,返回的是字符对应的码值
int code = isr.read();
while (code != -1) {
System.out.print((char)code);
code = isr.read();
}
// 关闭流
isr.close();
}// 在 UTF8 环境下写入 GBK 文件
public static void writeGBKFile () throws IOException {
// 创建字节流
FileOutputStream fos = new FileOutputStream("/Users/Desktop/test");
// 创建转换流,把字符流以 GBK 格式转换为字节流
OutputStreamWriter osw = new OutputStreamWriter(fos);
// 写入文件
osw.write("当前是 UTF8 编码环境,写入文件的编码是 GBK");
// 关闭流
osw.close();
}
}
BufferedReader
和 BufferedWriter
BufferedWriter
可以对输出字符流进行缓冲,写入数据到缓冲区,刷新缓冲区,或者缓冲区已满,或者关闭流时,将缓冲区的数据写入文件BufferedReader
可以对输入字符流进行缓冲,从缓冲区读取数据,不直接操作文件import java.io.IOException;
import java.io.FileWriter;
import java.io.FileReader;
import java.io.BufferedWriter;
import java.io.BufferedReader;
/**
* BufferedReader 和 BufferedWriter
*/
public class Test03 {
public static void main(String[] args) throws IOException {
writerBf();
readBf();
}// 使用字符缓冲流写入文件
public static void writerBf () throws IOException {
// 创建字符流
FileWriter fw = new FileWriter("/Users/Desktop/test");
// 创建缓冲字符流
BufferedWriter bw = new BufferedWriter(fw);
// 写入数据到缓冲区
bw.write("写入到缓冲区");
// 刷新缓冲区,把数据从缓冲区写入到文件
bw.flush();
// 关闭流
bw.close();
}// 使用字符缓冲流读取文件
public static void readBf () throws IOException {
// 创建字符流
FileReader fr = new FileReader("/Users/Desktop/test");
// 创建缓冲字符流
BufferedReader br = new BufferedReader(fr);
// 从缓冲区读取一行文件,如果读到文件末尾返回 null
String line = br.readLine();
while (line != null) {
System.out.println(line);
line = br.readLine();
}
// 关闭流
br.close();
}
}
【Java|Java 学习笔记(十一)IO 流】输出结果:
写入到缓冲区
推荐阅读
- JAVA(抽象类与接口的区别&重载与重写&内存泄漏)
- EffectiveObjective-C2.0|EffectiveObjective-C2.0 笔记 - 第二部分
- 由浅入深理解AOP
- 继续努力,自主学习家庭Day135(20181015)
- python学习之|python学习之 实现QQ自动发送消息
- Android中的AES加密-下
- 事件代理
- 一起来学习C语言的字符串转换函数
- Java|Java OpenCV图像处理之SIFT角点检测详解
- 定制一套英文学习方案