【Java I/O 流】4 - 6 转换流

§4-6 转换流

4-6.1 字符流的转换流

转换流是字符流的高级流,是字节流与字符流之间的桥梁。其体系如图所示:

image

使用转换流,使得字节流和字符流通过转换流这一个桥梁相互沟通。读取数据时,先经过字节流,然后通过转换流使用字符流中的方法;写出数据时,先经过转换流,转换成字节流操作字节数据。

作用

  • 指定字符集读写数据(自 JDK 11 起被淘汰);
  • 在字节流中使用字符流中的方法;

4-6.2 转换输入流

InputStreamReader 是一个从字节流转换为字符流的桥梁:它读取字节数据,并将字节数据使用指定字符集解码为对应字符。

构造方法

构造方法 描述
InputStreamReader(InputStream in) 使用平台默认字符集创建一条转换输入流
InputStreamReader(InputStream in, String name) 使用指定名称的字符集创建一条转换输入流
InputStreamReader(InputStream in, Charset cs) 使用指定字符集创建一条转换输入流
InputStreamReader(InputStream in, CharsetDecoder dec) 使用指定的字符集解码器创建一条转换输入流
  • 转换流属于高级流,在底层依赖于基本流,其构造方法都会要求传入一个基本流对象;

    为了效率,一般考虑在参数中包装基本流(new);

  • 使用转换输入流,则可以使用字符流的方法;

  • Charset 接口参数除了可以调用 StandardCharsets 中所定义的字符集枚举常量外,也可以直接调用 Charset 中的静态方法 forName(String charsetName) 获取;

  • 关闭流释放资源时,只需要关闭高级流即可,方法内部会自行关闭所依赖的基本流;

替代方案:使用 InputStreamReader 指定字符集读取数据的方式,自 JDK 11 起被淘汰,现有一种替代方案,调用 FileReader 的重载构造器:

构造方法 描述
FileReader(File file, Charset charset) 使用指定字符集,创建一个关联指定文件的文件阅读器对象
FileReader(String fileName, Charset charset) 使用指定字符集,创建一个关联指定文件的的文件阅读器对象

4-6.3 转换输出流

OutputStreamWriter 是一个从字符流转换到字节流的桥梁:写入的字符会根据所指定的字符集编码为字节数据。

构造方法

构造方法 描述
OutputStreamWriter(OutputStream out) 适用平台默认的字符集创建一条转换输出流
OutputStreamWriter(OutputStream out, String charsetName) 使用指定名称的字符集创建一条转换输出流
OutputStreamWriter(OutputStream out, Charset cs) 使用指定字符集创建一条转换输出流
OutputStreamWriter(OutputStream out, CharsetEncoder enc) 使用指定的字符集编码器创建一条转换输出流
  • 转换流属于高级流,在底层依赖于基本流,其构造方法都会要求传入一个基本流对象;

    为了效率,一般考虑在参数中包装基本流(new);

  • 关闭流释放资源时,只需要关闭高级流即可,方法内部会自行关闭所依赖的基本流;

替代方案:使用 OutputStreamWriter 指定字符集写出数据的方式,自 JDK 11 起被淘汰,现有一种替代方案,调用 FileWriter 的重载构造器:

构造方法 描述
FileWriter(File file, Charset charset, boolean append) 使用指定字符集,创建一条关联指定为文件的文件写入器
FileWriter(String fileName, Charset charset, boolean append) 使用指定字符集,创建一条关联指定名称文件的文件写入器

4-6.4 文件转码

需求:编写一个方法,可以将文件从 GBK 转码至 UTF-8。

JDK 8 及以前的实现:

public static void oldConvert(File src) throws IOException {
    Objects.requireNonNull(src);

    if (!src.exists()) {
        System.err.println("错误:文件不存在");
        return;
    } else if (src.isDirectory()) {
        System.err.println("错误:不支持目录");
        return;
    }

    //JDK 8 及以前的方案
    InputStreamReader isr = new InputStreamReader(new FileInputStream(src), "GBK");
    StringBuilder sb = new StringBuilder();
    char[] chars = new char[10];
    int len;
    while ((len = isr.read(chars)) != -1) {
        sb.append(chars, 0, len);
    }
    isr.close();

    OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(src.getParent() + "\\utf8file.tct"), StandardCharsets.UTF_8);
    osw.write(sb.toString());
    osw.close();
}

JDK 11 及以后的实现:

public static void newConvert(File src) throws IOException {
    Objects.requireNonNull(src);

    if (!src.exists()) {
        System.err.println("错误:文件不存在");
        return;
    } else if (src.isDirectory()) {
        System.err.println("错误:不支持目录");
        return;
    }

    //JDK 11 起
    FileReader fr = new FileReader(src, Charset.forName("GBK"));
    StringBuilder sb = new StringBuilder();
    char[] chars = new char[10];
    int len;
    while ((len = fr.read(chars)) != -1) {
        sb.append(chars, 0, len);
    }
    fr.close();

    FileWriter fw = new FileWriter(new File(src.getParent(), "utf8file.txt"), StandardCharsets.UTF_8);
    fw.write(sb.toString());
    fw.close();
}
posted @ 2023-08-20 00:52  Zebt  阅读(21)  评论(0)    收藏  举报