欢迎光临
我们一直在努力

Java IO 核心总结:File 类、字节流与字符流详解

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */
#content_views .toc,
/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */
#content_views.markdown_views > p:empty:has(+ .toc),
#content_views.markdown_views > .toc + p:empty,
/* 富文本旧版目录标记 */
#content_views.htmledit_views #main-toc,
#content_views.htmledit_views #hr-toc,
#content_views.htmledit_views p[id*=\”-toc\”] {
display: none !important;
}
/* 目录去掉后,紧跟的首个标题不再多出一块上边距 */
#content_views.markdown_views > .toc + h1,
#content_views.markdown_views > .toc + h2,
#content_views.markdown_views > .toc + h3,
#content_views.markdown_views > .toc + h4,
#content_views.markdown_views > .toc + p:empty + h1,
#content_views.markdown_views > .toc + p:empty + h2,
#content_views.markdown_views > .toc + p:empty + h3,
#content_views.markdown_views > .toc + p:empty + h4 {
margin-top: 0 !important;
}

在 Java 开发中,文件操作和 IO 流是非常基础且重要的内容。无论是读取配置文件、保存日志,还是实现文件上传下载,都离不开 IO 操作。

本文从实战角度出发,系统总结:

  • File 类的常见用法
  • 字节流:InputStream / OutputStream 的用法
  • 字符流:Reader / Writer 的用法
  • 字节流与字符流的区别与选择
  • 资源管理与综合示例

一、File 类:文件与目录的抽象

java.io.File 是 Java 对文件系统中文件(包括目录)的抽象描述。

注意:创建一个 File 对象,并不代表该文件在磁盘上真实存在。它只是路径的抽象表示。

1. 构造方法

构造方法说明
File(String pathname) 根据路径字符串创建 File 对象,可以是绝对路径或相对路径
File(File parent, String child) 根据父目录 File 对象和子路径创建
File(String parent, String child) 根据父目录路径字符串和子路径创建

示例:

File file1 = new File("hello.txt");
File file2 = new File("D:\\\\test", "hello.txt");
File parent = new File("D:\\\\test");
File file3 = new File(parent, "hello.txt");

2. 路径相关方法

File file = new File("..\\\\hello-world.txt");

System.out.println(file.getParent()); // ..\\
System.out.println(file.getName()); // hello-world.txt
System.out.println(file.getPath()); // ..\\hello-world.txt
System.out.println(file.getAbsolutePath()); // 绝对路径
System.out.println(file.getCanonicalPath()); // 修饰后的绝对路径,会解析 . 和 ..

3. 文件与目录操作

方法说明
exists() 判断文件或目录是否真实存在
isDirectory() 判断是否为目录
isFile() 判断是否为普通文件
createNewFile() 创建普通文件,已存在返回 false
delete() 删除文件或空目录
deleteOnExit() 程序退出时删除文件
mkdir() 创建单级目录,父目录不存在会失败
mkdirs() 创建多级目录,父目录不存在会一并创建
renameTo(File dest) 重命名或移动文件
listFiles() 返回目录下的子文件和子目录

示例:创建、删除文件

File file = new File("test.txt");

System.out.println(file.exists()); // false
System.out.println(file.createNewFile()); // true
System.out.println(file.exists()); // true
System.out.println(file.delete()); // true
System.out.println(file.exists()); // false

示例:创建目录

File dir = new File("some-parent\\\\some-dir");

// mkdir() 如果父目录不存在会失败
System.out.println(dir.mkdir()); // false

// mkdirs() 可以创建多级目录
System.out.println(dir.mkdirs()); // true


二、IO 流的分类

在 Java 中,IO 流按照处理数据的单位分为两类:

  • 字节流(Byte Stream):以字节(8位)为单位读写,适合处理图片、音频、视频等二进制文件。
    • 输入流:InputStream
    • 输出流:OutputStream
  • 字符流(Character Stream):以字符(16位)为单位读写,专门用于处理文本文件,会自动处理字符集编码。
    • 输入流:Reader
    • 输出流:Writer
  • 注意:字符流本质上还是基于字节流实现的,只是加了一层编码/解码的包装。


    三、字节流:InputStream / OutputStream

    1. InputStream(字节输入流)

    InputStream 是字节输入流的抽象类,最常用的子类是 FileInputStream。

    方法说明
    int read() 读取一个字节,返回 -1 表示读取完毕
    int read(byte[] b) 最多读取 b.length 个字节,返回实际读取数量,-1 表示读完
    void close() 关闭流

    推荐方式:使用缓冲区读取

    try (InputStream is = new FileInputStream("hello.txt")) {
    byte[] buf = new byte[1024];
    int len;

    while ((len = is.read(buf)) != –1) {
    // buf 的 [0, len) 是本次读取到的数据
    System.out.write(buf, 0, len);
    }
    }

    2. OutputStream(字节输出流)

    OutputStream 是字节输出流的抽象类,最常用的子类是 FileOutputStream。

    方法说明
    void write(int b) 写入一个字节
    void write(byte[] b) 写入整个字节数组
    void write(byte[] b, int off, int len) 写入字节数组的指定范围
    void flush() 刷新缓冲区,强制将数据写入目标
    void close() 关闭流

    写入示例:

    try (OutputStream os = new FileOutputStream("output.txt")) {
    String s = "你好中国";
    byte[] b = s.getBytes("UTF-8");
    os.write(b);

    os.flush(); // 不要忘记 flush
    }


    四、字符流:Reader / Writer(重点补充)

    字符流专门用于处理文本数据,它能自动处理字符集编码,避免字节流读取中文时的乱码问题。

    1. Reader(字符输入流)

    Reader 是字符输入流的抽象类,常用子类有 FileReader、BufferedReader。

    方法说明
    int read() 读取一个字符,返回 -1 表示读完
    int read(char[] cbuf) 最多读取 cbuf.length 个字符,返回实际读取数
    void close() 关闭流

    基础用法(FileReader):

    try (Reader reader = new FileReader("hello.txt")) {
    int ch;
    while ((ch = reader.read()) != –1) {
    System.out.print((char) ch);
    }
    }

    高效用法(BufferedReader,支持按行读取):

    BufferedReader 提供了 readLine() 方法,可以一次读取一行文本,非常适合处理文本文件。

    try (BufferedReader reader = new BufferedReader(new FileReader("hello.txt"))) {
    String line;
    while ((line = reader.readLine()) != null) {
    System.out.println(line);
    }
    }

    注意:FileReader 使用系统默认字符集,如果文件编码与系统默认不一致,可能会出现乱码。此时应使用 InputStreamReader 手动指定编码。

    2. Writer(字符输出流)

    Writer 是字符输出流的抽象类,常用子类有 FileWriter、BufferedWriter。

    方法说明
    void write(int c) 写入一个字符
    void write(char[] cbuf) 写入字符数组
    void write(String str) 写入字符串
    void flush() 刷新缓冲区
    void close() 关闭流

    基础用法(FileWriter):

    try (Writer writer = new FileWriter("output.txt")) {
    writer.write("你好,世界\\n");
    writer.write("Hello, World\\n");
    writer.flush();
    }

    高效用法(BufferedWriter,支持换行):

    try (BufferedWriter writer = new BufferedWriter(new FileWriter("output.txt"))) {
    writer.write("我是第一行");
    writer.newLine(); // 换行
    writer.write("我是第二行");
    writer.flush();
    }

    3. 转换流:InputStreamReader / OutputStreamWriter

    转换流是字节流和字符流之间的桥梁,可以指定字符集编码,解决乱码问题。

    读取时指定编码:

    try (BufferedReader reader = new BufferedReader(
    new InputStreamReader(new FileInputStream("hello.txt"), "UTF-8"))) {
    String line;
    while ((line = reader.readLine()) != null) {
    System.out.println(line);
    }
    }

    写入时指定编码:

    try (BufferedWriter writer = new BufferedWriter(
    new OutputStreamWriter(new FileOutputStream("output.txt"), "UTF-8"))) {
    writer.write("你好,世界");
    writer.flush();
    }


    五、字节流 vs 字符流:如何选择?

    维度字节流字符流
    处理单位 字节(8位) 字符(16位)
    适用场景 图片、音频、视频、压缩包等二进制文件 文本文件(txt、java、html 等)
    编码处理 需要手动处理编码 自动处理编码(或通过转换流指定)
    核心抽象类 InputStream / OutputStream Reader / Writer
    常见子类 FileInputStream / FileOutputStream FileReader / FileWriter、BufferedReader / BufferedWriter
    性能优化 使用 byte[] 缓冲区 使用 char[] 缓冲区或 BufferedReader

    选择原则:

    • 如果是二进制文件(图片、音视频等),必须使用字节流。
    • 如果是文本文件,优先使用字符流(尤其是 BufferedReader/BufferedWriter),避免乱码并提高效率。
    • 如果文本文件编码特殊(如 UTF-8 而系统默认 GBK),必须使用转换流指定编码。

    六、资源管理:try-with-resources

    IO 资源非常宝贵,使用完毕后必须关闭。Java 7 提供了 try-with-resources 语法,只要资源实现了 AutoCloseable 接口,就能自动关闭。

    标准写法:

    try (InputStream is = new FileInputStream("source.txt");
    OutputStream os = new FileOutputStream("dest.txt")) {

    byte[] buf = new byte[1024];
    int len;

    while ((len = is.read(buf)) != –1) {
    os.write(buf, 0, len);
    }

    os.flush();
    } catch (IOException e) {
    e.printStackTrace();
    }


    七、综合示例:文件复制(字节流 vs 字符流)

    1. 使用字节流复制任意文件(推荐)

    public class FileCopyDemo {
    public static void main(String[] args) {
    File source = new File("source.jpg");
    File dest = new File("dest.jpg");

    try (InputStream is = new FileInputStream(source);
    OutputStream os = new FileOutputStream(dest)) {

    byte[] buf = new byte[1024];
    int len;
    while ((len = is.read(buf)) != –1) {
    os.write(buf, 0, len);
    }
    os.flush();
    System.out.println("复制完成");
    } catch (IOException e) {
    e.printStackTrace();
    }
    }
    }

    2. 使用字符流复制文本文件

    public class TextCopyDemo {
    public static void main(String[] args) {
    try (BufferedReader reader = new BufferedReader(
    new InputStreamReader(new FileInputStream("source.txt"), "UTF-8"));
    BufferedWriter writer = new BufferedWriter(
    new OutputStreamWriter(new FileOutputStream("dest.txt"), "UTF-8"))) {

    String line;
    while ((line = reader.readLine()) != null) {
    writer.write(line);
    writer.newLine();
    }
    writer.flush();
    System.out.println("文本复制完成");
    } catch (IOException e) {
    e.printStackTrace();
    }
    }
    }


    八、总结

    类别核心类用途关键点
    文件抽象 File 描述文件或目录元信息 对象存在不代表文件真实存在
    字节输入 InputStream 读取字节数据 read() 返回 -1 表示读完
    字节输出 OutputStream 写入字节数据 write() 写入,flush() 刷新
    字符输入 Reader 读取字符数据 BufferedReader.readLine() 按行读取
    字符输出 Writer 写入字符数据 BufferedWriter.newLine() 换行
    转换流 InputStreamReader / OutputStreamWriter 字节流转字符流 可指定字符集,解决乱码
    资源管理 try-with-resources 自动关闭流 避免资源泄漏

    掌握 File、字节流、字符流的基本用法,是 Java 文件编程的基础。

    实际开发中:

    • 操作文件元信息使用 File;
    • 读写二进制文件使用 InputStream / OutputStream;
    • 读写文本文件使用 Reader / Writer,优先选择 BufferedReader / BufferedWriter;
    • 编码不一致时使用转换流指定字符集;
    • 始终使用 try-with-resources 管理资源;
    • 不要忘记 flush() 和 close()。
    赞(0)
    未经允许不得转载:171主机测评 » Java IO 核心总结:File 类、字节流与字符流详解
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址