Java学习IO流(一)
IO流概述
之前的程序,数据都是在内存中,一旦程序运行结束,数据就没有了。IO流的出现就是把运算完的数据都保存下来,下次运行程序时还能使用。把数据持久化的存储,就是把内存中的数据存储到内存以外的其他持久化的设备(光盘、硬盘、U盘等)上。
当需要把内存中的数据存储到持久化设备上这个动作称为输出(写)Output操作。
当把持久设备上的数据读取到内存中的这个动作称为输入(读)Input操作。
因此我们把这种输入和输出动作称为IO操作。
File类
File类有两个静态成员变量和三个构造方法
1、pathSeparator 与系统有关的路径分隔符 ;
2、separator 与系统有关的默认名称分隔符 \
构造方法:1、File(String pathname)
2、File(File parent,String child)
3、File(String parent,String child)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | package com.oracle.demo1; import java.io.File; public class FileDemo { public static void main(String[] args) { // 与系统有关的路径分隔符 ; String pathseparator = File.pathSeparator; System.out.println(pathseparator); // 与系统有关的默认名称分隔符 \ String separator = File.separator; System.out.println(separator); // 构造方法一 File(String pathname) File f = new File( "d:\\eclipsework1" ); System.out.println(f); // 构造方法二 File(File parent,String child) File parent = new File( "d:" ); File f2 = new File(parent, "eclipsework1" ); System.out.println(f2); // 构造方法三 File(String parent, String child) File f3 = new File( "d:" , "eclipsework1" ); System.out.println(f3); } } |
File类常用的方法
1、创建文件
boolean |
2、创建文件夹
3、删除
boolean |
delete() |
4、判断此文件是否存在
boolean |
exists() |
5、判断此文件是否是文件夹
boolean |
6、获取绝对路径
7、获取文件名
8、获取路径
9、长度
long |
length() |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | package com.oracle.demo1; import java.io.File; import java.io.IOException; public class FileDemo2 { public static void main(String[] args) throws IOException { // 创建文件 // File f = new File("d:\\eclipse\\demo.java"); // boolean b = f.createNewFile(); // System.out.println(b); // 创建文件夹用mkdir()(多级目录用mkdirs()) // File f2 = new File("d:\\eclipse\\test\\test2"); // boolean b = f2.mkdirs(); // System.out.println(b); // 删除(删除的文件不走回收站,直接从硬盘上删除) // File f2 = new File("d:\\eclipse\\test\\test2"); // boolean b = f2.delete(); // System.out.println(b); // 判断路径是否存在 // File f = new File("d:\\eclipse"); // boolean b = f.exists(); // System.out.println(b); // 文件File、目录(文件夹)directory、路径path // boolean isDirectory() 判断这个文件对象是否是文件夹 //System.out.println(f.isDirectory()); //文件的获取 //绝对路径 File f= new File( "d:\\eclipsework1" ); //相对路径 File f1= new File( "src" ); System.out.println(f.getAbsolutePath()); System.out.println(f.getName()); System.out.println(f.getPath()); System.out.println(f.length()); } } |
listFiles()方法
listFiles()方法用来获取一个目录中所有的文件和文件夹,得到的结果是一个数组或者集合
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | package com.oracle.demo1; import java.io.File; public class ListFileDemo { public static void main(String[] args) { // 创建你要获取的路径对象 File f = new File( "D:\\java\\jdk" ); // 获取此路径下文件的文件数组 File[] f2 = f.listFiles(); // 遍历数组得到文件 for (File file : f2) { System.out.println(file); } System.out.println(f2.length); } } |
注:在获取指定目录下的文件或者文件夹时必须满足下面两个条件
1,指定的目录必须是存在的,
2,指定的必须是目录。否则容易引发返回数组为null,出现NullPointerException
文件过滤器
当我们需要文件中某个指定的文件时,就需要用到文件过滤器。在File类中重载了listFiles方法,并接受指定的过滤器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | package com.oracle.demo1; import java.io.File; import java.io.FileFilter; public class MyFilter implements FileFilter{ public boolean accept(File pathname) { String p=pathname.getName(); return p.endsWith( ".exe" ); } } package com.oracle.demo1; import java.io.File; public class FileDemo3 { public static void main(String[] args) { File f = new File( "d:\\java\\jdk\\bin" ); File[] f2 = f.listFiles( new MyFilter()); for (File f3 : f2) { System.out.println(f3); } } } |
递归调用
递归:就是在当前的方法内调用自己的现象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | package com.oracle.demo2; public class demo1 { public static void main(String[] args) { // 求1......n的值 int sum = getsum( 100 ); System.out.println(sum); System.out.println(get( 5 )); } // 递归调用 public static int getsum( int a) { if (a== 1 ){ return 1 ; } return a + getsum(a - 1 ); } //递归求阶乘 public static int get( int b){ if (b== 1 ){ return 1 ; } return b*get(b- 1 ); } } |
注:递归一定要有条件限定,保证递归能够停止下来,否则会发生栈内存溢出。
在递归中虽然有限定条件,但是递归次数不能太多。否则也会发生栈内存溢出。
练习:1、递归打印指定目录及子目录下的所有文件
2、递归调用打印d:\java\jdk下所有的.exe文件
3、使用文件名称过滤器筛选将指定文件夹下的小于200K的小文件获取并打印
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | package com.oracle.demo2; import java.io.File; public class demo4 { public static void main(String[] args) { File file = new File( "d:\\java\\jdk" ); getFileAll(file); } //获取指定目录以及子目录中的所有的文件 public static void getFileAll(File file) { File[] files = file.listFiles(); //遍历当前目录下的所有文件和文件夹 for (File f : files) { //判断当前遍历到的是否为目录 if (f.isDirectory()){ //是目录,继续获取这个目录下的所有文件和文件夹 getFileAll(f); } else { //不是目录,说明当前f就是文件,那么就打印出来 System.out.println(f); } } } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | package com.oracle.demo2; import java.io.File; public class LianXi { public static void main(String[] args) { File file= new File( "d:\\java\\jdk" ); get(file); } public static void get(File f){ //获取文件数组 File[] file2=f.listFiles( new MyFileFilterDemo()); //遍历当前文件下所有的文件 for (File f2:file2){ if (f2.isDirectory()){ get(f2); } else { System.out.println(f2); } } } } package com.oracle.demo2; import java.io.File; import java.io.FileFilter; public class MyFileFilterDemo implements FileFilter{ public boolean accept(File pathname) { if (pathname.isDirectory()){ return true ; } String p=pathname.getName(); return p.endsWith( ".exe" ); } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | package com.oracle.demo2; import java.io.File; public class Demo01 { public static void main(String[] args) { // 1.使用文件名称过滤器筛选将指定文件夹下的小于200K的小文件获取并打印。 File file = new File( "d:\\java\\jdk" ); get(file); } public static void get(File f){ //获取指定路径文件数组 File[] file2=f.listFiles( new MyFileDemo()); //遍历得到所有文件 for (File f2:file2){ //如果是文件夹,就继续遍历里面的文件 if (f2.isDirectory()){ get(f2); } else { System.out.println(f2); } } } } package com.oracle.demo2; import java.io.File; import java.io.FileFilter; public class MyFileDemo implements FileFilter { public boolean accept(File pathname) { if (pathname.isDirectory()){ return true ; } if (pathname.length()/ 1024 < 200 ){ return true ; } return false ; } } |
字节流
前面学的File类的一些方法操作的都是空的文件或者文件夹,没有往里面去写任何数据,现在就通过字节流去往文件中写入数据
字节输出流OutputStream
OutputStream是一个抽象类,表示所有输出字节流的所有类的祖宗类,操作的数据都是字节
常用的方法:3个write()和1个close()方法
OutputStream类之FileOutputStream子类
FileOutputStream用于写入数据到文件
构造方法:
FileOutputStream(File file):默认的覆盖文件
FileOutputStream(String name):默认的覆盖文件
FileOutputStream(String name,boolean append)
注:若appand是true,则表示可以续写文件
若append是false,则表示覆盖文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | package com.oracle.demo3; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; public class OutputStreamDemo { /* * FileOutputStream创建对象,调用构造方法时 如果你这个文件对象中的文件存在,那么就给你覆盖 如果不存在,给你创建 new * FileOutputStream(f); 如果构造方法传一个值的时候等价于new FileOutputStream(f,false);会给你覆盖 * 如果new FileOutputStream(f,true);那么可以文件续写,不给你覆盖 加“\r\n” * * 字节流操作的单位是字节 write()方法,一次只能写入一个字节 100代表SACII值里面的d * 流对象的使用步骤 * 1、创建流子类的对象,绑定数据 * 2、调用write()方法 * 3、关闭流对象,调用close()方法,释放资源 */ public static void main(String[] args) throws IOException { // File f = new File("d:\\eclipse\\demo.txt"); // FileOutputStream fos = new FileOutputStream(f, true); // fos.write(49); // fos.write(48); // fos.write(48); // 如果你传入的是负数,那么就走汉字 // 一个汉字占两个字节,一个数字占一个字节 // byte[] b={-12,-23,-30,-45}; // 传字节数组的write方法 // fos.write(b); // void write(byte[] b,int off,int len); // fos.write(b, 1, 2); // 需求:传入Hello getBytes()返回一个字节数组 // fos.write("\r\njava".getBytes()); // fos.close(); // 创建一个java.txt File f = new File( "e:\\test\\java.txt" ); FileOutputStream fos = new FileOutputStream(f, true ); fos.write( "Java是世界上最好的语言" .getBytes()); fos.close(); } } |
输出流的操作步骤:
- 创建流对象
- 调用write()方法:每次只写入一个字节
- 关闭colse
IO异常处理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | package com.oracle.demo3; import java.io.FileOutputStream; import java.io.IOException; public class ThrowsDemo { /*IOException处理细节 * 1、保证流对象的作用域足够(在块外面声明,在块里面赋值) * 2、catch里面怎么处理异常 * IO异常一旦出现,一般不能处理 * 第一:输出异常信息;第二:throw new RuntimeException * 3、流对象建立失败,还需要关闭资源么? * 加一个判断,if(fos!=null) * */ public static void main(String[] args) { FileOutputStream fos = null ; try { fos = new FileOutputStream( "e:\\test\\java.txt" ); fos.write( "Java是世界上最好的语言" .getBytes()); } catch (IOException e) { e.printStackTrace(); throw new RuntimeException( "文件写入失败,请重试" ); } finally { try { if (fos != null ) { fos.close(); } } catch (IOException e) { e.printStackTrace(); } } } } |
字节输入流InputStream
InputStream此抽象类,是表示字节输入流的所有类的祖宗类。,定义了字节输入流的基本共性功能方法。
int read():读取一个字节并返回,没有字节返回-1.
int read(byte[]): 读取一定量的字节数,并存储到字节数组中,返回读取到的字节数
InputStream类之FileInputStream子类
构造方法:
输入流操作步骤:
- 创建流对象
- Read()
- close()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | package com.oracle.demo3; import java.io.FileInputStream; import java.io.IOException; public class InputStreamDemo { public static void main(String[] args) { FileInputStream fis = null ; try { fis = new FileInputStream( "e:\\test\\java.txt" ); // read()方法一次只能读取一个字节 如果到达流的末尾,则返回 -1。 // int b = fis.read(); // byte[] b = new byte[100]; // int c = fis.read(b); // for (byte b1 : b) { // System.out.println(b1); // } // System.out.println(c); // 1、read int len = 0 ; while ((len = fis.read()) != - 1 ) { System.out.print(( char ) len); } // 2、read(byte[] b) byte [] b = new byte [ 1024 ]; int l = 0 ; while ((l=fis.read())!=- 1 ) System.out.println( new String(b, 0 , l)); } catch (IOException ex) { ex.printStackTrace(); throw new RuntimeException( "文件读取失败,请重试" ); } finally { try { fis.close(); } catch (IOException ex) { ex.printStackTrace(); } } } } |
【推荐】还在用 ECharts 开发大屏?试试这款永久免费的开源 BI 工具!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步