Java 常用 IO 类说明以及字节流与字符流的区别说明和案例示范

1. Java IO 类概述

1.1 什么是 IO

IO 是 Input/Output(输入/输出) 的缩写,代表了程序与外部环境(如文件、网络、设备等)之间进行数据交换的操作。在 Java 中,IO 操作广泛用于文件读取、写入、网络通信等场景。Java 提供了强大的 IO 类来简化这些操作,并按照不同的数据类型(如字节、字符)和数据源提供了不同的类。

1.2 Java 常用的 IO 类

根据数据处理的方式不同,Java 中的 IO 操作可以分为以下几大类:

  • 字节流:处理二进制数据,适用于图片、音频、视频等非文本数据。
  • 字符流:处理文本数据,适用于字符串、字符等文本文件。

Java IO 常用类如下表:

类别 输入类 输出类
字节流 InputStream OutputStream
文件字节流 FileInputStream FileOutputStream
字符流 Reader Writer
文件字符流 FileReader FileWriter
缓冲流 BufferedInputStream BufferedOutputStream
缓冲字符流 BufferedReader BufferedWriter

2. 字节流与字符流的区别

Java 中的 IO 操作分为两类:字节流字符流。它们的区别在于处理的数据类型不同。

2.1 什么是字节流

字节流8 位字节 为单位读取或写入数据,适合处理 二进制数据。字节流的常见用法是处理图片、视频、音频等非文本文件。字节流类的主要父类有:

  • InputStream:字节输入流,用于从数据源读取字节。
  • OutputStream:字节输出流,用于将字节写入目标。

常用字节流类包括 FileInputStreamFileOutputStreamBufferedInputStreamBufferedOutputStream 等。

2.2 什么是字符流

字符流16 位字符 为单位进行数据处理,适合处理 文本数据,如字符串和文本文件。字符流类的主要父类有:

  • Reader:字符输入流,用于读取字符数据。
  • Writer:字符输出流,用于写入字符数据。

常用字符流类包括 FileReaderFileWriterBufferedReaderBufferedWriter 等。

2.3 字节流与字符流的区别

区别点 字节流 字符流
处理的数据类型 处理二进制数据,如图片、音频 处理文本数据,如文本文件、字符串
数据单位 以字节为单位(8 位) 以字符为单位(16 位)
使用场景 适用于非文本文件的处理 适用于文本文件或字符数据的处理
父类 InputStreamOutputStream ReaderWriter
常用类 FileInputStreamFileOutputStream FileReaderFileWriter

3. Java IO 常用字节流类

字节流主要用于处理非文本数据。Java 提供了丰富的字节流类来帮助开发者进行文件或网络数据的操作。

3.1 InputStream 类

InputStream 是字节输入流的父类,定义了从不同的输入源(如文件、网络、内存缓冲区)读取字节的基本方法。

常用的 InputStream 子类包括:

  • FileInputStream:用于从文件中读取字节数据。
  • BufferedInputStream:为其他输入流提供缓冲功能,提高读取效率。
  • ByteArrayInputStream:从字节数组中读取数据。

3.2 OutputStream 类

OutputStream 是字节输出流的父类,定义了向不同的输出目标(如文件、网络、内存缓冲区)写入字节的基本方法。

常用的 OutputStream 子类包括:

  • FileOutputStream:用于将字节数据写入文件。
  • BufferedOutputStream:为其他输出流提供缓冲功能,提高写入效率。
  • ByteArrayOutputStream:向字节数组中写入数据。

3.3 FileInputStream 和 FileOutputStream 示例

示例:读取二进制文件

通过 FileInputStream 读取二进制文件(如图片),并将其保存到字节数组中:

import java.io.FileInputStream;
import java.io.IOException;

public class FileInputExample {
    public static void main(String[] args) {
        String filePath = "image.jpg";  // 文件路径
        try (FileInputStream fis = new FileInputStream(filePath)) {
            byte[] data = new byte[fis.available()];
            fis.read(data);  // 将文件内容读取到字节数组中
            System.out.println("读取了 " + data.length + " 个字节的数据");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
示例:写入二进制文件

通过 FileOutputStream 将字节数据写入文件:

import java.io.FileOutputStream;
import java.io.IOException;

public class FileOutputExample {
    public static void main(String[] args) {
        String filePath = "output.jpg";  // 输出文件路径
        byte[] data = { /* 图片的字节数据 */ };
        
        try (FileOutputStream fos = new FileOutputStream(filePath)) {
            fos.write(data);  // 将字节数据写入文件
            System.out.println("写入了 " + data.length + " 个字节的数据");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

在这两个例子中,使用了 try-with-resources 语法来确保流的正确关闭,防止资源泄漏。


4. Java IO 常用字符流类

字符流用于处理文本数据,如字符串或文本文件的读取和写入。字符流以 ReaderWriter 为父类,分别对应输入和输出操作。

4.1 Reader 类

Reader 是字符输入流的父类,用于从各种输入源(如文件、内存缓冲区、网络连接)读取字符数据。

常用的 Reader 子类包括:

  • FileReader:从文件中读取字符数据。
  • BufferedReader:提供缓冲功能以提高读取效率。

4.2 Writer 类

Writer 是字符输出流的父类,用于将字符数据写入输出目标(如文件、内存缓冲区、网络连接)。

常用的 Writer 子类包括:

  • FileWriter:向文件写入字符数据。
  • BufferedWriter:提供缓冲功能以提高写入效率。

4.3 FileReader 和 FileWriter 示例

示例:读取文本文件

通过 FileReaderBufferedReader 读取文本文件的内容:

import java.io.FileReader;
import java.io.BufferedReader;
import java.io.IOException;

public class FileReaderExample {
    public static void main(String[] args) {
        String filePath = "example.txt";  // 文件路径
        
        try (BufferedReader br = new BufferedReader(new FileReader(filePath))) {
            String line;
            while ((line = br.readLine()) != null) {
                System.out.println(line);  // 输出文件的每一行
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
示例:写入文本文件

通过 FileWriterBufferedWriter 将文本数据写入文件:

import java.io.FileWriter;
import java.io.BufferedWriter;
import java.io.IOException;

public class FileWriterExample {
    public static void main(String[] args) {
        String filePath = "output.txt";  // 输出文件路径
        String content = "这是写入文件的文本内容。";

        try (BufferedWriter bw = new BufferedWriter(new FileWriter(filePath))) {
            bw.write(content);  // 写入文本内容
            bw.newLine();  // 换行
            bw.write("这是另一行文本。");
            System.out.println("文本内容已成功写入文件。");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

5. Java 读取和写入文本的综合示例

结合读取和写入操作,展示如何读取一个文件的内容,并将其写入到另一个文件中。

import java.io.FileReader;
import java.io.BufferedReader;
import java.io.FileWriter;
import java.io.BufferedWriter;
import java.io.IOException;

public class FileCopyExample {
    public static void main(String[] args) {
        String inputFilePath = "input.txt";  // 输入文件路径
        String outputFilePath = "output.txt";  // 输出文件路径
        
        try (
            BufferedReader br = new BufferedReader(new FileReader(inputFilePath));
            BufferedWriter bw = new BufferedWriter(new FileWriter(outputFilePath))
        ) {
            String line;
            while ((line = br.readLine()) != null) {
                bw.write(line);  // 将读取的行写入输出文件
                bw.newLine();  // 写入换行符
            }
            System.out.println("文件内容已成功复制到新的文件。");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

此示例通过 BufferedReader 读取文本文件,并通过 BufferedWriter 将内容写入到另一个文件中,确保了高效读取和写入操作。


6. 流泄漏问题及如何正确关闭流

6.1 流泄漏问题

在进行 IO 操作时,未能正确关闭流对象会导致资源泄漏问题。Java 的 IO 操作通常涉及文件句柄、网络连接等有限资源,如果这些资源未能及时释放,可能会引发以下问题:

  1. 文件锁未释放:如果文件流未关闭,文件可能仍被锁定,导致其他程序无法访问该文件。
  2. 资源消耗过高:长时间不释放 IO 资源会导致系统资源(如文件句柄)耗尽,从而引发性能问题或系统崩溃。

6.2 如何正确关闭流

为了解决流泄漏问题,Java 提供了多种方法来确保流在使用后被正确关闭:

方法1:显式关闭流

使用 try-finally 结构手动关闭流。

import java.io.FileInputStream;
import java.io.IOException;

public class ExplicitCloseExample {
    public static void main(String[] args) {
        FileInputStream fis = null;
        try {
            fis = new FileInputStream("example.txt");
            // 执行读取操作
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // 确保在 finally 中关闭流
            if (fis != null) {
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
方法2:使用 try-with-resources

从 Java 7 开始,提供了 try-with-resources 语法,该结构可以自动关闭实现了 AutoCloseable 接口的资源类,避免了手动关闭流的麻烦。

import java.io.FileInputStream;
import java.io.IOException;

public class TryWithResourcesExample {
    public static void main(String[] args) {
        try (FileInputStream fis = new FileInputStream("example.txt")) {
            // 执行读取操作
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 文件流会自动关闭
    }
}

try-with-resources 是推荐的方式,它能够确保即使发生异常,也会自动关闭流,极大地减少了流泄漏的可能性。

你可能感兴趣的:(java,开发语言,后端,系统架构,面试)