在Java中,数据的输入/输出操作以“流”的方式进行
字节流:以字节为单位获取数据(命名以Stream结尾的一般是字节流)
字符流:以字符为单位获取数据(以Reader/Writer结尾的一般是字符流)
	
节点流:可以直接从数据源或目的地读写数据
处理流:不直接连接到数据源或目的地,是处理流的流,处理流也叫包装流
FilterInputStream和FilterOutputStream是所有包装流的父类
节点流的父类:InputStream和OutputStream
处理流的父类:FilterInputStream extends InputStream、FilterOutputStream extends OutputStream
使用字节流可以读写任意类型的文件
使用字符流只可以读写文本文件(doc不是文本文件)
使用字符流的好处:处理非英文方便
注意:字符流的底层还是字节流
File类用来代表文件或文件夹
作用:
注意:File类不能对文件内容进行操作,内容操作要使用io流
常用方法:
public String getName():获取文件或文件夹的名称,不包含上级路径
public String getAbsolutePath():获取文件的绝对路径,与文件是否存在没关系
public long lastModified():获取最后一次被修改的时间
public long length():获取文件的大小(字节数)
public boolean exists():文件或文件夹是否存在
public boolean isFile():是否是一个文件,如果不存在,则始终为false
public boolean isDirectory():是否是一个目录,如果不存在,则始终为false
	
public boolean delete():删除文件或者一个空文件夹,不能删除非空文件夹
public void deleteOnExit():退出时删除文件或者文件夹,用于删除临时文件,无返回值
文件字节流
FileInputStream和FileOutputStream是字节流、节点流,数据源和目的地是文件
//创建输入流和输出流
InputStream input = new FileInputStream("e:/in.txt");
OutputStream output = new FileOutputStream("e:/out.txt");
//使用输入流和输出流完成文件复制
int n;				//定义一个中转站
n = input.read();		//读一个字节,public int read() 方法返回值为int类型
while(n !=-1) {	// n=-1 表示读到了文件末尾
	out.write(n);			//写一个字节
	n = input.read();		//再读一个字节
}
//关闭输入流和输出流
input.close();
output.close();
缺点:中转站太小,速度慢,效率低 ;可以将中转站由一个字节变为一个字节数组,减少读写硬盘次数
//创建输入流和输出流
InputStream input = new FileInputStream("e:/in.txt");
OutputStream output = new FileOutputStream("e:/out.txt");
//使用输入流和输出流完成文件复制
byte[] bytes = new byte[1024];		//定义一个中转站
int length = input.read(bytes);		//将读取的文件内容放入到字节数组中,返回读取的字节数
while(length != -1) {
	out.write(bytes, 0, length);			//将字节数组内容写入文件
	length = input.read(bytes);		//再读内容到一个字节数组
}
//关闭输入流和输出流
input.close();
output.close();
文件字符流
FileReader和FileWriter是字符流、节点流,数据源和目的地是文件
//创建输入流和输出流
Reader input = new FileReader("e:/in.txt");
Writer output = new FileWriter("e:/out.txt");
//使用输入流和输出流完成文件复制
int n;				//定义一个中转站
n = input.read();		//读一个字符,public int read() 方法返回值为int类型
while(n !=-1) {	// n=-1 表示读到了文件末尾
	out.write(n);			//写一个字符
	n = input.read();		//再读一个字符
}
//关闭输入流和输出流
input.close();
output.close();
//创建输入流和输出流
Reader input = new FileReader("e:/in.txt");
Writer output = new FileWriter("e:/out.txt");
//使用输入流和输出流完成文件复制
char[] chars = new char[1024];		//定义一个中转站
int length = input.read(chars);		//将读取的文件内容放入到字符数组中,返回读取的字符数
while(length != -1) {
	out.write(chars, 0, length);			//将字符数组内容写入文件
	length = input.read(chars);		//再读内容到一个字符数组
}
//关闭输入流和输出流
input.close();
output.close();
只使用文件字节流的方式的局限是要从硬盘中读取数据到中转站,而硬盘读取速度是远远低于内存的,因此如果文件较大,则需要多次将数据从硬盘读取到中转站
使用缓冲流的话会在内存中创建输入缓冲区和输出缓冲区,中转站从输入缓冲区读取数据,即从内存到内存,因此可以提高效率

刷新输出缓冲区
方法一:bufferedOutput.close();底层会关闭流之前主动调用flush()
方法二:主动调用 bufferedOutput.flush();
方法三:缓冲区满了会自动刷新
//创建输入流和输出流
InputStream input = new FileInputStream("e:/in.txt");
OutputStream output = new FileOutputStream("e:/out.txt");
BufferedInputStream bufferedInput = new BufferedInputStream(input);
BufferedOutputStream bufferedOutput = new BufferedOutputStream(output);
//使用输入流和输出流完成文件复制
int n;				//定义一个中转站
n = bufferedInput.read();		//读一个字节,public int read() 方法返回值为int类型
while(n !=-1) {	// n=-1 表示读到了文件末尾
	bufferedOutput.write(n);			//写一个字节
	n = bufferedInput.read();		//再读一个字节
}
//关闭输入流和输出流
bufferedInput.close();
bufferedOutput.close();
readLine()底层原理
底层还是一个一个字符地读取,使用StringBuilder的append方法进行拼接操作,遇到换行符后,将StringBuilder(char [])转换为String并返回
注意:不同操作系统中换行符是不同的
Unix系统中 "\n"
Windows系统中 "\r\n"
Mac系统中 "\r"
//创建输入流和输出流
BufferedReader reader = new BufferedReader(new FileReader("e:/in.txt"));
BufferedWriter writer = new BufferedWriter(new FileWriter("e:/out.txt"));
//使用输入流和输出流(按行读写)
String line = reader.readLine();	//先读一行
while(line != null) {
	writer.write(line);			//写一行
	writer.newLine();				//换行
	line = reader.readLine();		//再读一行
}
//关闭输入流和输出流
reader.close();
writer.close();
文件流、缓冲流读取文件只能按照字节、字节数组方式读取
数据流(DataInputStream和DataOutputStream)和对象流(ObjectInputStream和DataOutputStream)可以实现对各种基本类型和引用类型数据的读写,并保留其本身的类型
数据量只能操作基本数据类型和字符串,对象流还可以操作对象(数据流和对象流的使用方式差不多)
写入的是二进制数据,需要通过对应的输入流来读取
使用对象流读写引用类型的数据,需要相应类实现Serializable接口
import java.io.*;
public class mytest {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        write();
        read();
    }
    public static void read() throws IOException, ClassNotFoundException {
        InputStream inputStream = new FileInputStream("e:/out.txt");
        BufferedInputStream bis = new BufferedInputStream(inputStream);
        ObjectInputStream ois = new ObjectInputStream(bis);
        //使用输出流
        System.out.println(ois.readBoolean());
        System.out.println(ois.readDouble());
        System.out.println(ois.readUTF());
        System.out.println(ois.readObject());
        System.out.println(ois.readObject());
        //关闭输出流
        ois.close();
    }
    public static void write() throws IOException {
        //创建一个输出流
        OutputStream outputStream = new FileOutputStream("e:/out.txt");
        BufferedOutputStream bos = new BufferedOutputStream(outputStream);
        ObjectOutputStream oos = new ObjectOutputStream(bos);
        //使用输出流
        oos.writeBoolean(true);
        oos.writeDouble(12.6f);
        oos.writeUTF("北京");
        oos.writeObject(new User("唐三藏", 18));
        oos.writeObject(new User("x", 25));
        //关闭输出流
        oos.close();
    }
}
class User implements Serializable{
    String name;
    int age;
    public User() {
    }
    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 User(String name, int age) {
        this.name = name;
        this.age = age;
    }
    @Override
    public String toString() {
        return "User{" +
                "name=‘" + name + ‘\‘‘ +
                ", age=" + age +
                ‘}‘;
    }
}
PrintStream和PrintWriter
只有输出流,没有输入流
PrintStream 可以将各种类型的数据写入文件,不能保留原来的类型,都编程String类型
InputStreamReader和OutputStreamWriter
实现字节流到字符流的转换,是适配器模式的应用
只能从字节流转换为字符流,可以带来处理字符的便利;没有字符流转换为字节流的转换流,因为没有这种需求
ByteArrayInputStream和ByteArrayOutputStream是字节流、节点流,数据源和目的地都是一个字节数组
CharArrayReader和CharArrayWriter是字符流、节点流,数据源和目的地是一个字符数组
//创建输入流和输出流InputStream input = new FileInputStream("e:/in.txt");OutputStream output = new FileOutputStream("e:/out.txt");BufferedInputStream bufferedInput = new BufferedInputStream(input);BufferedOutputStream bufferedOutput = new BufferedOutputStream(output);//使用输入流和输出流完成文件复制int n;//定义一个中转站n = bufferedInput.read();//读一个字节,public int read() 方法返回值为int类型while(n !=-1) {// n=-1 表示读到了文件末尾bufferedOutput.write(n);//写一个字节n = bufferedInput.read();//再读一个字节}//关闭输入流和输出流bufferedInput.close();bufferedOutput.close();
原文:https://www.cnblogs.com/tang321/p/14800040.html