12、文件、IO流

114 阅读10分钟

一、文件

1.1、概念

File类:文件和目录路径名的抽象表示形式。

绝对路径:文件、文件夹的完整路径

相对路径:相对于当前项目的路径

1.2、构造函数

1.File(String path): 创建文件对象,放入字符串类型的文件路径
/*示例:
File f1 = new File("C:\Users\11245\Desktop\test\a.test");
System.out.println(f1);//C:\Users\11245\Desktop\test\a.txt
*/
2.File(String parent/*文件父路径*/,String child/*文件子路径*/):创建文件对象
/*示例:
File f2 = new File("C:\Users\11245\Desktop\test","b.txt");
System.out.println(f2);//C:\Users\11245\Desktop\test\b.txt
*/
3.File(File parent/*父类文件对象*/,String child/*文件子路径*/):创建文件对象
/*示例:
File f3 = new File("C:\Users\11245\Desktop\test");
File f4 = new File(f3,"c.txt");
System.out.println(f4);//C:\Users\11245\Desktop\test\c.txt
*/

1.3、常用方法

创建删除相关:

1.createNewFile(): 创建新文件
/*示例:
File f1 = new File("C:\Users\11245\Desktop\test\a.txt");
f1.createNewFile();//生成a.txt文件
*/
2.mkdir(): 创建文件夹
/*示例:
File f2 = new File("C:\Users\11245\Desktop\test\a");
f2.mkdir();//创建a文件夹
*/
3.mkdirs(): 创建文件夹,可以创建多层
/*示例:
File f2 = new File("C:\Users\11245\Desktop\test\a\b\c\d");
f2.mkdirs();//创建a.b.c.d多层文件夹
*/
4.delete(): 删除文件,运行到删除语句直接删除
5.deleteOnExit(): 删除文件,JVM关闭前删除

判断相关:

1.exists(): 判断是否存在,返回布尔值
2.isHidden(): 判断文件夹是否是隐藏文件
3.isFile(): 判断文件对象的路径指向是否是文件,若文件不存在,返回false
4.isDirectory(): 判断文件对象的路径指向是否是文件夹,若文件夹不存在,返回false
5.isAbsolute(): 判断文件对象指向的路径是否是绝对路径

获取相关:

1.getName(): 获取文件名
2.getPath(): 获取创建时的路径
/*示例:
File f2 = new File("a.test");
System.out.println(f2.getPath());//a.test
*/
3.getAbsolutePath(): 获取绝对路径,返回字符串的路径
/*示例:
File f2 = new File("a.test");
System.out.println(f2.getAbsolutePath());//C:\Users\11245\IdeaProjects\day08.24_File\a.test
*/
4.getAbsoluteFile(): 获取绝对路径,返回文件对象
5.getParent(): 获取父路径,返回字符串类型
/*示例:
File f1 = new File("C:\Users\11245\Desktop\test\a.txt");
System.out.println(f1.getParent());//C:\Users\11245\Desktop\test
*/
6.getParentFile(): 获取父路径,返回文件对象
7.getFreeSpace(): 获取空闲空间的大小,获取到的值以字节为单位
8.getUsableSpace(): 获取可以空间的大小,获取到的值以字节为单位
9.getTotalSpace(): 获取全部空间的大小,获取到的值以字节为单位
10.length(): 获取文件大小,获取到的值以字节为单位
1.list():获取指定目录中所有子文件子目录文件名组成的String数组
2.listFiles():获取指定目录中所有子文件子目录对象组成的File数组
3.list(FilenameFilter f):获取得到FilenameFilter的实现类中过滤得到的文件名字的字符串数组
/*示例:
  public static void main(String[] args) {
        File f = new File("C:\Users\11245\Desktop\test");
        MyFilenameFilter1 mf1 = new MyFilenameFilter1();
        String[] str = f.list(mf1);
        System.out.println(str.length);
        System.out.println(Arrays.toString(str));
  }
//定义一个FilenameFilter实现类,重写accept方法,用于过滤文件   
class MyFilenameFilter1 implements FilenameFilter{
  @Override
  public boolean accept(File dir, String name) {
        return name.endsWith(".wmv");
  }
}
​
*/
4.listFiles(FilenameFilter f):获取得到FilenameFilter的实现类中过滤得到的文件对象的对象数组
/*示例:
   public static void main(String[] args) {
     File f = new File("C:\Users\11245\Desktop\test");
     MyFilenameFilter2 mf2 = new MyFilenameFilter2();
     File[] files = f.listFiles(mf2);//获得过滤后的文件数组
     System.out.println(Arrays.toString(files));
     }
class MyFilenameFilter2 implements FilenameFilter{
    //获取文件中视频大小超过100MB的文件
    @Override
    public boolean accept(File dir, String name) {
        //要获取大小,就要用文件对象调用length方法,所以先创建文件对象
        File f = new File(dir,name);
        long l = f.length();
        if(l <= 100*1024*1024){
            return false;
        }
        return name.endsWith(".wmv");
    }
}
*/
5.listFiles(FileFilter f):获取得到FileFilter的实现类中过滤得到的文件对象的对象数组,在重写的accecpt中参数就是文件对象,直接可以调用文件对象的方法。
/*示例:
public class Test3 {
   public static void main(String[] args) {
       File f = new File("C:\Users\11245\Desktop\test");
       MyFileFilter mf = new MyFileFilter();
       File[] files = f.listFiles(mf);
       System.out.println(Arrays.toString(files));
​
   }
}
​
class MyFileFilter implements FileFilter {
   //过滤得到文件夹中大于100MB的文件
   @Override
   public boolean accept(File pathname) {
       return  pathname.length() > 100*1024*1024;
   }
}
*/
​
------------------------------------------------------------------------        
/*
FilenameFilter是一个接口,有抽象方法accept(File dir,String name),
参数1:当前遍历的目录对象
参数2:当前目录下的子文件子目录的名字
​
FileFilter是一个接口,有抽象方法accecpt(File pathname),
参数:当前目录下子文件子目录的文件对象
*/  

3.2、递归

示例1:使用递归的方法求1100的和
public class Test2 {
 public static void main(String[] args) {
     System.out.println(f(100));
 }
 public static int f(int n){
     if(n == 1){
         return 1;
     }
     return f(n-1) + n;//递归调用
 }
}
--------------------------------------------------------------------------
示例2:使用递归的方法求斐波那契数列的值
public class Test2 {
 public static void main(String[] args) {
     System.out.println(g(7));
 }
 public static int g(int n){
     if(n == 1 || n == 2){
         return 1;
     }
     return g(n-1) + g(n-2);
 }
}
---------------------------------------------------------------------------
示例3:使用递归的方法输出多层文件夹目录中的所有文件
public class Test {
 public static void main(String[] args) {
     File f = new File("C:\Users\11245\Desktop\test");
     f(f);
 }
 //使用递归的方法获取多级目录下的所有文件
 public static void f(File f){
     File[] files = f.listFiles();
     for (File file : files){
         if(file.isFile()){
             System.out.println(file);
         }else {
             f(file);
         }
     }
 }
}

二、IO流

2.1、概念

我们把数据的传递看成是数据的流动,就将这个传递的过程称为输入输出流,也就是IO流

I:input

O:output

IO流的分类:

  1. 根据流向来划分

    1. 输入流:外界=>内部
    2. 输出流:内部=>外界
  2. 根据数据的类型来划分

    1. 字节流:可以操作任何类型的文件
    2. 字符流:只能操作文本

四个顶层父类:它们都是抽象类

  1. 字节输入流:InputStream
  2. 字节输出流:OutputStream
  3. 字符输入流:Reader
  4. 字符输出流:Writer

2.2、FileOutputStream文件字节输出流

构造函数:

1.FileOutputStream(File f): 向文件对象指向的路径输出
2.FileOutputStream(String s): 向字符串指向的路径输出
3.FileOutputStream(File f,boolean append):向文件对象指向的路径输出,boolean值为true,表示可以续写,boolean值为flase,表示不可以续写
4.FileOutputStream(String f,boolean append):向字符串指向的路径输出,boolean值为true,表示可以续写,boolean值为flase,表示不可以续写

常用方法:

1.write(int b): 传入int类型的值,在对应路径的文件中写入对应的字符
/*示例:
File f = new File("C:\Users\11245\Desktop\test\a.txt");
FileOutputStream fos = new FileOutputStream(f,true);
fos.write(98);
fos.write(99);
fos.write(100);
*/
2.write(byte[] b): 通过字节数组在文件中写入对应的字符
/*示例:
byte[] by = {98,99,100,101,102};
fos.write(by);
fos.write("你好啊".getBytes());
*/
3.write(byte[] b,int offset,int len):从字节数组offset下标开始,写入对应个数为len的对应字符
4.close(): 关闭流

2.3、FileInputStream文件字节输入流

构造函数:

1.FileInputStream(File f): 传入文件对象,用于读取
2.FileInputStream(String s): 传入字符串的地址,用于读取该路径下的文件

常用方法:

1.read(): 读取文件中的一个字节,返回该字节对应的int类型的值
/*示例:
FileInputStream fis = new FileInputStream            ("C:\Users\11245\Desktop\test\a.txt");//cdef
System.out.println((char) fis.read());//c
System.out.println((char)fis.read());//d
*/
2.read(byte[] b):获取字节数组读取到的字节的个数
/*示例:
FileInputStream fis = new FileInputStream("文件路径");
byte[] b = new byte[3];
int len;
String s = "";
while((len = fis.read(b)) != -1){
     s += new String(b,0,len);
}
System.out.println(s);
*/

练习:

示例:
//剪切文件到另一个路径
public static void main(String[] args) throws Exception{
        //删除必须要有一个文件对象
        File f = new File("原文件地址");
        FileInputStream fis = new FileInputStream(f);
        FileOutputStream fos = new FileOutputStream("要拷贝到的地址");

        byte[] b = new byte[3];
        int len;
        while((len = fis.read(b)) != -1){
            fos.write(b,0,len);
        }
        //f.delete();不能够成功删除,因为还存在流对象在使用文件对象
        //f.deleteOnExit();可以成功删除,因为它是在JVM关闭前执行删除的
        fis.close();
        fos.close();
        //f.delete();可以成功删除
    }

2.4、FileWriter文件字符输出流

构造函数:

1.FileWriter(File f):向文件对象指向的路径输出
2.FileWriter(String s):向字符串指向的路径输出
3.FileWriter(File f,boolean append):向文件对象指向的路径输出,boolean值为true,表示可以续写,boolean值为flase,表示不可以续写
4.FileWriter(String f,boolean append):向字符串指向的路径输出,boolean值为true,表示可以续写,boolean值为flase,表示不可以续写

常用方法:

1.write(int b): 传入int类型的值,在对应路径的文件中写入对应的字符
2.write(String s): 传入字符串类型的值,在对应路径的文件中写入对应的字符串
3.write(String s,int offset,int len):传入字符串类型的值,在对应路径的文件中写入对应的从字符串指定位置开始,长度指定的字符串
4.write(char[] chs): 将字符数组中的对应字符放入指定文件中
5.write(char[] chs,int offset,int len):从字符数组offset下标开始,写入对应个数为len的对应字符
6.flush():才能将缓冲区中的内容写入到目标文件
7.close():关闭流,同时可以将缓冲区中的内容写入到目标文件
// 注:字符流输出时,先将内容写入到缓冲区中,要通过调用flush()或者close()才能将缓冲区中的内容写入到目标文件,它们的区别是flush()后流对象还能使用,而close()后流对象被释放,如果再使用流对象会发生IO异常

2.5、FileReader文件字符输入流

构造函数:

1.FileReader(File f):传入文件对象,用于读取
2.FileReader(String s):传入字符串的地址,用于读取该路径下的文件

常用方法:

1.read():读取文件中的一个字节,返回该字节对应的int类型的值
2.read(char[] chs):获取字节数组读取到的字节的个数
/*示例:
FileReader fr = new FileReader("C:\Users\11245\Desktop\test\b.txt");
char[] c = new char[2];
int len;
StringBuilder sb = new StringBuilder();
while ((len = fr.read(c)) != -1){
     sb.append(new String(c,0,len));
}
System.out.println(sb);
*/
3.close():关闭流

2.6、缓冲流

缓冲流也称为高效流,它是4个基本文件流的加强

注:缓冲流不能直接放路径和文件对象,缓冲流放的是流对象

BufferedInputStream:字节缓冲输入流

FileInputStream fis = new FileInputStream("对象文件地址");
BufferedInputStream bis = new BufferedInputStream(fis);

BufferedOutputStream:字节缓冲输出流

FileOutputStream fos = new FileOutputStream("对象文件地址");
BufferedOutputStream bos = new BufferedOutputStream(fos);

BufferedReader:字符缓冲输入流

FileWriter fw = new FileWriter("对象文件地址");
BufferedWriter bw = new BufferedWriter(fw);

BufferedWriter:字符缓冲输出流

FileReader fr = new FileReader("对象文件地址");
BufferedReader br = new BufferedReader(fr);

以上4个缓冲流中的功能与4个基本文件流的功能相同,但是在BufferedReader和BufferedWriter中额外定义了两个新方法:

  1. BufferedReader中readLine()

    FileWriter fw = new FileWriter("C:\Users\11245\Desktop\test\a.txt");
    BufferedWriter bw = new BufferedWriter(fw);
    bw.write("你好啊!");
    bw.newLine();
    bw.write("嘿嘿嘿嘿嘿");
    bw.flush();
    /*你好啊!
      嘿嘿嘿嘿嘿*/
    
  2. BufferedWriter中的newLine()

    FileReader fr = new FileReader("C:\Users\11245\Desktop\test\a.txt");
    BufferedReader br = new BufferedReader(fr);
    String s = "";
    String str;
    while ((str = br.readLine()) != null){
          s += str + '\n';
    }
    System.out.println(s);
    

2.7、对象流

对象流使程序可以将对象存储到文件中,还可以从文件中将对象读取到程序中

将对象存储到文件的过程称为序列化

从文件中将对象读取到程序的过程称为反序列化

ObjectInputStream、ObjectOutputStream

注:

  1. 如果要将一个类的对象序列化到文件中,那么这个类必须实现接口Serializable
例如:public class Student implements Serializable {
    private String name;
    private  int age;
}
  1. 如果写入对象时类的结构与读取对象时类的结构不同,那么读取时会发生InvalidClassException

关键字:transient瞬态的,被transient修饰的成员变量不会随着对象的序列化而存储

例如:public class Student implements Serializable {
   transient private String name;
   private  int age;
   }
   读写后的结果为:Student{name='null', age=34}