Java IO流基础与Guava Files工具类实战指南

小鹿同学
小鹿同学
发布时间:2026-10-15| 2人浏览过
原创

在Java开发中,文件与数据的IO传输是核心功能之一。Java原生提供了丰富的InputStream和OutputStream接口,但代码往往较为冗长。本文将解析Java IO流的分类与典型操作,并对比展示Google Guava库如何通过Files类简化文件读写、移动及高级内存映射等操作。

Java原生IO流体系解析

IO(Input/Output)指数据相对于程序的流入与流出。Java在java.io包中提供了庞大的接口体系,理解其分类是正确使用的前提。

流的分类维度

根据操作对象和功能的不同,Java IO流主要分为以下几类:

  • 按数据流向:输入流(InputStream,读入程序)与输出流(OutputStream,写出程序)。
  • 按操作单位:字节流以byte为单位,适用于所有类型文件;字符流以char为单位,基于Reader和Writer,需关注字符编码。
  • 按功能封装:包括缓冲流(提高读写效率)、转换流(字节与字符互转)、数据流(按基本数据类型读写)及对象序列化流。

区分技巧:通常以Stream结尾的是字节流,以Reader或Writer结尾的是字符流。

常见原生操作示例

原生IO API功能强大但样板代码较多,以下是几种典型场景的实现方式。

第1步:使用字节流进行文件复制

目的:将源文件数据逐块读取并写入目标文件。需注意手动关闭资源或使用Try-with-resources语句。

@Test
public void copyByBytes() throws IOException {
    String root = FileTests.class.getResource("/").getPath();
    // 建议在实际生产环境中使用 try-with-resources 自动管理资源
    FileInputStream fis = new FileInputStream(new File(root, "start.bat"));
    FileOutputStream fos = new FileOutputStream(root + "/out2.bat");

    byte[] buff = new byte[100];
    int b;
    while ((b = fis.read(buff)) != -1) {
        fos.write(buff, 0, b);
    }
    // 此处应调用 fis.close(); fos.close();
}

第2步:合并多个文件内容

目的:通过SequenceInputStream串联多个输入流,将它们连续读取后写入单一输出流。

@Test
public void mergeFiles() throws IOException {
    File file1 = new File("E:\\_projects\\...\\FileTests.java");
    File file2 = new File("E:\\_projects\\...\\StreamTests.java");

    Enumeration<InputStream> ins = Collections.enumeration(Arrays.asList(
            new FileInputStream(file1),
            new FileInputStream(file2)
    ));

    SequenceInputStream sequenceInputStream = new SequenceInputStream(ins);
    FileOutputStream fos = new FileOutputStream(root + "/out4");

    byte[] buff = new byte[100];
    int read;
    while ((read = sequenceInputStream.read(buff)) != -1) {
        fos.write(buff, 0, read);
    }
    fos.close();
}

第3步:读取文件为字符串

目的:使用FileReader配合StringBuilder构建完整文本内容。注意处理编码问题,避免乱码。

@Test
public void readStringFromFile() throws IOException {
    FileReader fileReader = new FileReader(new File(this.getClass().getResource("/").getPath(), "start.bat"));
    StringBuilder stringBuilder = new StringBuilder();
    int i;
    while ((i = fileReader.read()) != -1) {
        stringBuilder.append((char) i);
    }
    System.out.println(stringBuilder);
}

第4步:对象序列化与反序列化

目的:将Java对象转换为字节序列存储到文件,或从文件还原对象。对象必须实现Serializable接口。

@Test
public void objectToFile() throws IOException {
    Person person = new Person();
    person.setName("张三").setAge(25);
    String root = FileTests.class.getResource("/").getPath();
    FileOutputStream fos = new FileOutputStream(new File(root, "/person"));
    ObjectOutputStream oos = new ObjectOutputStream(fos);
    oos.writeObject(person);
    oos.close();
}

@Test
public void fileToObject() throws IOException, ClassNotFoundException {
    String root = FileTests.class.getResource("/").getPath();
    FileInputStream fis = new FileInputStream(new File(root, "/person"));
    ObjectInputStream ois = new ObjectInputStream(fis);
    Person person = (Person) ois.readObject();
    System.out.println(person);
}

Guava Files工具类的高效实践

Apache Commons IO和Google Guava都提供了更简洁的文件操作API。Guava的Files类不仅简化了常规读写,还引入了ByteSource/ByteSink抽象和内存映射技术。

基础文件操作

Guava封装了复制、移动、创建空文件等高频操作,且支持异常的统一抛出(IOException),无需繁琐的资源关闭代码。

/**
 * 文件复制
 */
@Test
public void copy() throws IOException {
    File from = new File(root,"from");
    File to = new File(root,"to");
    Files.copy(from,to);
}

/**
 * 文件移动
 */
@Test
public void move() throws IOException {
    File from = new File(root,"from");
    File to = new File(root,"to");
    Files.move(from,to);
}

/**
 * 按行读取文件
 * @throws IOException
 */
@Test
public void readLines() throws IOException {
    File dest = new File(root,"start.bat");
    List<String> lines = Files.readLines(dest, Charset.defaultCharset());
    lines.forEach(System.out::println);
}

/**
 * 写入文件
 * @throws IOException
 */
@Test
public void writeToFile() throws IOException {
    File dest = new File(root,"demo.txt");
    Files.write("hello world!".getBytes(Charset.defaultCharset()), dest);
}

/**
 * 修改文件更新时间(类似touch命令)
 * @throws IOException
 */
@Test
public void touch() throws IOException {
    File dest = new File(root,"demo.txt");
    Files.touch(dest);
}

高级IO:ByteSource与ByteSink

Guava引入ByteSource和ByteSink作为字节读写源的抽象。它们不仅代表文件,还可以代表网络流或数组,增强了组合能力。

文件转为字节数组:

@Test
public void fileAndBytes() throws IOException {
    File dest = new File(root,"start.bat");
    ByteSource byteSource = Files.asByteSource(dest);
    byte[] bytes = byteSource.read();
    System.out.println(bytes);

    // 字节写入文件,实现复制
    File target = new File(root, "start2.bat");
    ByteSink byteSink = Files.asByteSink(target);
    byteSink.write(bytes);
}

高性能操作:文件内存映射(零拷贝概念)

对于大文件处理,可以使用Files.map获取MappedByteBuffer,利用操作系统的虚拟内存机制减少用户态与内核态的数据拷贝次数。

/**
 * 文件的零拷贝(基于MappedByteBuffer)
 * @throws IOException
 */
@Test
public void map() throws IOException, URISyntaxException {
    File from = new File(root,"from");
    File to = new File(root,"to");
    Files.touch(to);
    
    MappedByteBuffer fromBuff = Files.map(from, MapMode.READ_ONLY, 1024);
    
    // => 这里演示将mapped buffer写入文件通道
    FileChannel channel = FileChannel.open(Paths.get(to.toURI()), StandardOpenOption.WRITE);
    channel.write(fromBuff);
    channel.close();
}

管道流通信示例

PipedInputStream和PipedOutputStream可用于线程间数据传输,模拟生产者-消费者模式。

@Test
public void pipe() throws IOException {
    PipedOutputStream pipedOutputStream = new PipedOutputStream();
    PipedInputStream pipedInputStream = new PipedInputStream();
    pipedOutputStream.connect(pipedInputStream);

    new Thread(()->{
        while (true){
            String date = new Date().toString();
            try {
                pipedOutputStream.write( date.getBytes(StandardCharsets.UTF_8) );
                pipedOutputStream.flush();
                TimeUnit.SECONDS.sleep(2);
            } catch (IOException | InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }).start();
    
    new Thread(()->{
        while (true){
            byte [] buff = new byte[1024];
            try {
                int read = pipedInputStream.read(buff);
                if(read > 0) {
                    System.out.println( new String(buff, 0, read) );
                }
                TimeUnit.SECONDS.sleep(4);
            } catch (IOException | InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }).start();
}

总结

Java原生IO流虽然灵活,但在处理常规文件读写时显得冗余。Guava提供的Files工具类通过ByteSource/Sink抽象和极简API(如copy, move, readLines),大幅降低了代码复杂度。对于高吞吐场景,其内置的内存映射功能也是优化IO性能的有效手段。以上就是Java中IO流与Guava使用的详细内容,更多关于Java基础与工具类优化的资料请关注本站其它相关文章!

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。