I/O框架
流
流的分类:
按方向:
输入流:将存储设备的内容读入到内存中
输出流:将内存的内容写入到存储设备中
按单位:
字节流:以字节为单位,可以读取所有数据
字符流:以字符为单位,只能读写文本数据
按功能:
节点流:具有实际传输数据的读写功能
过滤流:在节点流的基础之上的增强功能
字节流
InputStream:字节输入流
OutputStream:字节输出流
文件字节流
FileInputStream
package com.fileIO.demo01; import java.io.FileInputStream; import java.io.IOException; /* * FileInputStream的使用 * 文件字节输入流 * * */ public class Demo01 { public static void main(String[] args) throws IOException { //1.创建FileInputStream FileInputStream fis = new FileInputStream("C:\\c_learning\\javaDemo01.txt"); //2.读取文件 //2.1单个字节读取 //fis.read(); //一个字节一个字节读 // // int data = 0; // while( (data = fis.read()) != -1 ) { // System.out.print((char)data); //强制转换,data是int类型,返回ASCII // } //2.2 一次读取多个字节 byte[] buffer = new byte[1024]; int count = 0; while ((count = fis.read(buffer)) != -1 ) { System.out.println(new String(buffer, 0, count)); //0指的是从角标为0开始读 } //3.关闭 fis.close(); System.out.println("\n执行结束"); } }
FileOutputStream
package com.fileIO.demo01; import java.io.FileOutputStream; import java.io.IOException; /* * 演示文件字节输出流 * FileOutputStream * * */ public class Demo02 { public static void main(String[] args) throws IOException { //1.创建文件字节输出流对象 FileOutputStream fos = new FileOutputStream("C:\\c_learning\\javaDemo02.txt",true); //文件名后面加true,就能无限追加,执行两次,文件里就有两个abcHello world //2.写入文件 fos.write(97); //写入a fos.write('b'); //写入b fos.write('c'); //写入c String string = "Hello World"; fos.write(string.getBytes()); //getByte()获取字符串对应的字节数组 //3.关闭 fos.close(); System.out.println("执行完毕"); } }
文件复制
package com.fileIO.demo01; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; /* * 使用文件字节流实现文件的复制,图片,视频都行 * * */ public class Demo03 { public static void main(String[] args) throws IOException { //1.创建流 //1.1文件字节输入流 FileInputStream fis = new FileInputStream("C:\\c_learning\\javaDemo01.txt"); //1.2文件字节输出流 FileOutputStream fos = new FileOutputStream("C:\\c_learning\\javaDemo03.txt"); //2.一边读一边写 byte[] buffer = new byte[1024]; int count = 0; while ((count = fis.read(buffer)) != -1) { fos.write(buffer, 0, count); } //3.关闭 fis.close(); fos.close(); System.out.println("复制完毕"); } }
字节缓冲流
缓冲流:BufferedInputStream/BufferedOutputStream
提高IO效率,减少访问磁盘的次数
数据存储在缓冲区中,flush是将缓冲区的内容写入文件中,也可以直接close
BufferedInputStream
package com.fileIO.demo01; import java.io.BufferedInputStream; import java.io.FileInputStream; import java.io.IOException; /* * 使用字节缓冲流读取 * BufferedInputStream * */ public class Demo04 { public static void main(String[] args) throws IOException { //1.创建BufferedInputStream需要有节点流文件输入流就是一个节点流 FileInputStream fis = new FileInputStream("C:\\c_learning\\javaDemo01.txt"); BufferedInputStream bis = new BufferedInputStream(fis); //2.读取 int data = 0; while ((data = bis.read()) != -1) { System.out.print((char) data); } //3.关闭 bis.close(); } }
BufferedOutputStream
package com.fileIO.demo01; import java.io.BufferedOutputStream; import java.io.FileOutputStream; import java.io.IOException; /* * 使用字节缓冲流写入 * BufferedOutputStream * */ public class Demo05 { public static void main(String[] args) throws IOException { //1.创建BufferedOutputStream FileOutputStream fos = new FileOutputStream("C:\\c_learning\\buffer.txt"); BufferedOutputStream bos = new BufferedOutputStream(fos); //2.读取 for (int i = 0; i < 10; i++) { bos.write("hello".getBytes()); //写入8k缓冲区 bos.flush(); //刷新到硬盘 防止数据丢失 } //3.关闭 bos.close(); //close内部有flush方法 System.out.println("执行完毕"); } }
对象流
增强了缓冲区功能
增强了读写8种基本类型数据和字符串功能
增强读写对象的功能
使用传输对象的过程为序列化、反序列化
序列化
package com.fileIO.demo02; import java.io.Serializable; /* * 学生类 * */ public class Student implements Serializable { //该接口是标记接口什么内容都没有 //private static final long serialVersionUID = 100L; //serialVersionUID:序列化版本号ID 要保证序列化的和反序列化的一致 private String name; private int age; public Student() { } public Student(String name, int age) { this.name = name; this.age = age; } 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; } @Override public String toString() { return "Student{" + "name='" + name + '\'' + ", age=" + age + '}'; } }
package com.fileIO.demo02; import java.io.FileOutputStream; import java.io.ObjectOutputStream; /* * 使用ObjectOutputStream实现对象的序列化 *要求:序列化的类必须要实现Serializable * */ public class Demo01 { public static void main(String[] args) throws Exception { //1.创建对象流 FileOutputStream fos = new FileOutputStream("c:\\c_learning\\stu.bin"); ObjectOutputStream oos = new ObjectOutputStream(fos); //2.序列化(写入操作) Student s1 = new Student("Tom",1); oos.writeObject(s1); //3.关闭 oos.close(); System.out.println("序列化完毕"); //报错:NotSerializableException 要实现Serializable接口 } }
反序列化
package com.fileIO.demo02; import java.io.Serializable; /* * 学生类 * */ public class Student implements Serializable { //该接口是标记接口什么内容都没有 //private static final long serialVersionUID = 100L; //serialVersionUID:序列化版本号ID 要保证序列化的和反序列化的一致 private String name; private int age; public Student() { } public Student(String name, int age) { this.name = name; this.age = age; } 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; } @Override public String toString() { return "Student{" + "name='" + name + '\'' + ", age=" + age + '}'; } }
package com.fileIO.demo02; import java.io.FileInputStream; import java.io.ObjectInputStream; /* * 使用ObjectInputStream(读取重构成对象) * * */ public class Demo02 { public static void main(String[] args) throws Exception { //1.创建对象流 FileInputStream fis = new FileInputStream("c:\\c_learning\\stu.bin"); ObjectInputStream ois = new ObjectInputStream(fis); //2.读取文件(反序列化) Student s = (Student) ois.readObject(); //Student s2 = (Student) ois.readObject(); 读两个就会异常:EOFException //3.关闭 ois.close(); System.out.println("执行完毕"); System.out.println(s); } }
注意事项
序列化类必须要实现Serializable接口
序列化类中对象属性必须要实现Serializable接口如private Address ad; Address就要实现接口
序列化版本ID,保证序列化的和反序列化的是同一个类,如果在序列化的时候没有加序列化版本ID(系统就会给一个默认的值),反序列化的时候加了自定义的且不和系统默认的一样就报错 解决方法就是重新序列化 再 反序列化
使用transient关键字(瞬间的)修饰属性 使其无法被序列化 如:private transient int age;
静态属性不能序列化 如public static String country = "China";
序列化多个对象 再反序列化时就能写Student s2 = (Student)ois.readObject(); 还能优化一下 使用集合来实现
package com.fileIO.demo02; import java.io.FileOutputStream; import java.io.ObjectOutputStream; import java.util.ArrayList; /* * 使用ObjectOutputStream实现对象的序列化 *要求:序列化的类必须要实现Serializable * */ public class Demo01 { public static void main(String[] args) throws Exception { //1.创建对象流 FileOutputStream fos = new FileOutputStream("c:\\c_learning\\stu.bin"); ObjectOutputStream oos = new ObjectOutputStream(fos); //2.序列化(写入操作) Student s1 = new Student("Tom",1); Student s2 = new Student("Jack",2); ArrayList<Student> students = new ArrayList<Student>(); students.add(s1); students.add(s2); oos.writeObject(students); //3.关闭 oos.close(); System.out.println("序列化完毕"); //报错:NotSerializableException 要实现Serializable接口 } }
package com.fileIO.demo02; import java.io.FileInputStream; import java.io.ObjectInputStream; import java.util.ArrayList; /* * 使用ObjectInputStream(读取重构成对象) * * */ public class Demo02 { public static void main(String[] args) throws Exception { //1.创建对象流 FileInputStream fis = new FileInputStream("c:\\c_learning\\stu.bin"); ObjectInputStream ois = new ObjectInputStream(fis); //2.读取文件(反序列化) // Student s = (Student) ois.readObject(); //Student s2 = (Student) ois.readObject(); 读两个就会异常:EOFException ArrayList<Student> students = (ArrayList<Student>) ois.readObject(); //3.关闭 ois.close(); System.out.println("执行完毕"); System.out.println(students); } }
字符流
当我们使用字节流的方式去读取文件,如果文件内容是中文,就会出现乱码 因为txt里面汉字是UTF-8 一个汉字3个字节,一个一个字节读当然就是乱码了
文件字符流
FileReader
package com.fileIO.demo03; import java.io.FileReader; import java.io.IOException; /* * * FileReader读取文件 * */ public class Demo01 { public static void main(String[] args) throws IOException { //1.创建FileReader 文件字符输入流 FileReader fr = new FileReader("C:\\c_learning\\javaDemo01.txt"); //2.读取 //2.1单个字符 // int data = 0; // while ((data = fr.read()) != -1) { //读取一个字符 // System.out.println((char) data); // } //2.2 使用字符缓冲区 char[] buf = new char[1024]; int count = 0; while ((count = fr.read(buf)) != -1) { System.out.print(new String(buf, 0, count)); } //关闭 fr.close(); } }
FileWriter
package com.fileIO.demo03; import java.io.FileWriter; import java.io.IOException; /* * FileWriter写入文件 * * */ public class Demo02 { public static void main(String[] args) throws IOException { //1.创键FileWriter对象 FileWriter fw = new FileWriter("c:\\c_learning\\writer.txt"); //写入方法 for (int i = 0; i < 10; i++) { fw.write("java 是世界上最好的语言\n"); fw.flush(); } fw.close(); System.out.println("Execution completed!"); } }
复制文件
package com.fileIO.demo03; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; /* * FileReader和FileWriter复制文本文件,不能复制图片或其他二进制文件 二进制文件变成字符就是一堆乱码(要字节流可以复制任意文件) * * */ public class Demo03 { public static void main(String[] args) throws IOException { //1.创建FileReader FileWriter FileReader fr = new FileReader("C:\\c_learning\\writer.txt"); FileWriter fw = new FileWriter("C:\\c_learning\\writer2.txt"); //2.读写 int data = 0; while ((data = fr.read()) != -1) { fw.write(data); fw.flush(); } //3.关闭 fr.close(); fw.close(); System.out.println("Copy completed!"); } }
字符缓冲流
BufferedReader
package com.fileIO.demo03; import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; /* * 使用字符缓冲流读取文件 * BufferedReader * * */ public class Demo05 { public static void main(String[] args) throws IOException { //创建缓冲流 FileReader fr = new FileReader("C:\\c_learning\\writer.txt"); BufferedReader br = new BufferedReader(fr); //2.读取 //2.1 // char[] buf = new char[1024]; // int count = 0; // while ((count = br.read(buf) )!= -1) { // System.out.println(new String(buf,0, count)); // } //2.2 一行一行读 String line =null; while ((line = br.readLine()) != null) { System.out.println(line); } //3.关闭 br.close(); } }
BufferedWriter
package com.fileIO.demo03; import java.io.BufferedWriter; import java.io.FileWriter; import java.io.IOException; /* * BufferedWriter * * * */ public class Demo04 { public static void main(String[] args) throws IOException { //1.创建BufferedWriter对象 FileWriter fw = new FileWriter("C:\\c_learning\\buffer.txt"); BufferedWriter bw = new BufferedWriter(fw); //2.写入 for (int i = 0; i < 10; i++) { bw.write("好好学习,天天向上"); bw.newLine(); //写入一个换行符 windows \r\n linux \n bw.flush(); } //3.关闭 bw.close(); System.out.println("Execution completed!"); } }
打印流
package com.fileIO.demo04; import java.io.IOException; import java.io.PrintWriter; /* * PrintWriter的使用 * * * */ public class Demo01 { public static void main(String[] args) throws IOException { //1.创建打印流 PrintWriter pw = new PrintWriter("C:\\c_learning\\print.txt"); //2.打印 pw.println(97); //之前在字节流里是得到a pw.println(true); pw.println(3.14); pw.println('a'); //3.关闭 pw.close(); } }
转换流
桥转换流:InputStreamReader/OutputStreamWriter
可将字节流转换为字符流
可设置字符的编码方式
package com.fileIO.demo05; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStreamReader; /* *使用InputStreamReader 读取文件 指定使用的编码 * * * */ public class Demo01 { public static void main(String[] args) throws IOException { //1.创建InputStreamReader对象 FileInputStream fis = new FileInputStream("C:\\c_learning\\writer.txt"); InputStreamReader isr = new InputStreamReader(fis, "UTF-8"); //2.读取文件 int data = 0; while ((data = isr.read()) != -1) { System.out.print((char) data); } //3.关闭 fis.close(); } }
package com.fileIO.demo05; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStreamWriter; /* *使用OutputStreamWriter写入文件 指定编码 * * * */ public class Demo02 { public static void main(String[] args) throws IOException { //1.创建OutputStreamWriter FileOutputStream fos = new FileOutputStream("C:\\c_learning\\info.txt"); OutputStreamWriter osw = new OutputStreamWriter(fos, "gbk"); //2.写入 for (int i = 0; i < 10; i++) { osw.write("我爱北京"); osw.flush(); } //3.关闭 osw.close(); System.out.println("Execution completed!"); } }
文件类
代表物理盘符中一个文件或者文件夹
文件类的使用
package com.fileIO.demo06; import java.io.File; import java.io.IOException; import java.util.Date; /* * File类的使用 * 1.分隔符 * 2.文件操作 * 3.文件夹操作 * */ public class Demo01 { public static void main(String[] args) throws IOException { separator(); fileOperation(); directoryOperation(); } //1.分隔符 public static void separator() { System.out.println("路径分隔符"+ File.pathSeparator); System.out.println("名称分割符"+ File.separator); } //2.文件操作 public static void fileOperation() throws IOException { //1.创建文件 File file = new File("C:\\c_learning\\file.txt"); //如果不写成绝对路径形式只写file.txt就会在这个项创建 //System.out.println(file.toString()); if (!file.exists()) { boolean b = file.createNewFile(); System.out.println("创建结果" + b); //不存在就创true 存在就不创false } //2.删除文件 //2.1 直接删除 //System.out.println("删除结果"+file.delete()); //删除true 没删除false //2.2 jvm退出时删除 // file.deleteOnExit(); // try { // Thread.sleep(100); // } catch (InterruptedException e) { // throw new RuntimeException(e); // } //3.获取文件信息 System.out.println("获取文件的绝对路径"+file.getAbsolutePath()); System.out.println("获取路径"+file.getPath()); System.out.println("获取文件名称"+file.getName()); System.out.println("获取父目录"+file.getParent()); System.out.println("文件长度"+file.length()); System.out.println("文件创建时间"+new Date(file.lastModified())); //4.判断 System.out.println("是否能写"+file.canWrite()); System.out.println("是否是文件"+file.isFile()); System.out.println("是否隐藏"+file.isHidden()); } //3.文件夹操作 public static void directoryOperation(){ //1.创建文件夹 File dir = new File("C:\\aaa\\bbb\\ccc"); System.out.println(dir.toString()); if(!dir.exists()) { //dir.mkdir(); //只能创建单级目录 System.out.println(dir.mkdirs()); //创建多级目录 } //2.删除文件夹 //2.1直接删除(只能删除空目录) //System.out.println("删除结果"+dir.delete()); //只删除最底层的,要求底层的是空目录 //dir.deleteOnExit(); //3.获取文件夹信息 System.out.println("获取绝对路径"+dir.getAbsolutePath()); System.out.println("获取路径"+dir.getPath()); System.out.println("获取名称"+dir.getName()); System.out.println("获取父目录"+dir.getParent()); System.out.println("获取创建时间"+new Date(dir.lastModified())); //4.判断 System.out.println("是否是文件夹"+dir.isDirectory()); System.out.println("是否隐藏"+dir.isHidden()); //5.遍历文件夹 File dir2 = new File("C:\\c_learning"); String[] files = dir2.list(); for(String s : files) { System.out.println(s); } } }
FileFilter接口
在上面那个代码foreach循环后加上这串代码,实现只遍历后缀为txt的文件
System.out.println("--------------------------------FileFilter-----------------------------------------"); File[] file2 = dir2.listFiles(new FileFilter() { @Override public boolean accept(File pathname) { if(pathname.getName().endsWith(".txt")) { return true; } return false; } }); for (File file : file2) { System.out.println(file.getName()); }
递归遍历和递归删除
package com.fileIO.demo06; import java.io.File; /* *案例1:递归遍历文件夹 *案例2:递归删除文件夹 * * */ public class listDemo { public static void main(String[] args) { listDir(new File("C:\\myFiles")); deleteDir(new File("C:\\myFiles")); } //案例1:递归遍历文件夹 public static void listDir(File dir) { File[] files = dir.listFiles(); System.out.println(dir.getAbsolutePath()); if (files != null && files.length > 0) { for (File file : files) { if (file.isDirectory()) { listDir(file); //递归 }else { System.out.println(file.getAbsolutePath()); } } } } //案例2:递归删除 只有文件夹是空的才能删掉文件夹 public static void deleteDir(File dir) { File[] files = dir.listFiles(); if (files != null && files.length > 0) { for (File file : files) { if (file.isDirectory()) { deleteDir(file); //递归 }else { //删除文件 System.out.println(file.getAbsolutePath()+"删除"); file.delete(); } } } System.out.println(dir.getAbsolutePath()+dir.delete()); } }
补充:Properties
存储属性名和属性值
属性名和属性值都是字符串类型
没有泛型
和流有关
package com.fileIO.demo07; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.PrintWriter; import java.util.Properties; import java.util.Set; /* * Properties集合的使用 * */ public class Demo01{ public static void main(String[] args) throws IOException { //1.创建集合 Properties prop = new Properties(); //2.添加数据 prop.setProperty("username", "Tom"); prop.setProperty("age", "20"); System.out.println(prop); //3.遍历 //3.1keySet //3.2entrySet //3.3stringPropertyNames() Set<String> proNames= prop.stringPropertyNames(); for (String pro : proNames) { System.out.println(pro+"-------"+prop.getProperty(pro) ); } //4.和流有关的方法 //4.1list PrintWriter pw = new PrintWriter("C:\\c_learning\\printf.txt"); prop.list(pw); pw.close(); //4.2store保存 FileOutputStream fos = new FileOutputStream("C:\\c_learning\\printf.properties"); prop.store(fos, "注释"); fos.close(); //4.3load加载 Properties prop2 = new Properties(); FileInputStream fis = new FileInputStream("C:\\c_learning\\printf.properties"); prop2.load(fis); fis.close(); System.out.println(prop2); } }