Java IO流必备:File、递归与字符集详解

目录

  • 前言
  • File
    • 创建File类的对象
    • File类的相关方法
  • 方法递归
    • 认识递归
    • 文件搜索
  • 字符集
    • 常见字符集
      • ⚙️ 标准ASCII字符集
      • ⚙️GBK(汉字内码扩展规范,国标)
      • ⚙️Unicode(统一码、万国码)
      • ⚙️UTF-8(Unicode Transformation Format - 8-bit)
    • 编码与解码
      • ⚙️字符串编码与解码方法总结
      • ⚙️示例代码(Java)
      • ⚙️核心注意事项

前言

大家好!我是 EnigmaCoder
本文为学习IO流的前置知识,包含File、方法递归、字符集等。

File

  • Filejava.io.包下的类,File类的对象,用于代表当前操作系统的文件(可以是文件、或文件夹)。

  • File类的对象可以代表文件/文件夹,并可以调用其提供的方法对象文件进行操作。

  • 注意File类只能对文件本身进行操作,不能读写文件里面存储的数据,如果需要读写文件,就要用到IO流。

创建File类的对象

构造器 说明
public File(String pathname) 根据文件路径创建文件对象
public File(String parent,String child) 根据父路径和子路径名字创建文件对象
public File(File parent,String child) 根据父路径对应文件对象和子路径名字创建文件对象

注意

  • File对象既可以代表文件、也可以代表文件夹。
  • File封装的对象仅仅是一个路径名,这个路径可以是存在的,也可以是不存在的。
File f1 =new File ("E:\\resource\\wang.jpg");

可以使用相对路径定位文件对象

  • 只要带盘符的都称为绝对路径。
  • 不带盘符,默认在IDEA工程下直接寻找文件的是相对路径,其一般用来找工程下的项目文件。
File f1 =new File ("resource\\wang.jpg");

File类的相关方法

  1. File提供的判断文件类型、获取文件信息功能
方法名称 说明
public boolean exists() 判断当前文件对象对应的文件路径是否存在,存在返回true
public boolean isFile() 判断当前文件对象指代的是否是文件,是文件返回true,反之
public boolean isDirectory() 判断当前文件对象指代的是否是文件夹,是文件夹返回true
public String getName() 获取文件的名称(包含后缀)
public long length() 获取文件的大小,返回字节个数
public long lastModified() 获取文件的最后修改时间
public String getPath() 获取创建文件对象时使用的路径
public String getAbsolutePath() 获取绝对路径
  1. File提供的创建和删除文件的方法
方法名称 说明
public boolean createNewFile() 创建一个新的空文件
public boolean mkdir() 只能创建一级文件夹
public boolean mkdirs() 可以创建多级文件夹
public boolean delete() 删除文件、空文件夹

注意delete方法默认只能删除文件和空文件夹,删除后的文件不会进入回收站。

  1. File提供的遍历文件夹的方法
方法名称 说明
public String[] list() 获取当前目录下所有的“一级文件名称”到一个字符串数组中返回
public File[] listFiles() 获取当前目录下所有的“一级文件对象”到一个文件对象数组中返回

使用listFiles方法时的注意事项

  • 当主调是文件,或者路径不存在时,返回null
  • 当主调是空文件夹时,返回一个长度为0的数组。
  • 当主调是一个有内容的文件夹时,将里面所有一级文件和文件夹的路径放在File数组中返回。
  • 当主调是一个文件夹,且里面有隐藏文件时,将里面所有文件和文件夹的路径放在File数组中返回,包含隐藏文件。
  • 当主调是一个文件夹,但是没有权限访问该文件夹时,返回null

方法递归

认识递归

递归是一种算法,从形式上来说,方法调用自身的形式称为方法递归。

两种形式

  • 直接递归:方法自己调用自己。
  • 间接递归:方法调用其他方法,其他方法又回调方法自己。

案例:递归求阶乘

public class RecursionTest2{
   public static void main(String[] args ){
       int result = f(5);
       System.out.println("5的阶乘是:"+result); 
   }
   public static int f(int n){
       if(n==1) return 1;
       else return n*f(n-1);     
   }
}

递归算法的三要素:

  • 递归公式
  • 递归的终结点
  • 递归的方向必须走向终结点

文件搜索

使用递归算法搜索需要的文件。

public class Test {
    public static void main(String[] args) {
        File dir  = new File("C:\\");
        searchFile(dir,"QQ.exe");
    }

    public static void searchFile(File dir,String fileName){
        if(dir==null||!dir.exists()) return;

        File[] files = dir.listFiles();

        if(files!=null && files.length>0){
            for(File file:files){
                if(file.isFile()){
                    if(file.getName().equals(fileName)){
                        System.out.println("找到了目标文件:"+file.getAbsolutePath());
                    }
                }else{
                    searchFile(file,fileName);
                }
            }
        }
    }

}

字符集

常见字符集

⚙️ 标准ASCII字符集

  1. 定义
    ASCII(American Standard Code for Information Interchange,美国信息交换标准代码),包含英文、符号等字符。

  2. 存储规则

    • 使用 1个字节 存储一个字符,首位固定为0
    • 可表示的字符总数:2^7 = 128 个(满足英语等简单语言需求)。
  3. 局限性

    • ASCII无法编码中文等复杂字符,需扩展字符集。

⚙️GBK(汉字内码扩展规范,国标)

  1. 定位
    汉字编码字符集,涵盖 2万多个汉字及符号,解决中文存储问题。

  2. 存储规则

    • 中文字符:1个中文字符 → 2个字节 存储。
    • 兼容性:兼容ASCII字符集(ASCII字符仍用1字节、首位为0存储,与GBK共存)。
  3. 编码规则
    汉字的 第一个字节的第一位必须是1(用于区分ASCII字符,避免冲突)。

  4. 示例辅助

    • 字符示例:我a你(“我”“你”是汉字,各占2字节;“a”是ASCII,占1字节)。
    • 字节结构对比:
      • 原始混合(ASCII + 汉字):
        xxxxxxxx xxxxxxxx 0xxxxxxx xxxxxxxx xxxxxxxx
        (中间0xxxxxxx是ASCII的“a”,两侧是汉字的两字节)
      • 规范后(汉字首字节第一位为1):
        1xxxxxxx xxxxxxxx 0xxxxxxx 1xxxxxxx xxxxxxxx

⚙️Unicode(统一码、万国码)

  1. 定位
    跨语言、跨平台的字符编码标准,目标是覆盖全球所有字符(包括各国文字、符号、 emoji 等)。

  2. 核心特点

    • 唯一码点:为每个字符分配 全球唯一的数字编号(如 U+0041 表示字母 AU+4E2D 表示汉字 )。
    • 与编码方式无关:Unicode 仅定义字符与数字的映射关系,具体存储需依赖 UTF-8/UTF-16/UTF-32 等编码实现
  3. 局限性
    Unicode 本身不规定存储方式,直接按码点存储(如 U+4E2D 需 2 字节)会导致 空间浪费(如 ASCII 字符仅需 1 字节,但 Unicode 需 2 字节)。

⚙️UTF-8(Unicode Transformation Format - 8-bit)

  1. 定位
    Unicode 的可变长度编码方式,是互联网最主流的字符编码(兼容 ASCII,节省存储空间)。

  2. 存储规则

    • 可变字节数:根据字符复杂度动态调整字节数:
      • 1字节:ASCII 字符(范围:U+0000 ~ U+007F,首位固定为 0,与 ASCII 完全兼容)。
      • 2字节:大部分欧洲语言、中东字符(范围:U+0080 ~ U+07FF)。
      • 3字节:东亚文字(如中文、日文、韩文,范围:U+0800 ~ U+FFFF)。
      • 4字节:罕见字符、emoji(范围:U+10000 ~ U+10FFFF)。
    • 字节结构规则
      • 多字节字符的 首字节1 标识长度(如 110xxxxx 表示2字节,1110xxxx 表示3字节)。
      • 后续字节 固定以 10 开头(如 10xxxxxx)。
  3. 优势

    • 兼容性:完全兼容 ASCII,旧系统可无缝升级。
    • 节省空间:对常用字符(如英文)仅用 1 字节,复杂字符按需扩展。

对比总结

字符集 编码方式 存储空间特点 兼容性 典型应用场景
ASCII 定长(1字节) 仅支持128个字符 无扩展支持 早期英文系统
GBK 混合(1/2字节) 中文占2字节,兼容ASCII 仅支持中文及少数符号 中文Windows系统
Unicode 无(仅码点) 需配合UTF-8/16/32存储 需转换才能兼容旧系统 跨语言标准(如Java内部)
UTF-8 变长(1-4字节) 英文1字节,中文3字节 完全兼容ASCII 互联网、Linux/ macOS系统
  • 核心逻辑:UTF-8 通过可变长度编码平衡了 全球字符覆盖存储效率,成为全球化场景的首选编码。
  • 注意:字符编码是使用的字符集,和解码时使用的字符集必须一致,否则会出现乱码。

编码与解码

⚙️字符串编码与解码方法总结

  • (1)编码:String → 字节数组
方法签名 说明
byte[] getBytes() 平台默认字符集,将字符串编码为字节数组
byte[] getBytes(String charsetName) 指定字符集(如"UTF-8"),将字符串编码为字节数组
  • (2)解码:字节数组 → String
构造方法签名 说明
String(byte[] bytes) 平台默认字符集,解码字节数组为字符串
String(byte[] bytes, String charsetName) 指定字符集(如"UTF-8"),解码字节数组为字符串

⚙️示例代码(Java)

import java.io.UnsupportedEncodingException;

public class SimpleCharsetExample {
    public static void main(String[] args) {
        String text = "你好";

        try {
            // 编码:String → byte[]
            byte[] utf8Bytes = text.getBytes("UTF-8");  // UTF-8编码,1个中文占3字节
            byte[] gbkBytes = text.getBytes("GBK");     // GBK编码,1个中文占2字节

            System.out.println("UTF-8字节数:" + utf8Bytes.length); // 输出:6
            System.out.println("GBK字节数:" + gbkBytes.length);    // 输出:4

            // 解码:byte[] → String
            String decodedUtf8 = new String(utf8Bytes, "UTF-8");   // 正确解码
            String decodedGbk = new String(gbkBytes, "GBK");       // 正确解码
            String wrongDecode = new String(utf8Bytes, "GBK");     // 错误解码(乱码)

            System.out.println("UTF-8解码:" + decodedUtf8);  // 输出:你好
            System.out.println("GBK解码:" + decodedGbk);    // 输出:你好
            System.out.println("错误解码:" + wrongDecode);  // 输出乱码:浣犲ソ
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
    }
}

⚙️核心注意事项

  1. 字符集必须一致
    编码用 UTF-8,解码也必须用 UTF-8;若编码和解码字符集不同,必然出现乱码(如示例中用GBK解码UTF-8字节)。

  2. 平台默认字符集的风险
    getBytes()new String(byte[]) 依赖系统默认字符集(Windows 多为 GBK,Linux/Mac 多为 UTF-8),跨平台易出问题,建议始终显式指定字符集(如"UTF-8"

  3. 异常处理
    方法会抛出 UnsupportedEncodingException(如传入不存在的字符集"UTF8",少写横线),需捕获或声明抛出。

你可能感兴趣的:(Java,java,开发语言)