I: INPUT 输入
O: OUTPUT 输出
Java用方向输入与输出划分读写操作,其中输入用来读取,输出用来写入
java.io.InputStream : 输入流,是所有输入流的超类,定义了读取字节的相关方法
java.io.OutputStream : 输出流,是所有输出流的超类,定义了写出字节的相关方法。
java将流分为两类:节点流与处理流
特点是实际连接程序与另一端的“管道“,负责实际读写数据的流,
文件流就是非常典型的低级流
文件流就是非常典型的低级流,因为它是实际连接程序与文件之间的“管道”,负责实际读写文件数据的流
文件流
特点是不能独立存在,必须连接在其他流上,目的是当数据经过当前流时,对该数据进行某种加工操作,简化我们的同等工作.
注意:
高级流可以连接在低级流上,也可以连接在其他高级流上
I/O流
import java.io.*;
/*
* java将流分为两类:节点流与处理流
* 节点流(也称低级流):特点是实际连接程序与另一端的“管道“,
* 负责实际读写数据的流
* 文件流就是非常典型的低级流,因为它是实际连接程序与文件之间的“管道”,负责实际读写文件数据的流
* 处理流(也称高级流):特点是不能独立存在,必须连接在其他流上,
* 目的是当数据经过当前流时,对该数据进行某种加工操作,简化我们的同等工作.
* 注意:
* 高级流可以连接在低级流上,也可以连接在其他高级流上
* 流的连接:
* 实际开发中我们经常会串联一组高级流最终到某个低级流上,使得读写数据的过程中以"流水线"式的加工完成.这个过程也称为流的连接.
*/
public class CopyDemo3 {
/*
* 缓冲流java.io.BufferedInputStream和BufferedOutputStream
* 功能:
* 加快读写字节数据的效率
*/
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("./310792.jpg");
FileOutputStream fos = new FileOutputStream("./image.jpg");
BufferedInputStream bis = new BufferedInputStream(fis);
BufferedOutputStream bos = new BufferedOutputStream(fos);
int num;
while ((num = bis.read()) != -1){
bos.write(num);
}
bis.close();
bos.close();
}
}
BufferedOutputStream用flush方法才能将缓存区里面的数据强迫发送,不然无法写出到数据,close方法里面调用了flush方法
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
/*
* 缓冲输出流的缓冲区问题
*/
public class FlushDemo {
public static void main(String[] args) throws IOException {
FileOutputStream fos = new FileOutputStream("./demofile.txt");
BufferedOutputStream bos = new BufferedOutputStream(fos);
bos.write("天下文才共九斗,我独得一石,天下欠我一斗".getBytes(StandardCharsets.UTF_8));
/*
* flush方法是接口Flushable中定义的唯一抽象方法
* 输出流的超类java.io.OutputStream实现了这个方法
*/
bos.flush(); //将缓冲区的数据强迫发送
System.out.println("写出成功");
bos.close();
}
}
对象流是一对高级流,作用是进行对象序列化和反序列化
对象序列化:将一个java对象按照其结构和内容转换为一组字节的过程
反之则为对象反序列化
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
/*
* 对象流:
* java.io.ObjectOutputStream java.io.ObjectInputStream
* 对象流是一对高级流,作用是进行对象序列化和反序列化
* 对象序列化:将一个java对象按照其结构和内容转换为一组字节的过程
* 反之则为对象反序列化
*/
public class OosDemo {
/*
* 对象序列化
*/
public static void main(String[] args) throws IOException {
String name = "张三";
int age = 23;
String gender = "男";
String[] otherInfo = {"技术好","技术超好","大家的启蒙老师"};
Person person = new Person(name,age,gender,otherInfo);
System.out.println(person);
//将person对象写入文件person.obj中
FileOutputStream fos = new FileOutputStream("./person.obj");
ObjectOutputStream oos = new ObjectOutputStream(fos);
/*
* 对象输出流提供了序列化操作:
* void writeObject(Object obj) 该方法会将参数给定的对象按照其结构转换为一组字节后写出.
* 注意:
* 运行可能会报错java.io.NotSerializableException,
* 这是因为类需要调用java.io.Serializable接口
*/
oos.writeObject(person);
System.out.println("写出完毕");
oos.close();
}
}
import java.io.Serializable;
import java.util.Arrays;
/*
* 使用当前类测试对象序列化与反序列化
* 加上transient关键字修饰属性后
* 属性序列化时会被忽略
* private transient String[] otherInfo
*/
public class Person implements Serializable {
private String name;
private int age;
private String gender;
private String[] otherInfo;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public String[] getOtherInfo() {
return otherInfo;
}
public void setOtherInfo(String[] otherInfo) {
this.otherInfo = otherInfo;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
", gender='" + gender + '\'' +
", otherInfo=" + Arrays.toString(otherInfo) +
'}';
}
public Person(String name, int age, String gender, String[] otherInfo) {
this.name = name;
this.age = age;
this.gender = gender;
this.otherInfo = otherInfo;
}
public Person() {
}
}
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
/*
* 对象反序列化
*/
public class OisDemo {
public static void main(String[] args) throws IOException, ClassNotFoundException {
FileInputStream fis = new FileInputStream("./person.obj");
ObjectInputStream ois = new ObjectInputStream(fis);
/*
* 对象输入流提供了反序列化操作:
* Object readObject()
*/
Person person = (Person) ois.readObject();
System.out.println(person);
ois.close();
}
}
转换流是唯一可以连接在字节流上的字符流,在流连接中其他的字符流可以通过连接上的转换流从而与下面的字节流串联进行读写操作.
传统方法实现字符转换
简易记事本
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.nio.charset.StandardCharsets;
/*
* 转换流:
* java.io.OutputStreamWriter java.io.InputStreamReader
* 转换流是唯一可以连接在字节流上的字符流,在流连接中其他的字符流可以通过连接上的转换流
* 从而与下面的字节流串联进行读写操作.
*/
public class OswDemo {
public static void main(String[] args) throws IOException {
FileOutputStream fos = new FileOutputStream("./demofile.txt");
/*
* 指定字符集(不指定会使用系统默认的)
*/
OutputStreamWriter opsw = new OutputStreamWriter(fos, StandardCharsets.UTF_8);
/*
* OutputStreamWriter继承自字符输出流超类Write,
* Write上提供了直接写出字符的write方法
* 转换输出流OutputStreamWriter是一个高级流,通过它写出的字符会被转换为字节再写出
*/
opsw.write("转换流测试");
System.out.println("写出完毕");
opsw.close();
}
}
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
/*
* 转换输入流读取文件
*/
public class IsrDemo {
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("./demofile.txt");
InputStreamReader ipsr = new InputStreamReader(fis);
/*
* 字符流超类Reader上提供了读取字符的方法:
* int read()
* 读取一个字符(char),用int形式返回。
* 如果返回的int值为整数-1表示流到读取到了了末尾
*/
int d;
while ((d = ipsr.read()) != -1) {
System.out.print((char) d);
}
ipsr.close();
}
}
import java.io.FileNotFoundException;
import java.io.PrintWriter;
/*
* 缓冲字符流
* java.io.BufferedWriter和BufferedReader
* 缓冲字符流可以块读写文本数据加速
* java.io.PrintWriter是具有自动行刷新的缓冲字符输出流.内部总是连接BufferedWriter
* 特点:
* 1:可以按行写出字符串
* 2:自动行刷新
*/
public class PwdDemo {
public static void main(String[] args) throws FileNotFoundException {
/*
* PrintWriter提供了直接对文件进行写操作的构造器:
* PrintWriter(String fileName)
* PrintWriter(File file)
* 上述两个构造器内部都进行了4层流连接
* PrintWriter -> BufferedWriter -> OutputStreamWriter -> FileOutputStreamWriter
* PW:负责按行写出字符串
* BW:块写文本数据加速(内部有一个默认8192长度的字符数组)
* OSW:将写出的字符转字节
* FOS:将字节写入到文件中
*/
PrintWriter pw = new PrintWriter("./demofile.txt");
pw.println("这是测试。");
pw.println("测试PrintWriter");
System.out.println("写出完毕");
pw.close();
}
}
import java.io.*;
import java.nio.charset.StandardCharsets;
/*
* 使用流连接完成pw创建
*/
public class PwdTest {
public static void main(String[] args) throws FileNotFoundException {
FileOutputStream fos = new FileOutputStream("./demofile.txt",true); //文件流
OutputStreamWriter opsw = new OutputStreamWriter(fos, StandardCharsets.UTF_8); //转换流
BufferedWriter bw = new BufferedWriter(opsw); //缓冲字符流
/*
* PrintWriter如果第一个参数为流,那么就支持再传入一个参数boolean
* 如果这个值为true那么就打开了自动行刷新
*/
PrintWriter pw = new PrintWriter(bw,true);
pw.println("测试自己写流连接");
pw.println("PrintWriter -> BufferedWriter -> OutputStreamWriter -> FileOutputStreamWriter");
System.out.println("写出成功");
pw.close();
}
}
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
/*
* java.io.BufferedReader
* 缓冲字符输入流,内部维护一个默认8192长度的char数组,可以块读文本数据加速
* 并且可以按行读取字符串
*/
public class BrDemo {
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("./demofile.txt"); //文件流
InputStreamReader isr = new InputStreamReader(fis); //转换流
BufferedReader br = new BufferedReader(isr);
/*
* BufferedReader提供的方法:
* String readLine()
* 读取并返回一行字符串,返回的字符串中不含有该行结束的换行符
* 如果返回值为null则表示读取到了末尾
* 如果读取了空行(只有一个换行符)返回值为空字符串:""
*/
String str;
while ((str = br.readLine()) != null ) {
System.out.println(str);
}
br.close();
}
}
实际开发中我们经常会串联一组高级流最终到某个低级流上,使得读写数据的过程中以"流水线"式的加工完成.这个过程也称为流的连接.