拓冰建站拓冰建站
首页 / 资讯中心 / 正文

Java IO流详解:从InputStream到文件操作实战

目录一、InputStream字节输入流概述二、InputStream常用子类三、FileInputStream文件输入流详解3.1 构造方法3.2 核心方法read()1. read() - 读取单个字节2. read(byte[] b) - 读取到字节数组3. read(byte[] b, int off, int len) - 带偏移量的读取四、FileInputStream实战读取文本文件4.1 基础读取示例4.2 中文读取问题分析4.3 优化方案使用字节数组读取五、FileOutputStream文件输出流5.1 构造方法5.2 核心方法write()5.3 实战示例写入字符串到文件六、综合实战图片文件拷贝七、其他重要字节流7.1 BufferedInputStream缓冲字节输入流7.2 ObjectInputStream对象字节输入流八、总结与最佳实践一、InputStream字节输入流概述InputStream是 Java IO 体系中所有字节输入流类的抽象父类它定义了读取字节数据的基本操作。作为抽象类InputStream 本身不能被实例化但它的各种子类为不同的数据源如文件、网络、内存等提供了具体的实现。二、InputStream常用子类InputStream 的主要子类包括FileInputStream文件输入流用于从文件中读取字节数据ByteArrayInputStream字节数组输入流从内存中的字节数组读取数据BufferedInputStream缓冲字节输入流提供缓冲功能以提高读取效率ObjectInputStream对象字节输入流用于反序列化对象DataInputStream数据输入流用于读取基本数据类型三、FileInputStream文件输入流详解3.1 构造方法FileInputStream 提供了三种主要的构造方法// 1. 通过File对象构造 File file new File(test.txt); FileInputStream fis1 new FileInputStream(file); // 2. 通过文件描述符构造 FileDescriptor fd ...; FileInputStream fis2 new FileInputStream(fd); // 3. 通过文件路径字符串构造 FileInputStream fis3 new FileInputStream(test.txt);3.2 核心方法read()FileInputStream 提供了三个重载的 read() 方法1. read() - 读取单个字节// 从输入流中读取一个字节返回值为int类型0-255 // 当读取到文件末尾时返回-1 int byteData fis.read();2. read(byte[] b) - 读取到字节数组// 从输入流中读取最多b.length个字节到字节数组b中 // 返回实际读取的字节数文件末尾返回-1 byte[] buffer new byte[1024]; int bytesRead fis.read(buffer);3. read(byte[] b, int off, int len) - 带偏移量的读取// 从输入流中读取最多len个字节到字节数组b中 // off表示数组b中的起始偏移量 byte[] buffer new byte[1024]; int bytesRead fis.read(buffer, 0, 1024);四、FileInputStream实战读取文本文件4.1 基础读取示例使用 FileInputStream 读取 test.txt 文件内容并打印到控制台import java.io.FileInputStream; import java.io.IOException; public class FileInputStreamDemo { public static void main(String[] args) { FileInputStream fis null; try { // 创建文件输入流 fis new FileInputStream(test.txt); int byteData; // 循环读取直到文件末尾 while ((byteData fis.read()) ! -1) { System.out.print((char) byteData); } } catch (IOException e) { e.printStackTrace(); } finally { // 必须关闭流释放资源 if (fis ! null) { try { fis.close(); } catch (IOException e) { e.printStackTrace(); } } } } }4.2 中文读取问题分析重要提醒使用 read() 方法读取中文文件会出现乱码原因分析中文字符在 UTF-8 编码中通常占用 3 个字节read() 方法每次只能读取 1 个字节将单个字节强制转换为 char 会导致编码错误示例读取 你好 这两个中文字符// 错误示例 - 会出现乱码 while ((byteData fis.read()) ! -1) { System.out.print((char) byteData); // 输出乱码 }4.3 优化方案使用字节数组读取为了提高读取效率和正确处理中文推荐使用 read(byte[] b) 方法import java.io.FileInputStream; import java.io.IOException; public class EfficientFileReader { public static void main(String[] args) { FileInputStream fis null; try { fis new FileInputStream(test.txt); byte[] buffer new byte[1024]; // 1KB缓冲区 int bytesRead; while ((bytesRead fis.read(buffer)) ! -1) { // 将字节数组转换为字符串指定编码 String content new String(buffer, 0, bytesRead, UTF-8); System.out.print(content); } } catch (IOException e) { e.printStackTrace(); } finally { if (fis ! null) { try { fis.close(); } catch (IOException e) { e.printStackTrace(); } } } } }注意如果一次读取的数据量小于数组长度之前读取的值不会被清空因此需要使用 bytesRead 参数来限制转换的范围。五、FileOutputStream文件输出流5.1 构造方法FileOutputStream 的主要构造方法// 1. 通过文件路径创建覆盖模式 FileOutputStream fos1 new FileOutputStream(output.txt); // 2. 通过文件路径创建追加模式 FileOutputStream fos2 new FileOutputStream(output.txt, true); // 3. 通过File对象创建 File file new File(output.txt); FileOutputStream fos3 new FileOutputStream(file); // 4. 通过File对象创建追加模式 FileOutputStream fos4 new FileOutputStream(file, true);参数说明第二个 boolean 参数为 true 表示追加模式为 false 或不写表示覆盖模式。5.2 核心方法write()FileOutputStream 提供了三个重载的 write() 方法// 1. 写入单个字节 fos.write(65); // 写入字符A // 2. 写入字节数组 byte[] data Hello.getBytes(); fos.write(data); // 3. 写入字节数组的指定部分 byte[] data2 Hello World.getBytes(); fos.write(data2, 6, 5); // 写入World5.3 实战示例写入字符串到文件import java.io.FileOutputStream; import java.io.IOException; public class FileOutputStreamDemo { public static void main(String[] args) { FileOutputStream fos null; try { // 创建文件输出流如果文件不存在会自动创建 fos new FileOutputStream(test.txt); // 要写入的字符串 String content Hello World; // 将字符串转换为字节数组可指定编码 byte[] bytes content.getBytes(UTF-8); // 写入文件 fos.write(bytes); System.out.println(文件写入成功); } catch (IOException e) { e.printStackTrace(); } finally { if (fos ! null) { try { fos.close(); } catch (IOException e) { e.printStackTrace(); } } } } }六、综合实战图片文件拷贝使用 FileInputStream 和 FileOutputStream 实现图片文件拷贝功能import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; public class ImageCopy { public static void main(String[] args) { FileInputStream fis null; FileOutputStream fos null; try { // 创建输入流读取源图片 fis new FileInputStream(source.png); // 创建输出流写入目标文件 fos new FileOutputStream(copy.png); // 使用缓冲区提高拷贝效率 byte[] buffer new byte[8192]; // 8KB缓冲区 int bytesRead; // 循环读取并写入 while ((bytesRead fis.read(buffer)) ! -1) { // 重要必须指定长度否则可能写入错误数据 fos.write(buffer, 0, bytesRead); } System.out.println(图片拷贝完成); } catch (IOException e) { e.printStackTrace(); } finally { // 关闭输入流 if (fis ! null) { try { fis.close(); } catch (IOException e) { e.printStackTrace(); } } // 关闭输出流 if (fos ! null) { try { fos.close(); } catch (IOException e) { e.printStackTrace(); } } } } }重要提醒在 write() 方法中必须指定长度参数bytesRead如果错误地写成 write(buffer)可能会写入多余的旧数据导致文件大小不正确。虽然某些图片查看器可能仍然能打开但文件内容已经损坏。七、其他重要字节流7.1 BufferedInputStream缓冲字节输入流BufferedInputStream 为输入流提供缓冲功能可以显著提高读取效率import java.io.BufferedInputStream; import java.io.FileInputStream; import java.io.IOException; public class BufferedStreamDemo { public static void main(String[] args) { try (BufferedInputStream bis new BufferedInputStream( new FileInputStream(largefile.dat))) { byte[] buffer new byte[8192]; int bytesRead; while ((bytesRead bis.read(buffer)) ! -1) { // 处理数据 } } catch (IOException e) { e.printStackTrace(); } } }7.2 ObjectInputStream对象字节输入流ObjectInputStream 用于反序列化对象通常与 ObjectOutputStream 配合使用import java.io.FileInputStream; import java.io.IOException; import java.io.ObjectInputStream; public class ObjectStreamDemo { public static void main(String[] args) { try (ObjectInputStream ois new ObjectInputStream( new FileInputStream(object.dat))) { // 读取对象 Object obj ois.readObject(); System.out.println(读取的对象: obj); } catch (IOException | ClassNotFoundException e) { e.printStackTrace(); } } }八、总结与最佳实践1. 资源管理必须使用 try-with-resources 或 finally 块确保流被关闭2. 编码处理处理文本文件时明确指定字符编码如 UTF-83. 缓冲区使用使用适当大小的缓冲区提高IO效率4. 异常处理正确处理 IOException避免资源泄漏5. 文件操作FileOutputStream 会自动创建不存在的文件但不会创建目录通过本文的学习你应该已经掌握了 Java 字节输入输出流的基本原理和实战应用。在实际开发中建议优先使用 Java NIO 的 Files 和 Paths 类进行文件操作它们提供了更简洁、更安全的API。
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门