10.IO流(一)

本文详细介绍了Java中的IO流,包括File类的使用、方法递归的概念及其应用、字符集编码解码,以及字节流和输出流的基础知识。此外,还涵盖了如何处理文件操作,如创建、删除、遍历文件夹,以及递归算法的实现和文件搜索案例。
摘要由CSDN通过智能技术生成

文章目录

IO流

一、File

1.创建对象

1.1 创建File类的对象
构造器说明
public File(String pathname)根据文件路径创建文件对象(文件/文件夹/绝对路径/相对路径)
public File(String parent,String child)根据父路径和子路径名字创建文件对象
public FIle(File parent,String child)根据付路径文件对象和子路径名字创建文字对象
1.2 注意
  • File对象既可以代表文件、也可以代表文件夹
  • File封装的对象仅仅是一个路径名,这个路径可以是存在的,也允许是不存在的
1.3 绝对路径、相对路径
  1. 绝对路径:从盘符开始 (例 D:\\JavaCode\\a.txt 或 D:/JavaCode/a.txt)
  2. 相对路径:不带盘符,默认直接到当前工程下的目录寻找文件 (例 TxtFile\\a.txt 或 TxtFile/a.txt)

2.常用方法1:判断文件类型、获取文件信息

方法名称说明
public boolean exists()判断当前文件对象,对应的文件路径是否存在,存在返回true
public boolean isFile()判断当前文件对象指代的是否是文件,是文件返回true,反之
public boolean isDirectorv()判断当前文件对象指代的是否是文件夹,是文件夹返回true,反之。
public String getName()获取文件的名称 (包含后缀)
public long length()获取文件的大小,返回字节个数
public long lastModified()获取文件的最后修改时间
public String getPath()获取创建文件对象时,使用的路径
public String getAbsolutePath()获取绝对路径
import java.io.File;

public class FileDemo1 {
    public static void main(String[] args) {
        File file = new File("b.txt");
        File[] files = file.listFiles();
        for (File f : files) {
            System.out.println(f.getAbsoluteFile());
        }
    }
}

3.常用方法2:创建文件、删除文件

3.1 File类创建文件的功能
方法名称说明
public boolean createNewFile()创建一个新的空的文件
public boolean mkdir()只能创建一级文件夹
public boolean mkdirs()可以创建多级文件夹
3.2 File类删除文件的功能
方法名称说明
public boolean delete()删除文件、空文件夹

注意delete()默认只能删除文件和空文件夹,删除后的文件不会键入回收站

4.常用方法3:遍历文件夹

4.1 File类提供的遍历文件夹的功能
方法名称说明
public String[] list()获取当前目录下所有的"一级文件名称"到一个字符串数组中去返回
public File[] listFiles()获取当前目录下所有的"一级文件对象"到一个文件对象数组中去返回(重点)
4.2 使用listFiles()方法时的注意事项
  • 当主调是文件,或者路径不存在时,返回null
  • 当主调是空文件夹时,返回一个长度为0的数组
  • 当主调是一个有内容的文件夹时,将里面所有一级文件和文件夹的路径放在File数组中返回
  • 当主调是一个文件夹,且里面有隐藏文件时,将里面所有文件和文件夹的路径放在File数组中返回,包含隐藏文件
  • 当主调是一个文件夹,但是没有权限访问该文件是,返回null

二、前置知识:方法递归

1.认识递归的形式

1.1 方法递归概述
  • 递归是一种算法,在程序设计语言中广泛应用
  • 从形式上说:方法调用自身的方式称为方法递归(recursion)
1.2 递归的形式
  • 直接递归:方法自己调用自己
  • 简介递归:方法调用其他方法,其他方法又回调自己
1.3 使用方法递归是需要注意的问题

递归如果没有控制好终止,会出现死循环,导致栈内存溢出错误(StackOverflowException)

2.应用、执行流程、算法思想

2.1 递归算法三要素
  • 递归的公式: f(n) = f(n-1) * n
  • 递归的终结点: f(1)
  • 递归的防线必须走向终结点
2.2 案例:使用递归计算阶乘
public class Demo1 {
    public static void main(String[] args) {
        System.out.println(factorial(5));
        System.out.println(sum(100));
    }

    //计算阶乘递归
    public static int factorial(int n) {
        //递归没有出口的话,报错: StackOverflowError 栈内存溢出
        if (n == 1) { //递归出口
            return 1;
        }
        return factorial(n - 1) * n;
    }

    //求和 递归
    public static int sum(int n) {
        if (n == 1) {
            return 1;
        } else {
            return sum(n - 1) + n;
        }
    }
}

3.其他应用:文件搜索

3.1 从D盘中搜索“QQ.exe”文件,找到后直接输出其位置
import java.io.File;
/**
 * @description: 在指定盘符下寻找 QQ.exe 文件【遍历查找,并输出此文件的绝对路径】
 */
public class QQFileFindDemo {
    public static void main(String[] args) {
        findQQ(new File("D:\\"));
    }

    //定义方法
    public static void findQQ(File file) {
        //1.判断路径是否存在
        if (!file.exists()) { //不存在直接结束方法
            return;
        }
        //2.判断路径是文件夹还是文件
            //2.1 文件
        if (file.isFile()) {
            if ("QQ.exe".equals(file.getName())) { //找到了
                System.out.println(file.getAbsolutePath()); //打印绝对路径
                return; //找到后结束方法
            }
        } else { //2.2 文件夹
            File[] files = file.listFiles();
            //如果没有权限访问的话,files就是null,直接结束方法
            if (files == null){
                return;
            }
            //说明文件夹可以访问,则递归调用 findQQ 方法继续查找
            for (File f : files) {
                findQQ(f);
            }
        }
    }
}
3.2 删除非空文件夹
import java.io.File;

public class DeleteSpecifyDir {
    public static void main(String[] args) {
        deleteDir(new File("E:\\abc"));
    }

    //删除非空文件夹
    public static void deleteDir(File file){
        //1.判断路径是否存在
        if (!file.exists()){ //不存在
            return;
        }
        //2. 文件夹
        File[] files = file.listFiles();
        if (files == null){
            return;
        }
        for (File f : files) {
            if (f.isFile()){
                f.delete();
            }else {
                deleteDir(f);
            }
        }
        //删除自己这个空文件夹
        file.delete();
    }
}

三、前置知识:字符集

1.常见字符集介绍

1.1 标准ASCII字符集
  • 美国信息交换标准代码,包括了英文、符号等。
  • 标准ASCII使用1个字节存储一个字符,首位是0,总共可表示128个字符,对美国佬来说完全够用
1.2 GBK(汉字内码扩展规范,国标)
  • 汉字编码字符集,包含了2万多个汉字等字符,GBK中一个中文字符编码成两个字节的形式存储
  • 注意:GBK兼容了ASCII字符集【GBK规定:汉字的第一个字节的第一位必须是1】
1.3 Unicode字符集(统一码,也叫万国码)
  • Unicode是国际组织指定的,可以容纳世界上所有文字、符号的字符集

  • UTF-32 :4个字节表示一个字符

  • UTF-8

    • 是Unicode符集的一种编码方案,采取可变长编码方案,共分四个长度区:1个字节,2个字节,3个字节,4个字节
    • 英文字符、数字等只占1个字节(兼容标准ASCII编码),汉字字符占用3个字节
  • 要点

    • ASCI字符集:只有英文、数字、符号等,占1个字节
    • GBK字符集:汉字占2个字节,英文、数字占1个字节
    • UTF-8字符集:汉字占3个字节,英文、数字占1个字节

    注意

    注意1:字符编码时使用的字符集,和解码时使用的字符集必须一致,,否则会出现乱码

    注意2:英文,数字一般不会乱码,因为很多字符集都兼容了ASCII编码

2.字符集的编码、解码操作

2.1 编码
String提供了如下方法说明
byte[] getBytes()使用平台的默认字符集将该String编码为一系列字节,将结果存储到新的字节数组
byte[] getBytes(String charsetName)使用指定的字符集将该String编码为一系列字节,将结果存储到新的字节数组
2.2 解码
String提供了如下方法说明
String(byte[] bytes)通过使用平台的默认字符集解码指定的字节数组来构造新的String
String(byte[] bytes,String charsetName)通过指定的字符集解码指定的字节数组来构造新的String
import java.util.Arrays;

public class CharSetDemo1 {
    public static void main(String[] args) throws Exception {
        //编码操作
        byte[] bytes = "中".getBytes(); //按照平台默认的编码格式进行编码
        System.out.println(Arrays.toString(bytes));
		
        byte[] bytes1 = "中".getBytes("GBK"); //按照指定的编码格式GBK进行编码
        System.out.println(Arrays.toString(bytes1));
        
        //解码操作
        String str = new String(bytes,"GBK"); //按照指定的字符集对byte数组进行解码
        System.out.println(str);

        String str2 = new String(bytes1,"GBK");
        System.out.println(str2);
    }
}

四、IO流

1.认识IO流

  • I指Input,称为输入流:负责把数据读到内存中去
  • O指Output,称为输出流:负责写数据出去

2.IO流的分类

1.1 按流的方向分

IO流{1.输入流 2.输出流}

1.2 按流中数据的最小单位分

IO流:

  1. 字节流:适合操作所有类型的数据
  2. 字符流:只适合操作纯文本文件,比如:读写txt、java文件等

3.IO流四大类

3.1 字节输入流InputStream(读字节数据的)

以内存为基准,来自磁盘文件/网络中的数据以字节的形式读入到内存中去的流

3.2 字节输出流OutputStream(写字节数据出去的)

以内存为基准,把内存中的数据以字节写出到磁盘文件或者网络中去的流

3.3 字符输入流Reader(读字符数据的)

以内存为基准,来自磁盘文件/网络中的数据以字符的形式读入到内存中去的流

3.4 字符输出流Writer(写字符数据出去的)

以内存为基准,把内存中的数据以字符写出到磁盘文件或者网络介质中去的流。

五、IO流-字节流

在这里插入图片描述

1.文件字节输入流(FileInputStream):每次读取一个字节

FileInputStream(文件字节输入流)

  • 作用:以内存为基准,可以把磁盘文件中的数据以字节的形式读入到内存中去
构造器说明
public FileInputStream(File file)创建字节输入流管道与源文件接通
public FileInputStream(String pathname)创建字节输入流管道与源文件接通
方法名称说明
public int read()每次读取一个字节返回,如果发现没有数据可读会返回-1.
public int read(byte[] buffer)每次用一个字节数组去读取数据,返回字节数组读取了多少个字节,如果发现没有数据可读会返回-1.
import java.io.File;
import java.io.FileInputStream;
import java.util.Arrays;

public class FileInputStreamDemo {
    public static void main(String[] args) throws Exception {
        File file = new File("SE_Advanced/1.txt");
        //创建字输入流对象
        FileInputStream fis = new FileInputStream(file);
        int ch;
        // read() 读取数据【读取不到时 返回 -1 】
        while ((ch = fis.read()) != -1){
            System.out.println(ch);
        }
    }
}

2.文件字节输入流(FileInputStream):每次读取多个字节

方法名称说明
public int read(byte[] buffer)每次用一个字节数组去读取数据,返回字节数组读取了多少个字节,如果发现没有数据可读会返回-1.
  • 注意:使用FileInputStream每次读取多个字节,读取性能得到了提升,但读取汉字输出还是会乱码
import java.io.File;
import java.io.FileInputStream;
import java.util.Arrays;

public class FileInputStreamDemo {
    public static void main(String[] args) throws Exception {
        File file = new File("SE_Advanced/1.txt");
        //创建字输入流对象
        FileInputStream fis = new FileInputStream(file);
       	//字节数据读取
        byte[] arr = new byte[3];
        int len;
        while ((len = fis.read()) != -1){
            System.out.println(Arrays.toString(arr));
        }
    }
}

3.文件字节输入流(FileInputStream):一次读取完全部字节

方式一:定义一个字节数组与被读取的文件大小一样大,然后使用该字节数组,一次读完文件的全部字节
方法名称说明
public int read(byte[] buffer)每次用一个字节数组去读取,返回字节数组读取了多少个字节,
如果发现没有数据可读会返回-1.
方式二:va官方为lnputStream提供了如下方法,可以直接把文件的全部字节读取到一个字节数组中返回
方法名称说明
public byte[] readAllBvtes() throws IOException直接将当前字节输入流对应的文件对象的字节数据装到一个字节数组返h回

注意:如果文件过大,创建的字节数组也会过大,可能引起内存溢出

4.文件字节输出流:写字节出去

FileOutputStream(文件字节输出流):

  • 作用:以内存为基准,把内存中的数据以字节的形式写出到文件中去
构造器说明
public FileOutputStream(File file)创建字节输出流管道与源文件对象接通
public FileOutputStream(String filepath)创建字节输出流管道与源文件路径接通
public FileOutputStream(File file, boolean append)创建字节输出流管道与源文件对象接通,可追加数据
public FileOutputStream(String filepath, boolean append)创建字节输出流管道与源文件路径接通,可追加数据
方法名称说明
public void write(int a)写一个字节出去
public void write(byte[] buffer)写一个字节数组出去
public void write(byte[] buffer , int pos ,int len)写一个字节数组的一部分出去
public void close() throws IOException关闭流
import java.io.FileOutputStream;

public class FileOutputStreamDemo{
    public static void main(String[] args) throws Exception {
        //1.创建字节输出流 【append:表示追加> true表示可追加】
        FileOutputStream fos = new FileOutputStream("SE_Advanced/2.txt",true);
        //2.写数据
        fos.write(97);
        //写一个字节数组出去
        byte[] arr = {98,99,100};
        fos.write(arr);
        //写字节数组从 0 开始 到 1 的元素出去
        fos.write(arr,0,1);
        //写一个换行
        fos.write("\n".getBytes());
        //关闭输出流
        fos.close();
    }
}

5.案例-文件复制

import java.io.FileInputStream;
import java.io.FileOutputStream;

public class FileCopyDemo {
    public static void main(String[] args) throws Exception {
        //定义 输入、输出流
        FileInputStream fis = new FileInputStream("E:\\WallPaperLap\\main2.jpg");
        FileOutputStream fos = new FileOutputStream("SE_Advanced\\main.jpg");
        //读写数据
        byte[] arr = new byte[1024];
        int len;
        while ((len = fis.read(arr)) != -1){
            fos.write(arr,0,len);
        }
        //关闭 输入、输出流
        fis.close();
        fos.close();
    }
}

六、释放资源的方式

1.try-catch-finally

try{
    ...
    ...
} catch (IOException e) {
    e.printStackTrance();
} finally {
    ...
    (最后一定执行的内容)
}
  • inally代码区的特点:无论try中的程序是正常执行了,还是出现了异常,最后都一定会执行finally区,除非JVM终
    止.
  • 作用:一般用于在程序执行完成后进行资源的释放操作(专业级做法)

2.try-with-resource

try(定义资源1; 定义资源2;...) {
    可能出现异常的代码;
} catch (异常类名  变量名) {
    异常处理的代码
}

该资源使用完毕后,会自动调用其close(方法,完成对资源的释放!

  • () 中只能放置资源,否则报错
  • 资源一般指的是最终实现了AutoCloseable接口。

3.案例

  1. Student实体类
public class Student {
    private String name;
    private int chinese;
    private int math;
    private int english;
    // get,set,toString方法均省略
}
  1. 文件流操作类
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;

public class StuFileInOutDemo {
    public static void main(String[] args){
        FileOutputStream fos = null;
        try {
            Student s1 = new Student("林青霞", 98, 99, 100);
            Student s2 = new Student("朱茵", 100, 100, 100);

            ArrayList<Student> students = new ArrayList<>();
            students.add(s1);
            students.add(s2);
            students.sort(((o1, o2) -> o2.totalScore()- o1.totalScore()==0?1:o2.totalScore()- o1.totalScore()));

            fos = new FileOutputStream("SE_Advanced/student.txt");
            for (Student stu : students) {
                byte[] bytes = (stu.getName()+":"+stu.getChinese()+" "+stu.getMath()+" "+stu.getEnglish()+"\n").getBytes();
                System.out.println(Arrays.toString(bytes));
                fos.write(bytes);
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }finally {
            //不管 try 中的代码是否出现异常,finally中的代码都会执行
            try {
                if (fos != null) {
                    fos.close();
                }
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }
}
  • 19
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值