【Java I/O 流】文件字节输入输出流:FileInputStream & FileOutputStream(文件读写案例)

简介: 本篇文章主要讲述“文件字节输入流”和“文件字节输出流”两个类的使用,并列举了一些案例,帮助学习。

在这里插入图片描述

❤️ 个人主页:水滴技术
🚀 支持水滴:点赞👍 + 收藏⭐ + 留言💬
🌸 订阅专栏:Java 教程:从入门到精通

大家好,我是水滴~~

本篇文章主要讲述“文件字节输入流”和“文件字节输出流”两个类的使用,并列举了一些案例,帮助学习。

  • 文件字节输入流(FileInputStream)用于读取文件内容。将磁盘中文件的数据,读取到内存中使用。
  • 文件字节输出流(FileOutputStream)用于向文件写入内容。将内存中的数据,写入到磁盘文件中。

在这里插入图片描述

FileInputStream(文件字节输入流)

java.io.FileInputStream 是抽象类 java.io.InputStream 的一个具体实现类,用于读取文件的原始字节流。

构造函数

FileInputStream 类有三个构造方法,构造方法需要指定要读取的文件。如果指定的文件不存在,会抛出 java.io.FileNotFoundException 异常。

FileInputStream(FileDescriptor fdObj)

通过文件描述符 FileDescriptor 创建一个 FileInputStream 实例,表示与一个实际文件的连接。

FileInputStream(File file)

通过文件 File 创建一个 FileInputStream 实例(最终会创建一个新的文件描述符),表示与一个实际文件的连接。

FileInputStream(String name)

通过文件的路径名创建一个 FileInputStream 实例。最终会创建一个 File 对象,然后调用 FileInputStream(File file) 构造方法。

常用方法

int read()

该方法从输入流读取数据的下一个字节。将读取的字节以 int 型返回,如果读取至末尾,则返回值 -1 。

int read(byte b[])

从输入流中读取多个字节,并将它们存储至缓冲区 b 中。读取的字节数最多等于 b 的长度,也可以读取比 b 长度小的字节数。返回值为实际读取的字节数,如果没有可读取的字节,则返回值 -1。

int read(byte b[], int off, int len)

从输入流中读取 len 个字节,并从缓存区 boff 下标处开始存储(即读取的第一个字节存入缓 b[off] 中,下一个字节存入 b[off + 1] 中...)。同样返回值为实际读取的字节数,如果没有可读取的字节,则返回值 -1。

int available()

返回该输入流中可读取的有效字节数。

void close()

关闭该输入流,并释放与之相关的所有系统资源。

读取文件的案例

通过一些案例来演示 FileInputStream 的使用,加深记忆。

案例一:一次读取一个字节

创建一个文件:C:\io\01.txt,文件内容为:abc

代码示例:

public static void read1() throws IOException {
   
   
    // 通过文件路径创建 FileInputStream 实例
    FileInputStream fis = new FileInputStream("c:/io/01.txt");

    // 可读取的字节数
    System.out.println("可读取的字节数: " + fis.available());

    // 读取一个字节
    int read = fis.read();
    System.out.println("可读取的字节数: " + fis.available() + "\t读取内容: " + read);

    // 读取一个字节
    read = fis.read();
    System.out.println("可读取的字节数: " + fis.available() + "\t读取内容: " + read);

    // 读取一个字节
    read = fis.read();
    System.out.println("可读取的字节数: " + fis.available() + "\t读取内容: " + read);

    // 读取一个字节
    read = fis.read();
    System.out.println("可读取的字节数: " + fis.available() + "\t读取内容: " + read);

    // 关闭输入流
    fis.close();
}

输出内容:

可读取的字节数: 3
可读取的字节数: 2  读取内容: 97
可读取的字节数: 1  读取内容: 98
可读取的字节数: 0  读取内容: 99
可读取的字节数: 0  读取内容: -1

通过该案例可以发现:

  • read() 方法读取的字节以 int 型返回。如上例,a的 ASCII 码值为 97b的 ASCII 码值为 98c的 ASCII 码值为 99
  • 读取完最后一个字节,available() 可读取的字节数为0
  • 读取完最后一个字节,再次 read() 读取,返回值为 -1
  • 最后不要完了关闭流。

案例二:通过循环判断可读取字节数,一次读取一个字节

使用案例一中的文件:C:\io\01.txt,文件内容为:abc

代码示例:

public static void read2() throws IOException {
   
   
    // 通过文件路径创建 FileInputStream 实例
    FileInputStream fis = new FileInputStream("c:/io/01.txt");

    // 循环判断可读取字节数
    while (fis.available() > 0) {
   
   
        // 读取一个字节
        int read = fis.read();
        System.out.println("可读取的字节数: " + fis.available() + "\t读取内容: " + read);
    }

    // 关闭输入流
    fis.close();
}

输出内容:

可读取的字节数: 2  读取内容: 97
可读取的字节数: 1  读取内容: 98
可读取的字节数: 0  读取内容: 99

案例三:通过循环判断是否读到末尾,一次读取一个字节

使用案例一中的文件:C:\io\01.txt,文件内容为:abc

代码示例:

public static void read3() throws IOException {
   
   
    // 通过文件路径创建 FileInputStream 实例
    FileInputStream fis = new FileInputStream("c:/io/01.txt");

    int read;
    // 循环读取一个字节,每次判断是否到达末尾
    while ((read = fis.read()) != -1) {
   
   
        System.out.println("可读取的字节数: " + fis.available() + "\t读取内容: " + (char)read);
    }

    // 关闭输入流
    fis.close();
}

输出内容:

可读取的字节数: 2  读取内容: a
可读取的字节数: 1  读取内容: b
可读取的字节数: 0  读取内容: c

案例四:一次读取多个字节

使用案例一中的文件:C:\io\01.txt,文件内容为:abc

代码示例:通过 new String(bytes) 方法将读取的字节数组转为字符串

public static void read4() throws IOException {
   
   
    // 通过文件路径创建 FileInputStream 实例
    FileInputStream fis = new FileInputStream("c:/io/01.txt");
    // 可读取的字节数
    System.out.println("可读取的字节数: " + fis.available());

    // 字节数组,缓存读取的内容
    byte[] bytes = new byte[2];

    // 一次读取多个字节
    int len = fis.read(bytes);
    System.out.println("可读取的字节数: " + fis.available() + "\t读取的字节数: " + len + "\t读取内容: " + new String(bytes));

    // 一次读取多个字节
    len = fis.read(bytes);
    System.out.println("可读取的字节数: " + fis.available() + "\t读取的字节数: " + len + "\t读取内容: " + new String(bytes));

    // 一次读取多个字节
    len = fis.read(bytes);
    System.out.println("可读取的字节数: " + fis.available() + "\t读取的字节数: " + len + "\t读取内容: " + new String(bytes));

    // 关闭输入流
    fis.close();
}

输出内容:

可读取的字节数: 3
可读取的字节数: 1  读取的字节数: 2   读取内容: ab
可读取的字节数: 0  读取的字节数: 1   读取内容: cb
可读取的字节数: 0  读取的字节数: -1  读取内容: cb

通过该案例可以发现:

  • read()方法返回值为读取的内容;而read(bytes)方法返回值为读取的字节数。
  • 字节数组未被填满时,剩余位置会保留原来的值。
  • 通过 new String(bytes) 方法可以将字节数组转为字符串。

案例五:通过循环判断可读取字节数,一次读取多个字节

使用案例一中的文件:C:\io\01.txt,文件内容为:abc

代码示例:

public static void read5() throws IOException {
   
   
    // 通过文件路径创建 FileInputStream 实例
    FileInputStream fis = new FileInputStream("c:/io/01.txt");

    // 字节数组,缓存读取的内容
    byte[] bytes = new byte[2];

    while (fis.available() > 0) {
   
   
        // 一次读取多个字节
        int len = fis.read(bytes);
        System.out.println("可读取的字节数: " + fis.available() + "\t读取的字节数: " + len + "\t读取内容: " + new String(bytes, 0, len));
    }

    // 关闭输入流
    fis.close();
}

输出内容:

可读取的字节数: 1  读取的字节数: 2  读取内容: ab
可读取的字节数: 0  读取的字节数: 1  读取内容: c

通过该案例可以发现:

  • 使用 new String(bytes, 0, len) 方法可以将有效的字节转为字符串,解决了数组未填满的情况。

案例六:通过循环判断是否读到末尾,一次读取多个字节

使用案例一中的文件:C:\io\01.txt,文件内容为:abc

代码示例:

public static void read6() throws IOException {
   
   
    // 通过文件路径创建 FileInputStream 实例
    FileInputStream fis = new FileInputStream("c:/io/01.txt");

    // 字节数组,缓存读取的内容
    byte[] bytes = new byte[2];
    int len;
    // 循环读取一个字节,每次判断是否到达末尾
    while ((len = fis.read(bytes)) != -1) {
   
   
        System.out.println("可读取的字节数: " + fis.available() + "\t读取的字节数: " + len + "\t读取内容: " + new String(bytes, 0, len));
    }

    // 关闭输入流
    fis.close();

}

输出内容:

可读取的字节数: 1  读取的字节数: 2  读取内容: ab
可读取的字节数: 0  读取的字节数: 1  读取内容: c

FileOutputStream(文件字节输出流)

java.io.FileOutputStream 是抽象类 java.io.OutputStream 的一个具体实现类,用于将数据写入到文件的输出流中。某些平台允许一次只能打开一个文件输出流。

构造函数

FileOutputStream 类有五个构造函数,构造函数需要指定要写入的目标文件。如果目标文件所属目录不存在,会抛出 java.io.FileNotFoundException 异常;如果仅是目标文件不存在,会创建一个文件。

FileOutputStream(FileDescriptor fdObj)

通过指定的文件描述符 FileDescriptor 创建一个 FileOutputStream 实例,表示与一个实际文件的连接。

FileOutputStream(File file, boolean append)

通过指定的文件File创建一个FileOutputStream 实例。如果appendtrue,表示从末尾追加,否则会将原数据覆盖。

FileOutputStream(File file)

通过指定的文件 File 创建一个FileOutputStream 实例,默认覆盖文件中原数据。

FileOutputStream(String name, boolean append)

通过文件的路径名创建一个 FileOutputStream 实例。如果appendtrue,表示从末尾追加,否则会将原数据覆盖。

FileOutputStream(String name)

通过文件的路径名创建一个 FileOutputStream 实例,默认覆盖文件中原数据。

常用方法

void write(int b)

向输出流中写入一个字节。该方法是一个抽象方法,要求子类必须实现此方法。

void write(byte b[])

向输出流中写入多个字节。该方法将缓存区 b 中的字节写入到输出流中。

void write(byte b[], int off, int len)

向输出流中写入多个字节,从缓存区 boff 下标处开始写入 len 个字节。

void flush()

刷新该输出流,强制将缓存区中的字节写出去。

void close()

关闭该输出流,并释放与之相关的所有资源。

写入文件的案例

案例一:一次写入一个字节

代码示例:

public static void write1() throws IOException {
   
   
    // 通过文件路径创建 FileOutputStream 实例
    FileOutputStream fos = new FileOutputStream("c:/io/02.txt");

    // 写入一个字节 97=a
    fos.write(97);
    // 写入一个字节 98=b
    fos.write(98);
    // 写入一个字节 99=c
    fos.write(99);

    // 关闭输出流
    fos.close();
}

会创建一个c:/io/02.txt 文件,文件内容为:abc

案例二:一次写入多个字节

代码示例:

public static void write2() throws IOException {
   
   
    // 通过文件路径创建 FileOutputStream 实例
    FileOutputStream fos = new FileOutputStream("c:/io/03.txt");

    String str = "水滴abc";
    byte[] bytes = str.getBytes();
    fos.write(bytes);

    // 关闭输出流
    fos.close();
}

会创建一个c:/io/03.txt 文件,文件内容为:水滴abc

案例三:一次写入多个字节,指定字节数组的偏移量

代码示例:

public static void write3() throws IOException {
   
   
    // 通过文件路径创建 FileOutputStream 实例
    FileOutputStream fos = new FileOutputStream("c:/io/04.txt");

    String str = "水滴abc";
    byte[] bytes = str.getBytes();
    fos.write(bytes, 0, bytes.length - 3);

    // 关闭输出流
    fos.close();
}

会创建一个c:/io/03.txt 文件,文件内容为:水滴


系列文章

相关文章
|
9月前
|
安全 Java API
Java 集合高级应用与实战技巧之高效运用方法及实战案例解析
本课程深入讲解Java集合的高级应用与实战技巧,涵盖Stream API、并行处理、Optional类、现代化Map操作、不可变集合、异步处理及高级排序等核心内容,结合丰富示例,助你掌握Java集合的高效运用,提升代码质量与开发效率。
369 0
|
9月前
|
安全 JavaScript Java
java Web 项目完整案例实操指南包含从搭建到部署的详细步骤及热门长尾关键词解析的实操指南
本项目为一个完整的JavaWeb应用案例,采用Spring Boot 3、Vue 3、MySQL、Redis等最新技术栈,涵盖前后端分离架构设计、RESTful API开发、JWT安全认证、Docker容器化部署等内容,适合掌握企业级Web项目全流程开发与部署。
796 0
|
10月前
|
缓存 算法 NoSQL
校招 Java 面试高频常见知识点深度解析与实战案例详细分享
《2025校招Java面试核心指南》总结了Java技术栈的最新考点,涵盖基础语法、并发编程和云原生技术三大维度: 现代Java特性:重点解析Java 17密封类、Record类型及响应式Stream API,通过电商案例演示函数式数据处理 并发革命:对比传统线程池与Java 21虚拟线程,详解Reactor模式在秒杀系统中的应用及背压机制 云原生实践:提供Spring Boot容器化部署方案,分析Spring WebFlux响应式编程和Redis Cluster缓存策略。
298 1
|
10月前
|
人工智能 Java API
Java 生态大模型应用开发全流程实战案例与技术路径终极对决
在Java生态中开发大模型应用,Spring AI、LangChain4j和JBoltAI是三大主流框架。本文从架构设计、核心功能、开发体验、性能扩展性、生态社区等维度对比三者特点,并结合实例分析选型建议。Spring AI适合已有Spring技术栈团队,LangChain4j灵活性强适用于学术研究,JBoltAI提供开箱即用的企业级解决方案,助力传统系统快速AI化改造。开发者可根据业务场景和技术背景选择最适合的框架。
2362 2
|
10月前
|
自然语言处理 前端开发 Java
JBoltAI 框架完整实操案例 在 Java 生态中快速构建大模型应用全流程实战指南
本案例基于JBoltAI框架,展示如何快速构建Java生态中的大模型应用——智能客服系统。系统面向电商平台,具备自动回答常见问题、意图识别、多轮对话理解及复杂问题转接人工等功能。采用Spring Boot+JBoltAI架构,集成向量数据库与大模型(如文心一言或通义千问)。内容涵盖需求分析、环境搭建、代码实现(知识库管理、核心服务、REST API)、前端界面开发及部署测试全流程,助你高效掌握大模型应用开发。
947 5
|
10月前
|
缓存 Java API
Java 集合容器实操技巧与案例详解
本教程基于Java 8+新特性和现代开发实践,深入讲解Java集合容器的实操技巧。通过具体场景演示Stream API数据处理、ConcurrentHashMap并发控制、LinkedHashMap实现LRU缓存、TreeSet自定义排序等高级特性。同时涵盖computeIfAbsent优化操作、EnumMap专用集合使用、集合统计与运算(交集、并集、差集)等内容。代码示例丰富,助力掌握高效编程方法。[点击获取完整代码](https://pan.quark.cn/s/14fcf913bae6)。
209 0
|
10月前
|
前端开发 JavaScript Java
Java 学习路线规划及项目案例中的技术栈应用解析
内容包括:**Java 17核心特性**(如sealed class、record)与模块化开发;Spring Boot 3 + Spring Cloud微服务架构,涉及响应式编程(WebFlux)、多数据库持久化(JPA、R2DBC、MongoDB);云原生技术**如Docker、Kubernetes及CI/CD流程;性能优化(GraalVM Native Image、JVM调优);以及前后端分离开发(Vue 3、Spring Boot集成)。通过全栈电商平台项目实战,掌握从后端服务(用户、商品、订单)到前端应用(Vue 3、React Native)的全流程开发。
465 9
|
10月前
|
存储 Java 数据安全/隐私保护
Java技术栈揭秘:Base64加密和解密文件的实战案例
以上就是我们今天关于Java实现Base64编码和解码的实战案例介绍。希望能对你有所帮助。还有更多知识等待你去探索和学习,让我们一同努力,继续前行!
658 5
|
10月前
|
缓存 NoSQL Java
校招 Java 面试常见知识点及实战案例全解析
本文全面解析了Java校招面试中的常见知识点,涵盖Java新特性(如Lambda表达式、、Optional类)、集合框架高级应用(线程安全集合、Map性能优化)、多线程与并发编程(线程池配置)、JVM性能调优(内存溢出排查、垃圾回收器选择)、Spring与微服务实战(Spring Boot自动配置)、数据库与ORM框架(MyBatis高级用法、索引优化)、分布式系统(分布式事务、缓存应用)、性能优化(接口优化、高并发限流)、单元测试与代码质量(JUnit 5、Mockito、JaCoCo)以及项目实战案例(电商秒杀系统、社交消息推送)。资源地址: [https://pan.quark.cn/s
275 4
|
10月前
|
人工智能 Java 开发者
【Java实例-简易计算机】使用Java实现简单的计算机案例
一个简单的Java案例——“简易计算器”,帮助编程新手快速上手。通过实现用户输入、基本逻辑运算和结果输出,学习者可以掌握变量声明、Scanner对象使用、控制流语句等关键知识点。文章分为设计思路、关键知识点、完整代码和测试运行四个部分。
285 9
【Java实例-简易计算机】使用Java实现简单的计算机案例