在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