Loading... ## 流的分类 1. 按方向 - 输入流:存储设备->内存 - 输出流:内存->存储设备 2. 按单位 - 字节流:以字节为单位,可以读写所有数据 - 字符流:以字符为单位,只能读写文本数据(一个字符可能有好几个字节) 3. 按功能 - 节点流:具有实际传输数据的读写功能 - 过滤流:在节点流的基础之上增强功能 ## 字节流 InputStream OutputStream --- ### 文件字节流 #### FileInputStream 1. 一个字节一个字节地读取 ```Java //1.指定文件路径 FileInputStream fis = new FileInputStream("E:\\test.txt"); //2.一个字节一个字节地读取数据 int data=0; while((data=fis.read())!=-1){ System.out.print((char)data); } //3.关闭 fis.close(); ``` 2. 一次读取多个字节 ```Java //1.指定文件路径 FileInputStream fis = new FileInputStream("E:\\test.txt"); //2.一次读取多个字节长度 int len = 0; byte[] buf = new byte[4]; while((len=fis.read(buf))!=-1){ System.out.print(new String(buf,0,len)); } //3.关闭 fis.close(); ``` #### FileOutputStream 需要将字符串转为字节流再写入文件 `getBytes()` `FileOutputStream`构造方法的第二个参数为`true`,则再文件末尾接着写入(不覆盖原有数据) ```Java // 1. 指定文件路径 FileOutputStream fos = new FileOutputStream("E:\\a.txt"); //FileOutputStream fos = new FileOutputStream("E:\\a.txt",true); // 2. 写入数据 fos.write(97); //写入字符‘a’ fos.write('b'); //写入字符‘b’ String str = "Hello FileOutputStream"; fos.write(str.getBytes()); //将字符串转为字节流写入文件 // 3. 关闭 fos.close(); ``` #### 案例:实现文件复制 ```Java // 1.文件字节输入 FileInputStream fis = new FileInputStream("E:\\photos\\head.jpg"); // 2.文件字节输出 FileOutputStream fos = new FileOutputStream("E:\\head.txt"); // 3.读写 byte[] buf = new byte[1024]; int count = 0; while((count = fis.read(buf))!=-1){ fos.write(buf,0,count); } // 4.关闭 fos.close(); fis.close(); ``` ### 字节缓冲流 > 提高读取效率 #### BufferedInputStream ```Java //1.创建BufferedInputStream FileInputStream fis = new FileInputStream("E:\\test.txt"); BufferedInputStream bis = new BufferedInputStream(fis); //2.读取 int data = 0; while((data=bis.read())!=-1){ System.out.print((char)data); } //3.关闭 关闭BufferedInputStream会自动关闭FileInputStream bis.close(); ``` #### BufferedOutputStream > 先写到缓冲区,再写入内存设备 ```Java //1.创建BufferedOutputStream FileOutputStream fos = new FileOutputStream("E:\\test.txt"); BufferedOutputStream bos = new BufferedOutputStream(fos); //2.写入缓冲区(缓冲区大小:8K) for(int i=0;i<10;++i){ bos.write("hellow BufferedOutputStream\n".getBytes()); } //3.写入硬盘 bos.flush(); //4.关闭 bos.close(); ``` ### 对象流 > 使用流传输对象的过程称为序列化、反序列化 注意事项: - 被序列化的类必须实现`Serializable`接口 - 被序列化的类中的对象属性也必须实现`Serializable`接口 - 使用`transient`修饰的属性将不会被序列化,反序列化时该属性被赋值为默认值 - 静态属性不能被序列化 - 序列化多个对象可以使用集合 - 序列化版本号ID用于保证序列化和反序列化的类是同一个类 被序列化的类实现如下: ```Java //实现Serializable接口才可序列化 public class Student implements Serializable { //序列化版本号ID private static final long serialVersionUID = 100L; private String name; private int age; public Student(String name, int age) { this.name = name; this.age = age; } @Override public String toString() { return "Student{" + "name='" + name + '\'' + ", age=" + age + '}'; } } ``` #### ObjectOutputStream 序列化 ```Java FileOutputStream fos = new FileOutputStream("E:\\student.dat"); ObjectOutputStream oos = new ObjectOutputStream(fos); Student s1 = new Student("Jack",17); oos.writeObject(s1); oos.close(); ``` #### ObjectInputStream 反序列化 ```Java FileInputStream fis = new FileInputStream("E:\\student.dat"); ObjectInputStream ois = new ObjectInputStream(fis); Student s1 = (Student)ois.readObject(); ois.close(); System.out.println(s1); ``` ## 字符流 --- > 仅能读写文本文件 Reader Writer ### 文件字符流 > 类比文件字节流 #### FileReader 1. 一次读取一个字符 ```Java FileReader fr = new FileReader("E:\\test.txt"); int data = 0; while((data=fr.read())!=-1){ System.out.print((char)data); } fr.close(); ``` 2. 一次读取多个字符 ```Java FileReader fr = new FileReader("E:\\test.txt"); 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 ```Java FileWriter fw = new FileWriter("E:\\test.txt"); fw.write("你好"); fw.flush(); //刷新 fw.close(); ``` #### 案例:实现文件复制 > 只能复制文本文件 ```Java FileReader fr = new FileReader("E:\\test.txt"); FileWriter fw = new FileWriter("E:\\hhh.txt"); char[] buf = new char[1024]; int count = 0; while((count=fr.read(buf))!=-1){ fw.write(buf,0,count); fw.flush(); } fw.close(); fr.close(); ``` ### 字符缓冲流 #### BufferedReader ```Java FileReader fr = new FileReader("E:\\test.txt"); BufferedReader br = new BufferedReader(fr); String data = null; while((data=br.readLine())!=null){ System.out.println(data); } br.close(); ``` #### BufferedWriter ```Java FileWriter fw = new FileWriter("E:\\test.txt"); BufferedWriter bw = new BufferedWriter(fw); for (int i=0;i<10;++i) { bw.write("Hello BufferedWriter and BufferedReader"); bw.newLine(); //换行 bw.flush(); //将缓存写入文件 } bw.close(); ``` ### PrintWriter ```Java PrintWriter pw = new PrintWriter("E:\\test.txt"); pw.println(97); //打印数字 pw.println(4.556); pw.println('a'); //打印字符 pw.println("hello world");//打印字符串 pw.close(); ``` ## 转换流 > 字节流与字符流转换 ### InputStreamReader > 是字节流通向字符流的桥梁 ```Java // 以utf-8编码方式读取 FileInputStream fis = new FileInputStream("E:\\test.txt"); InputStreamReader isr = new InputStreamReader(fis,"utf-8"); int data = 0; while((data=isr.read())!=-1){ System.out.print((char)data); } isr.close(); ``` ### OutputStreamWriter > 是字符流通向字节流的桥梁 ```Java FileOutputStream fos = new FileOutputStream("E:\\test.txt"); OutputStreamWriter osw = new OutputStreamWriter(fos,"utf-8"); for (int i = 0; i < 10; i++) { osw.write("hello\n"); } osw.close(); ``` ## File类 > 代表物理盘符中的一个文件或文件夹 ### 分隔符 - 路径分隔符:; - 名称分隔符:\ ```Java System.out.println("路径分隔符:"+ File.pathSeparator); System.out.println("名称分隔符:"+ File.separator); ``` ### 文件操作 ```Java // 1.创建文件对象 File file = new File("E:\\file.txt"); System.out.println(file.toString()); //打印文件路径 // 2.创建文件 if(!file.exists()){ boolean b = file.createNewFile(); System.out.println("创建结果:"+b); } // 3.删除文件 /// 3.1 直接删除 //file.delete(); //返回boolean /// 3.2 JVM退出时删除 file.deleteOnExit(); Thread.sleep(3000); //休眠3秒便于观察 // 4.获取文件信息 System.out.println(file.getAbsoluteFile()); //绝对路径 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()).toLocaleString());//创建时间 // 5.判断 System.out.println(file.canWrite()); //是否可写 System.out.println(file.isFile()); //是否是文件 System.out.println(file.isHidden()); //是否隐藏 ``` ### 文件夹操作 `delete()`只能删除空文件夹(文件夹中不能有文件夹或者文件) ```Java // 1. 创建文件夹对象 File dir = new File("E:\\test\\demo"); // 2. 创建文件夹 if(!dir.exists()){ //dir.mkdir(); //创建单级目录 System.out.println("创建结果:" + dir.mkdirs()); //创建多级目录 } // 3. 删除文件夹 只能删除最底层的一级目录,而且该目录下不能有文件 /// 3.1 直接删除 //dir.delete(); /// 3.2 JVM关闭时删除 dir.deleteOnExit(); //Thread.sleep(3000); // 4. 获取文件夹信息 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()).toLocaleString());//创建时间 // 5. 判断 System.out.println(dir.isDirectory()); //是否是文件夹 System.out.println(dir.isHidden()); //是否隐藏 // 6. 遍历文件夹 File dir2 = new File("E://photos"); String[] filesName = dir2.list(); for(String str:filesName){ System.out.println(str); } ``` ### FileFilter接口 实现`FileFilter`接口的`accept`方法可以实现对文件/文件夹的过滤 例:打印E:\photos下的所有jpg文件 ```Java File dir2 = new File("E://photos"); File[] files = dir2.listFiles(new FileFilter() { @Override public boolean accept(File pathname) { if(pathname.getName().endsWith("jpg")){ return true; } return false; } }); for(File file : files){ System.out.println(file.getName()); } ``` ### 案例1:递归遍历文件夹 ```Java public static void listDir(File dir){ File[] files = dir.listFiles(); if(files!=null && files.length>0){ for(File file : files){ if(file.isDirectory()){ //如果是文件夹,则递归遍历 listDir(file); } else{ System.out.println(file.getAbsolutePath()); } } } else{ System.out.println("文件夹不存在或者为空文件夹"); } } ``` ### 案例2:递归删除文件夹 > 先删除文件夹中的文件再删除文件夹 ```Java public static void deleteDir(File dir){ File[] files = dir.listFiles(); if(files==null){ System.out.println("文件夹不存在"); return; } if(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属性集合 特点: - 存储属性名和属性值 - 属性名和属性值都是字符串类型 - 和流有关 - 线程安全 ### Properties集合的基本使用 ```Java // 1.创建集合 Properties properties = new Properties(); // 2.添加数据 properties.setProperty("username","Jack"); properties.setProperty("age","21"); System.out.println(properties); // 3.遍历 //可以使用keySet entrySet StringPropertyNames()遍历 Set<String> pronames = properties.stringPropertyNames(); for(String str:pronames){ System.out.println(str + " == "+properties.getProperty(str)); } ``` ### Properties集合与流有关的方法 - list方法 - store方法 - load方法 ```Java // list 列表 PrintWriter pw = new PrintWriter("E:\\print.txt"); properties.list(pw); pw.close(); // store 保存 FileOutputStream fos = new FileOutputStream("E:\\print.properties"); properties.store(fos,"这里是注释"); fos.close(); // load 加载 Properties properties2 = new Properties(); FileInputStream fis = new FileInputStream("E:\\print.properties"); properties2.load(fis); fis.close(); System.out.println(properties2); ``` © 允许规范转载 赞 0 如果觉得我的文章对你有用,请随意赞赏