I/O是 input/output 的缩写,IO技术是非常实用的技术,如读写文件,网络通讯等
流(Stream)是指从源节点到目标节点的数据流动(用来传输数据的管道)。
源节点和目标节点可以是文件、网络、内存、键盘、显示器等等。
源节点的数据流称为输入流(用来读取数据)。
目标节点的数据流称为输出流(用来写入数据)。
流的分类
1.按操作数据单位不同分为:
字节流(8bit):用于操作非文本文件(FileInputStream/FileOutputStream)
字符流 (16bit) :用于操作文本文件 (FileReader/FileWriter)
2. 按数据流的流向不同分为:
输入流 :将文件读入程序的叫输入流
输出流 :将文件从程序输出的叫输出流
3. 按流的角色的不同分为:
节点流 :FileInputStream/FileOutputStream/FileReader/FileWrite
处理流:缓冲流,对象流等
字符流完成文本的复制
public static void main(String[] args) throws Exception {
// 创建缓冲流包装对应的节点流 用于提高效率
BufferedReader br = null;
BufferedWriter bw = null;
try {
// 创建一个输入/输出流对象 管道,同时指定文件
FileReader fr = new FileReader("E:/important/Text.txt"); // E:\\important\\Text.txt E:\\important/Text.txt 都可以
FileWriter fw = new FileWriter("E:/important/Text1.txt"); // 在指定目录下创建文件 若已有文件则覆盖 若不想覆盖则加一个true如下
//FileWriter fw = new FileWriter("E:/important/Text1.txt",true); 默认为false
br = new BufferedReader(fr);
bw = new BufferedWriter(fw);
// 一次读入一行数据
String inString = null;
while ((inString = br.readLine()) != null) {
// bw.write(inString+"\n");
bw.write(inString); //此时会源文件文本读入到一行上
bw.newLine(); //换行
}
} catch (IOException e) {
e.printStackTrace();
} finally {
//关闭流 从下向上顺序关闭 关闭缓冲流的同时也关闭了节点流
if (bw != null) {
try {
bw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (br != null) {
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
字节流完成非文本文件的复制
public static void main(String[] args) throws Exception {
// 创建缓冲流包装对应的节点流 用于提高效率
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
try {
// 创建一个输入/输出流对象 管道,同时指定文件
FileInputStream fis = new FileInputStream("E:/important/123.avi"); // E:\\important\\123.avi E:\\important/123.avi 都可以
FileOutputStream fos = new FileOutputStream("E:/important/456.avi");
//FileOutputStream fos = new FileOutputStream("E:/important/456.avi", true);
bis = new BufferedInputStream(fis);
bos = new BufferedOutputStream(fos);
// 将读取的内容放在字节数组中(如果是FileRead/FileWirte 就放在字符数组里)
byte[] b = new byte[1024];
int len = 0;
while ((len = bis.read(b)) != -1) {
bos.write(b, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
//关闭流 此处只关闭包装流即可,因为关闭包装流就自动关闭节点流:查看BufferedInputStream源代码就明白
if (bos != null) {
try {
bos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (bis != null) {
try {
bis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
对象流完成对象的序列化和反序列化
序列化:用ObjectOutputStream类保存基本类型数据或对象的机制
(将内存中的对象以二进制的形式永久的保存到磁盘中)
反序列化:用ObjectInputStream类读取基本类型数据或对象的机制
(将磁盘中的二进制数据读取到内存中)
ObjectOutputStream和ObjectInputStream不能序列化static和transient修饰的成员变量
//若相对象被序列化 必须实现Serializable接口才可以
//实现接口以后指定一个序列号 当反序列话的时候会根据序列号反序列化
public class Person implements Serializable {
private static final long serialVersionUID = 115785215422L;
// 属性
private String name;
private int age;
private double weight;
private String gender;
private String country;
// 提供公共的无参构造器和全参构造器
public Person() {
}
public Person(String name, int age, double weight, String gender, String country) {
this.name = name;
this.age = age;
this.weight = weight;
this.gender = gender;
this.country = country;
}
public String toString() {
return "姓名:" + name + "\t年龄:" + age + "\t体重:" + weight + "\t性别:" + gender + "\t国籍:" + country;
}
}
对象的序列化
public static void main(String[] args) throws Exception {
// 创建缓冲流包装对应的节点流 用于提高效率
Person p1 = new Person("小明", 15, 54, "男", "美国");
Person p2 = new Person("小红", 17, 56, "女", "加拿大");
Person p3 = new Person("小刚", 16, 68, "男", "日本");
// 创建对象流包装缓冲流 进行序列化
ObjectOutputStream oos = null;
try {
// 创建输出流对象 管道 并指定文件
FileOutputStream fos = new FileOutputStream("E:/important/person.txt");
// 创建缓冲流包装节点流 提高传输效率(此步为选用)
BufferedOutputStream bos = new BufferedOutputStream(fos);
oos = new ObjectOutputStream(bos);
// 利用对象流对对象进行序列化
oos.writeObject(p1);
oos.writeObject(p2);
oos.writeObject(p3);
} catch (IOException e) {
e.printStackTrace();
} finally {
// 关闭流 此出关闭对象流即可 关闭对象流就会把 缓冲流和节点流一同关掉
if (oos != null) {
try {
oos.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
对象的反序列化
public static void main(String[] args) throws Exception {
//创建对象流包装缓冲流 并实现反序列化
ObjectInputStream ois = null;
try {
//创建一个输入流实例 管道 并指定文件
FileInputStream fis = new FileInputStream("E:/important/person.txt");
// 创建缓冲流包装节点流 提高传输效率(此步为选用)
BufferedInputStream bis = new BufferedInputStream(fis);
ois = new ObjectInputStream(bis);
//实现反序列化
Person p1 = (Person) ois.readObject();
Person p2 = (Person) ois.readObject();
Person p3 = (Person) ois.readObject();
System.out.println(p1);
System.out.println(p2);
System.out.println(p3);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
//关闭流
if (ois != null) {
try {
ois.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
转换流https://blog.youkuaiyun.com/weixin_42114097/article/details/80879238
InputStreamReader & OutputStreamWriter (将字节流(二进制)转化为字符流)
什么是编码: 字符串、图片、音频等 ---> 二进制数据(字节数组)
(计算机中都是以二进制形式存储底层都是010101001形式)
什么是解码:二进制数据(字节数组) ---> 字符串、图片、音频
public static void main(String[] args) throws Exception {
//将字符串 以GBK形式编码 写入到CSV文件里
FileOutputStream fos = new FileOutputStream("E:/hello.csv",true);//为true时在原文件里追加数据 false则覆盖数据 默认为false
OutputStreamWriter osw = new OutputStreamWriter(fos, "GBK"); //将字节流转化为字符流 GBK编码
BufferedWriter bw = new BufferedWriter(osw);
for(int i=0;i<=10;i++){
String outString = "abcde中国"+i;
bw.write(outString);
bw.newLine();
}
bw.close();
//将csv文件里的数据以GBK解码到内存中
FileInputStream fis = new FileInputStream(new File("E:\\hello.csv")); // 读取的CSV文件
InputStreamReader isr = new InputStreamReader(fis,"GBK"); //将字节流转化为字符流 GBK解码 此处字符集如果不和编码是一样就会乱码
BufferedReader br = new BufferedReader(isr);
String inString = null;
while((inString = br.readLine()) != null){
System.out.println(inString);
}
br.close();
}
控制台IO
默认输入设备是键盘,默认输出设备是显示器
System.in : “标准”的输入流
System.in的类型是InputStream(in是System类中的属性,in的类型是InputStream)
System.out : “标准”的输出流
System.out的类型是PrintStream(打印流)(out是System类中的属性,out的类型是PrintStream),
其是OutputStream的子类,FilterOutputStream 的子类
System.err : “标准”的错误输出流
public static void main(String[] args) throws Exception {
//System.out输出位置的设置
FileOutputStream fos = new FileOutputStream("E:/infoLog.txt", true); //有true 就不会覆盖重写了会追加
//此设置之后,打印的文字就不会显示在控制台上,会打印在指定的文件上(E盘的infoLog.txt文件下)
System.setOut(new PrintStream(fos));
System.out.println("此消息会输出在E盘的infoLog.txt文件里");
//异常打印的位置
try {
int div = 10 / 0;
} catch (Exception e) {
PrintWriter pw = new PrintWriter(new FileWriter("E:/errorLog.txt"));
e.printStackTrace(pw); //异常信息或打印在指定的文件下(E盘的errorLog.txt文件下)
pw.flush();
}
}
RandomAccessFile
RandomAccessFile raf = new RandomAccessFile(“test.txt”, “rw”);
可以记录上次观看视频的位置 和 实现断点续传