File类和IO流

本文详细介绍了Java中的File类,包括创建、判断、获取和删除文件与目录的功能,以及递归操作。接着深入探讨了IO流,涵盖字节流和字符流,包括写数据、读数据的方法、缓冲流的使用,以及字符流中的编码解码问题。

IO流小结

在这里插入图片描述

1.File类

  • 文件和目录路径名的抽象表示。

  • 文件和目录是可以通过File封装成对象的

  • 对于File而言,其封装的并不是一个真正存在的文件,仅仅是一个路径名而已。**它可以是存在的,也可以是不存在的.**将来是要通过具体的操作把这个路径的内容转换为具体存在的
    构造方法

      • File(File parent, String child) 从父抽象路径名和子路径名字符串创建新的 File实例。
        File(String pathname) 通过将给定的路径名字符串转换为抽象路径名来创建新的 File实例。
        File(String parent, String child) 从父路径名字符串和子路径名字符串创建新的 File实例。
public class FileDemo01 {
    public static void main(String[] args) {
        File f = new File("F:\\Java学习\\黑马资料\\JavaEE资料和习题\\资料");
        System.out.println(f);
    }
}

File类创建功能(先创建目录,在创建文件)

public boolean createNewFiLe(): 当具有该名称的文件不存在时,创建一个由该抽象路径名命名的新空文件
如果文件不存在,就创建文件,并返回true
如果文件存在,就不创建文件,并返回false
public booLean mkdir( ): 创建由此抽象路径名命名的目录
public boolean mkdirs ( ): 创建由此抽象路径名命名的目录,包括任何必需但不存在的父目录

public class FileDemo02 {
    public static void main(String[] args) throws IOException {
        //需求1:我要在F:\\test目录下创建一个文件java.txt
        //需求2:我要在F:\\test目录下创建一个目录JavaSE
        //需求3:我要在F:\\test目录下创建一个多级目录JavawEB\\HTML
        //需求4:我要在F:\\test目录下创建一个文件javase.txt


        //需求1:我要在F:\\test目录下创建一个文件java.txt
        File f1 = new File("F:\\test\\java.txt");
        System.out.println(f1.createNewFile());

        // 需求2我要在F:\\test目录下创建一个目录JavaSE
        File f2 = new File("F:\\test\\JavaSE");
        System.out.println(f2.mkdir());

        //需求3:我要在F:\\test目录下创建一个多级目录JavawEB\\HTML
        File f3 = new File("F:\\test\\JavaEB\\HTML");
        System.out.println(f3.mkdirs());

        //需求4。我要在F:\\test目录下创建一个文件javase.txt
        File f4 = new File("F:\\test\\java.txt");
        System.out.println(f4.mkdir());
    }
}

File类的判断和获取功能

public boolean isDirectory() 测试此抽象路径名表示的File是否为目录
public boolean isFile() 测试此抽象路径名表示的File是否为文件
public boolean exists() 测试此抽象路径名表示的File是否存在

public String getAbsolutePath() 返回此抽象路径名的绝对路径名字符串 F:\test\JavaSE\java.txt
public String getPath() 将此抽象路径名转换为路径名字符串 JavaSE\java.txt
public String getName() 返回由此抽象路径名表示的文件或目录的名称 java.txt

public String[] list() 返回此抽象路径名表示的目录中的文件和目录的名称字符串数组
publicFile[] listFiles() 返回此抽象路径名表示的目录中的文件和日录的File对象数组

File类的删除功能

public boolean delete() 删除由此抽象路径名表示的文件或目录

绝对路径和相对路径的区别

绝对路径:完整的路径名,不需要任何其他信息就可以定位它所表示的文件。

例如: E:\itcast\lJjava.txt

相对路径:必须使用取自其他路径名的信息讲行解释。

例: myFile\iava.txt

递归

​ 方法定义中调用方法本身的现象。

递归解决问题的思路:
把一个复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解递归策略只需少量的程序就可描述出解题过程所需要的多次重复计算

​ 递归解决问题要找到两个内容:
​ 递归出口:否则会出现内存溢出
​ 递归规则:与原问题相似的规模较小的问题

递归求阶乘

需求:用递归求5的阶乘,并把结果在控制台输出
分析:
阶乘:一个正整数的阶乘是所有小于及等于该数的正整数的积,自然数n的阶乘写作n!
5!= 54321
递归出口:1!=1递归规则: n!=n*(n-1)!
5!= 5*4!

public class JcDemo {
    public static void main(String[] args) {
        int i = jc(5);
        System.out.println(i);
    }
    public static int jc(int n){
        if (n == 1) {
            return 1;
        }else {
            return n*jc(n-1);
        }
    }
}

//结果120

遍历目录

需求

​ 给定一个路径(E\Vitcast),请通过递归完成遍历该目录下的所有内容,并把所有文件的绝对路径输出在控制台

思路:

​ 根据给定的路径创建一个File对象
​ 定义一个方法,用于获取给定目录下的所有内容,参数为第1步创建的File对象获取给定的File目录下所有的文件或者目录的File数组
​ 遍历该File数组,得到每一个File对象
​ 判断该File对象是否是目录
​ 是:递归调用
​ 不是:获取绝对路径输出在控制台调用方法

public class JcDemo02 {
    public static void main(String[] args) {
        File f = new File("F:\\");
           getAllFile(f);
    }

    public static void getAllFile(File file) {
        File[] listArray = file.listFiles();
        if (listArray != null) {
            for (File f : listArray) {
                if (f.isDirectory()) {
                  getAllFile(f);   // getAllFile(file);StackOverflowError:当堆栈溢出发生时抛出一个应用程序递归太深
                } else {
                  System.out.println(f.getAbsolutePath());
                }
            }
        }
    }
}

2.IO流

IO流概述:
I0:输入/输出(Input/Output)
流:是一种抽象概念,是对数据传输的总称。也就是说数据在设备间的传输称为流,流的本质是数据传输IO流就是用来处理设备间数据传输问题的
常见的应用:文件复制;文件上传;文件下载

IO流分类;
按照数据的流向

输入流:读数据 (硬盘—>内存)读数据

输出流:写数据按照数据类型来分 (内存—>硬盘)写数据
字节流
字节输入流;字节输出流亨符流
字符输入流;字符输出流
—般来说。我们说IO流的分类是按照数据类型来分的那么这两种流都在什么情况下使用呢?
如果数据通过Window自带的记事本软件打开,我们还可以读懂里面的内容,就使用字符流,否则使用字节流。如果你不知道该使用哪种类型的流,就使用字节流

字节流

字节流抽象基类
lnputStream:这个抽象类是表示字节输入流的所有类的超类

​ OutputStream:这个抽象类是表示字节输出流的所有类的超类

​ 子类名特点:子类名称都是以其父类名作为子类名的后缀

FileOutputStream:文件输出流用于将数据写入File
FileOutputStream(String name):创建文件输出流以指定的名称写入文件

使用字节输出流写数据的步骤:

​ 1.创建字节输出流对象(调用系统功能创建了文件,创建字节输出流对象,让字节输出
​ 2.调用字节输出流对象的写数据方法
​ 3.**释放资源(**关闭此文件输出流并释放与此流相关联的任何系统资源)

有两个构造方法:学一个够了

public class FileOutPutStream {
    public static void main(String[] args) throws IOException {
        FileOutputStream fos = new FileOutputStream("F:\\test\\java.txt");
        fos.write(97);
        fos.close();
    }
}

字节写数据的三种方式

​ void write(int b) 一次写一个

​ void write(byte[] b) 将b.length的字节全部写出来

​ void write(byte[] b,int off,int length) 写出指定的长度

byte[] b = “abcdefg”.getByte() String类中的获取字节数组的方法

public class FileOutPutStream02 {
    public static void main(String[] args) throws IOException {
        FileOutputStream fos = new FileOutputStream("F:\\test\\fos.txt");
        byte[] b = "abcdefg".getBytes();    // String类中的获取字节数组的方法
        fos.write(b);
        fos.close();
    }
}

字节流写数据遇到2个小问题(换行/追加写入)

字节流写数据如何实现换行呢?
写完数据后,加换行符
windows:\r\n

linux:\n

mac:\r
字节流写数据如何实现追加写入呢?
public FileOutputStream(String name,boolean append)
创建文件输出流以指定的名称写入文件。如果第二个参数为true,则字节将写入文件的末尾而不是开头

public class FileOutPutStream03 {
    public static void main(String[] args) throws IOException {
        FileOutputStream fos = new FileOutputStream("F:\\test\\fos.txt",true);//参数true
        for (int i = 0; i <10 ; i++) {
            byte[] b = "abcdefg\n".getBytes();       //加入换行符
            fos.write(b);
        }
        fos.close();
    }
}

字节流写数据异常处理

​ finally:在异常处理时提供finally块来执行所有清除操作。

​ 比如说IO流中的释放资源特点:被finally控制的语句一定会执行,除非JVM退出

public class FileOutPutStreamDemo03 {
    public static void main(String[] args) {
        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream("F:\\test\\java.txt");
            byte[] b = "aaabbbccc".getBytes();
            fos.write(b);

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (fos != null) {
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

字节流读数据(读字节)

读数据的步骤和写数据的差不多。三步走

public class FileInputStreamDemo {
    public static void main(String[] args) throws IOException {
        FileInputStream fis = new FileInputStream("F:\\test\\java.txt");
        int i;
        //1.读数据:fis.read()
        //2.赋值:将读取的数据赋值给i
        //3.判断:读取到文件末尾,值为-1
        while ((i = fis.read())!= -1){
            System.out.print((char)i);
        }
        fis.close();
    }
}

字节流复制文本文件

先读后写

public class FileInputStreamDemo02 {
    public static void main(String[] args) throws IOException {
        //复制文本文件,先读后写
        FileInputStream fis = new FileInputStream("F:\\test\\java.txt");
        FileOutputStream fos = new FileOutputStream("F:\\test\\JavaSE\\java.txt");
        int by;
        while ((by=fis.read()) != -1){
            fos.write(by);
        }
        fis.close();
        fos.close();
        
    }
}

字节流读数据(读字节数组)

public class FileInputStreamDemo03 {
    public static void main(String[] args) throws IOException {
        FileInputStream fis = new FileInputStream("F:\\test\\java.txt");
        byte[] by = new byte[1024];//容器,一般是1024的倍数
        int len;
        while ((len = fis.read(by)) != -1){//fis.read(by)读取by个存入到数组。len实际读取的长度
            System.out.println(new String(by,0,len));//只把0-实际长度转成字符串
        }
        fis.close();
    }
}

字节流复制图片略

字节缓冲流(重点)

字节缓冲流:
BufferOutputStream:该类实现缓冲输出流。通过设置这样的输出流,应用程序可以向底层输出流写入字节,而不必为写入的每个字 节导致底层系统的调用
BufferedlnputStream:创建BufferedlnputStream将创建一个内部缓冲区数组。当从流中读取或跳过字节时,内部缓冲区将根据需要 从所包含的输入流中重新填充,一次很多字节
构造方法:
字节缓冲输出流:BufferedOutputStream(OutputStream out)字节缓冲输入流: BufferedInputStream(InputStream in)t
为什么构造方法需要的是字节流。而不是具体的文件或者路径呢?
●字节缓冲流仅仅提供缓冲区,而真正的读写数据还得依靠基本的字节流对象进行操作

字节缓冲流读数据和写数据

public class BufferedInputOutputStreamDemo01 {
    public static void main(String[] args) throws IOException {
//        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("F:\\test\\java.txt"));
//        byte[] bys = "abcde\r\n".getBytes();
//        byte[] bys2 = "fijklmn\r\n".getBytes();
//        bos.write(bys);
//        bos.write(bys2);
//        bos.close();
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("F:\\test\\java.txt"));
        //第一种
//        int by;
//        while ((by = bis.read()) != -1){
//            System.out.print((char)by);
//        }
        //第二种
        byte[] bys =  new byte[1024];
        int len;
        while ((len = bis.read(bys)) != -1){
            System.out.print(new String(bys,0,len));
        }
    }
}

字节流复制视频

先读后写

四种方式实现复制视频,并记录每种方式复制视频的时间
1:基本宁节流一次读写一个字节
共耗时:64565毫秒
2:基本宁节流一次读写一个字节数组
共耗时:107毫秒
3:字节缓冲流一次读写一个字节
共耗时:465毫秒
4**:字节缓冲流一次读写一个字节数组**
共耗时:64毫秒

字符流

由于字节流操作中文不是特别的方便,所以ava就提供字符流

字符流=字节流+编码表

用字节流复制文本文件时,文本文件也会有中文,但是没有问题,原因是最终底层操作会自动进行字节拼接成中文,

如何识别是中文的呢?
汉字在存储的时候。无论选择哪种编码存储,第一个字节都是负数

编码表

计算机中储存的信息都是用二进制数表示的;我们在屏幕上看到的英文、汉字等字符是二进制数转换之后的结果

按照某种规则,将字符存储到计算机中,称为编码。反之,将存储在计算机中的二进制数按照某种规则解析显示出来,称为解码。

这里强调一下:

按照A编码存储,必须按照A编码解析,这样才能显示正确的文本符号。否则就会导致乱码现象

常用的字符编码 GBK UTF-8(3字节)

public class UtfGbkDemo01 {
    public static void main(String[] args) throws UnsupportedEncodingException {
        String s = "中国";
//        byte[] by = s.getBytes();//编码
//        System.out.println(Arrays.toString(by));//[-28, -72, -83, -27, -101, -67]
//        byte[] by2 = s.getBytes("UTF-8");
//        System.out.println(Arrays.toString(by2));//[-28, -72, -83, -27, -101, -67]
        byte[] gbks = s.getBytes("GBK");
        System.out.println(Arrays.toString(gbks));//[-42, -48, -71, -6]

        //解码
//        String s1 = new String(by);
//        System.out.println(s1);//中国
//        String s2 = new String(by,"UTF-8");
//        System.out.println(s2);//中国
        String s3 = new String(gbks,"GBK");
        System.out.println(s3);//中国
    }
}

字符流中的编码解码问题

字符流抽象基类

Reader :字符输入流的抽象类·
Writer:字符输出流的抽象类

字符流中和编码解码问题相关的两个:

OutputstreamWriter

lnputStreamReader

构造方法4个:

    • OutputStreamWriter(OutputStream out) 创建一个使用默认字符编码的OutputStreamWriter。
      OutputStreamWriter(OutputStream out, Charset cs) 创建一个使用给定字符集的OutputStreamWriter。
 OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("F:\\test\\osw.txt"),"UTF-8");

字符流写入数据的5种方式加2种刷新

    • voidclose() 关闭流,先刷新。
      voidflush() 刷新流。
      StringgetEncoding() 返回此流使用的字符编码的名称。
      voidwrite(char[] cbuf, int off, int len) 写入字符数组的一部分。
      voidwrite(int c) 写一个字符
      voidwrite(String str, int off, int len) 写一个字符串的一部分。

​ void write(int c)写一个字符

​ void write(String str)写一个字符串

public class OutputStreamWriterDemo01 {
    public static void main(String[] args) throws IOException {
        OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("F:\\test\\osw.txt"),"UTF-8");
             osw.write(97);
             osw.write("\r\nabcd");
             osw.flush();
             char[] c = {'a','b','d'};
             osw.write(c);//a  abcdabd
             osw.close();
             
    }
}

字节流读数据2种方式

    • intread() 读一个字符
      intread(char[] cbuf, int offset, int length) 将字符读入数组的一部分。
public class InputStreamReaderDemo01 {
    public static void main(String[] args) throws IOException {
        InputStreamReader isr = new InputStreamReader(new FileInputStream("F:\\test\\osw.txt"), "UTF-8");
        //第一种
//        int ch;
//        while ((ch = isr.read()) != -1){
//            System.out.print((char) ch);
//        }
        //第二种
        int ch2;
        char[] c = new char[1024];
        while ((ch2 = isr.read(c))!= -1){
            System.out.print(new String(c),0,len);
        }
    }
}

案例 复制java类文件

需求:把模块目录下的“ConversionStreamDemo.java”复制到模块目录下的“Copy.java"
分析:
转换流的名字比较长,而我们常见的操作都是按照本地默认编码实现的,所以,为了简化书写,转换流提供了对应的子类FileReader:用于读取字符文件的便捷类
FileReader(String fileName)
FileWriter:用于写入字符文件的便捷类
FileWriter(String fileName)

按照具体情况使用

public class BufferedWriteDemo02 {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new FileReader("F:\\test\\OutputInputDemo.java"));
        BufferedWriter bw = new BufferedWriter(new FileWriter("F:\\test\\JavaSE\\OutputInputDemo.java"));
//        int len;
//        char[] c = new char[1024];        ******************************重点************************
//        while ((len = br.read(c)) != -1){  //千万别忘传入数据c
//         bw.write(c,0,len);         //记住设置读取的实际长度

 //       }
        int by;
        while ((by = br.read()) != -1){
            bw.write(by);
        }
        bw.close();
        br.close();
    }
}

字符缓冲流(重点)

不改变之前写的:在构造方法中加append:ture

BufferedWriter:

​ 将文本写入字符输出流,缓冲字符,以提供单个字符,数组和字符串的高效写入,可以指定缓冲区大小,或者可以接受默认大小。默 认值足够大,可用于大多数用途
BufferedReader:

​ 从字符输入流读取文本,缓冲字符,以提供字符,数组和行的高效读取,可以指定缓冲区大小,或者可以使用默认大小。默认值足够 大,可用于大多数用途

构造方法:
BufferedWriter(Writer out)

​ BufferedReader(Reader in)

public class BufferedReaderWriterDemo {
    public static void main(String[] args) throws IOException {
//        BufferedWriter bw = new BufferedWriter(new FileWriter("F:\\test\\java.txt"));
//        bw.write("abcde\r\n");
//        bw.write("qwer\r\n");
//        bw.close();
        BufferedReader br = new BufferedReader(new                        FileReader("F:\\test\\java.txt"));//("F:\\test\\java.txt")它的构造方法
//        int ch;
//        while ((ch = br.read()) != -1){
//            System.out.print((char)ch);
//        }
        int len;
        char[] c = new char[1024];
        while ((len = br.read(c)) != -1){
            System.out.print(new String(c,0,len));//0-len
        }
    }
}

字符缓冲流的特有功能

BufferedWriter:
void newLine():写一行行分隔符,行分隔符字符串由系统属性定义

BufferedReader:
public String readLine():读一行文字。结果包含行的内容的字符串,不包括任何行终止字符,如果流的结尾已经到达,则为null

public class OutputStreamWriteDemo {
    public static void main(String[] args) throws IOException {
//        BufferedWriter bw = new BufferedWriter(new FileWriter("F:\\test\\java.txt"));
//
//        for (int i = 0; i <10 ; i++) {
//            bw.write("Hello"+i);
////            bw.write("\r\n");
//            bw.newLine();
//            bw.flush();
//        }
//        bw.close();
        BufferedReader br = new BufferedReader(new FileReader("F:\\test\\java.txt"));
//        String line = br.readLine();
//        System.out.println(line);
        String line;
        while ((line = br.readLine()) != null){
            System.out.println(line);//println  手动加换行
        }
        br.close();
    }
}

案例 复制java文件升级版

public class JavaCopyDemo {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new FileReader("F:\\test\\OutputInputDemo.java"));
        BufferedWriter bw = new BufferedWriter(new FileWriter("F:\\test\\JavaSE\\OutputInputDemo.java"));
          String line;
          while ((line = br.readLine()) != null){ //如果一行里还有字符串
              bw.write(line);//1.写字符
              bw.newLine();  //2.换行符
              bw.flush();    //3.刷新
          }
          br.close();
          bw.close();
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值