Skip to content

字符集与I/O流基础与应用指南

Published:  at  08:59 PM

字符集(Character Set)

字符集是对字符进行统一编号的一套规则
计算机底层只能存储二进制数据,二进制可以映射为整数,因此字符通过编号的方式在计算机中存储。

常见字符集:

字符集决定了字符 ↔ 字节之间的映射规则,是理解 I/O 流中文乱码问题的基础。


I/O 流概述

I/O(Input / Output)流用于完成数据在内存与外部介质之间的传输

File 类只能表示和操作文件本身,不能读写文件内容。
对文件内容的读写必须依赖 I/O 流。


I/O 流的分类

按数据流向划分


按数据单位划分


FileInputStream —— 文件字节输入流

将磁盘文件中的数据按字节读入内存

构造器

常用方法

public int read();   // 读取一个字节,读取结束返回 -1

示例:逐字节读取

FileInputStream in = new FileInputStream("text.txt");
int code;
while ((code = in.read()) != -1) {
    System.out.println((char) code);
}
in.close();

该方式效率较低,且在读取多字节字符(如中文)时会出现乱码问题。


示例:字节数组读取

FileInputStream in = new FileInputStream("text.txt");
byte[] buffer = new byte[1024];
int len = in.read(buffer);
String result = new String(buffer, 0, len);
System.out.println(result);
in.close();

缓冲数组使用注意点

若多次复用同一个字节数组,必须使用 len 限定有效数据范围:

new String(buffer, 0, len);

处理乱码的常见方式

byte[] bytes = in.readAllBytes();
String result = new String(bytes, StandardCharsets.UTF_8);

FileOutputStream —— 文件字节输出流

将内存中的数据按字节写出到磁盘文件

构造器

常用方法


示例

FileOutputStream out = new FileOutputStream("text.txt", true);
out.write("Hello IO\n".getBytes());
out.flush();
out.close();

默认情况下,输出流会覆盖原文件内容。 设置 append=true 可实现追加写入。


使用字节流复制文件

字节流适合复制任意类型文件

基本步骤

  1. 创建输入流
  2. 创建输出流
  3. 循环读写字节数组
  4. 关闭资源
FileInputStream in = new FileInputStream("src.jpg");
FileOutputStream out = new FileOutputStream("dest.jpg");
byte[] buffer = new byte[8192];
int len;
while ((len = in.read(buffer)) != -1) {
    out.write(buffer, 0, len);
}
in.close();
out.close();

FileReader —— 字符输入流

以字符为单位,将文本文件数据读入内存,自动处理编码。

构造器

方法

FileReader reader = new FileReader("text.txt");
char[] buffer = new char[1024];
int len = reader.read(buffer);
System.out.println(new String(buffer, 0, len));
reader.close();

FileWriter —— 字符输出流

将内存中的字符数据写出到文件。

构造器

方法


缓冲流(Buffered Stream)

缓冲流通过**内部缓冲区(默认 8KB)**减少系统 I/O 次数,提高性能。

字节缓冲流

BufferedInputStream bis = new BufferedInputStream(new FileInputStream("a.txt"));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("b.txt"));

字符缓冲流

支持按行读写:

BufferedReader br = new BufferedReader(new FileReader("a.txt"));
String line;
while ((line = br.readLine()) != null) {
    System.out.println(line);
}
br.close();

对象的序列化与反序列化

概念

对象必须实现 Serializable 接口。


示例

ObjectOutputStream oos =
    new ObjectOutputStream(new FileOutputStream("obj.dat"));
oos.writeObject(user);
oos.close();

ObjectInputStream ois =
    new ObjectInputStream(new FileInputStream("obj.dat"));
User u = (User) ois.readObject();
ois.close();

transient 关键字

transient 修饰的成员变量不参与序列化,常用于敏感数据。


serialVersionUID

private static final long serialVersionUID = 1L;

用于保证序列化版本一致性。


打印流(PrintStream)

特点:

PrintStream ps = new PrintStream("out.txt");
ps.println(100);
ps.println("Hello");
ps.close();

输出重定向

System.setOut(new PrintStream("log.txt"));
System.out.println("redirect output");

Properties —— 属性集文件

Properties 是基于 Map<String,String> 的集合,常用于配置文件。

写入属性文件

Properties p = new Properties();
p.setProperty("user", "root");
p.setProperty("password", "123456");
p.store(new FileOutputStream("config.properties"), null);

读取属性文件

Properties p = new Properties();
p.load(new FileInputStream("config.properties"));
System.out.println(p.getProperty("user"));

Suggest Changes

Previous Post
构造器与变量初始化及清理的安全性探讨
Next Post
递归的概念、形式与应用场景分析