在Java开发中,基于文本文件管理结构化数据是常见的需求,相比数据库方案,文本文件存储更轻量,适合配置信息、小型业务数据等场景。常见的结构化文本格式有CSV、自定义分隔符格式、JSON等,不同格式的读写策略存在差异。

常见结构化文本格式选择
首先需要根据数据复杂度选择合适的文本格式:
- CSV格式:适合行列结构规整的数据,用逗号分隔字段,换行分隔记录,通用性强
- 自定义分隔符格式:可以用特殊字符如|、#作为分隔符,避免和字段内容冲突
- JSON格式:适合嵌套结构复杂的对象数据,可读性和扩展性更好
数据写入策略
写入结构化数据时需要保证格式规范,避免后续读取出错。以CSV格式为例,写入用户数据(包含id、姓名、年龄)的实现如下:
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class TextDataWriter {
// 定义用户数据结构
static class User {
int id;
String name;
int age;
User(int id, String name, int age) {
this.id = id;
this.name = name;
this.age = age;
}
}
public static void writeUsersToCsv(String filePath, List<User> userList) throws IOException {
try (BufferedWriter writer = new BufferedWriter(new FileWriter(filePath))) {
// 写入表头
writer.write("id,name,age");
writer.newLine();
// 写入每条用户数据
for (User user : userList) {
String line = user.id + "," + user.name + "," + user.age;
writer.write(line);
writer.newLine();
}
}
}
public static void main(String[] args) {
List<User> users = new ArrayList<>();
users.add(new User(1, "张三", 25));
users.add(new User(2, "李四", 30));
try {
writeUsersToCsv("user_data.csv", users);
System.out.println("数据写入完成");
} catch (IOException e) {
e.printStackTrace();
}
}
}
数据读取策略
读取文本结构化数据时需要对每一行进行解析,处理可能的格式异常。同样是CSV格式的用户数据读取实现:
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class TextDataReader {
static class User {
int id;
String name;
int age;
User(int id, String name, int age) {
this.id = id;
this.name = name;
this.age = age;
}
}
public static List<User> readUsersFromCsv(String filePath) throws IOException {
List<User> userList = new ArrayList<>();
try (BufferedReader reader = new BufferedReader(new FileReader(filePath))) {
String line;
// 跳过表头行
reader.readLine();
while ((line = reader.readLine()) != null) {
// 按逗号分割字段
String[] fields = line.split(",");
if (fields.length == 3) {
int id = Integer.parseInt(fields[0]);
String name = fields[1];
int age = Integer.parseInt(fields[2]);
userList.add(new User(id, name, age));
}
}
}
return userList;
}
public static void main(String[] args) {
try {
List<User> users = readUsersFromCsv("user_data.csv");
for (User user : users) {
System.out.println("id:" + user.id + ",姓名:" + user.name + ",年龄:" + user.age);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
数据更新策略
文本文件不支持随机修改,更新数据通常需要读取全部内容,修改目标记录后重新写入整个文件。以下是更新指定id用户年龄的实现:
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class TextDataUpdater {
static class User {
int id;
String name;
int age;
User(int id, String name, int age) {
this.id = id;
this.name = name;
this.age = age;
}
}
public static void updateUserAge(String filePath, int targetId, int newAge) throws IOException {
List<String> lines = new ArrayList<>();
// 读取所有行
try (BufferedReader reader = new BufferedReader(new FileReader(filePath))) {
String line;
while ((line = reader.readLine()) != null) {
lines.add(line);
}
}
// 处理表头外的数据行
for (int i = 1; i < lines.size(); i++) {
String line = lines.get(i);
String[] fields = line.split(",");
if (fields.length == 3) {
int currentId = Integer.parseInt(fields[0]);
if (currentId == targetId) {
// 替换年龄字段
fields[2] = String.valueOf(newAge);
lines.set(i, String.join(",", fields));
break;
}
}
}
// 重新写入所有内容
try (BufferedWriter writer = new BufferedWriter(new FileWriter(filePath))) {
for (String line : lines) {
writer.write(line);
writer.newLine();
}
}
}
public static void main(String[] args) {
try {
updateUserAge("user_data.csv", 1, 26);
System.out.println("数据更新完成");
} catch (IOException e) {
e.printStackTrace();
}
}
}
数据查询策略
查询操作通常基于读取后的数据集合进行过滤,也可以逐行读取时直接匹配目标条件,减少内存占用。以下是按姓名查询用户的方法:
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class TextDataQuery {
static class User {
int id;
String name;
int age;
User(int id, String name, int age) {
this.id = id;
this.name = name;
this.age = age;
}
}
public static List<User> queryUsersByName(String filePath, String targetName) throws IOException {
List<User> result = new ArrayList<>();
try (BufferedReader reader = new BufferedReader(new FileReader(filePath))) {
String line;
// 跳过表头
reader.readLine();
while ((line = reader.readLine()) != null) {
String[] fields = line.split(",");
if (fields.length == 3 && fields[1].equals(targetName)) {
int id = Integer.parseInt(fields[0]);
int age = Integer.parseInt(fields[2]);
result.add(new User(id, fields[1], age));
}
}
}
return result;
}
public static void main(String[] args) {
try {
List<User> users = queryUsersByName("user_data.csv", "张三");
for (User user : users) {
System.out.println("查询到用户:id=" + user.id + ",年龄=" + user.age);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
注意事项
- 字段内容包含分隔符时,需要对字段进行转义,比如CSV中用双引号包裹包含逗号的字段
- 多线程操作同一个文本文件时,需要添加文件锁避免数据冲突
- 数据量较大时,频繁全量读写会影响性能,可考虑分文件存储或结合缓存使用
- 写入时建议先写临时文件,完成后再替换原文件,避免写入中断导致数据损坏