如何读写含单行与多行字符串的列表至文件(无分隔符方案)
可行方案汇总
除了JSON之外,你可以考虑以下几种无需分隔符或预统计行号的方案:
1. 字节长度前缀方案
通过在每个字符串前写入其UTF-8编码的字节长度,读取时先解析长度再读取对应字节数的内容,完全避免用户输入内容的干扰。
存储实现:
import java.io.FileOutputStream; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.util.List; public static void storeToFile(List<String> strings, String fileName) throws IOException { try (FileOutputStream fos = new FileOutputStream(fileName)) { for (String s : strings) { byte[] contentBytes = s.getBytes(StandardCharsets.UTF_8); // 写入长度(数字字符串+换行) String lengthStr = String.valueOf(contentBytes.length) + "\n"; fos.write(lengthStr.getBytes(StandardCharsets.UTF_8)); // 写入字符串内容字节 fos.write(contentBytes); } } }
读取实现:
import java.io.ByteArrayOutputStream; import java.io.FileInputStream; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; public static List<String> fromFile(String fileName) throws IOException { List<String> result = new ArrayList<>(); try (FileInputStream fis = new FileInputStream(fileName)) { ByteArrayOutputStream lengthBuffer = new ByteArrayOutputStream(); int byteRead; while ((byteRead = fis.read()) != -1) { if (byteRead == '\n') { // 解析长度 int contentLength = Integer.parseInt(new String(lengthBuffer.toByteArray(), StandardCharsets.UTF_8)); lengthBuffer.reset(); // 读取对应长度的内容字节 byte[] contentBytes = new byte[contentLength]; int actualRead = fis.read(contentBytes); if (actualRead != contentLength) { throw new IOException("文件读取异常:未读取到预期长度的内容"); } result.add(new String(contentBytes, StandardCharsets.UTF_8)); } else { lengthBuffer.write(byteRead); } } } return result; }
2. 转义+空行分隔方案
将字符串中的换行符转义为\n、反斜杠转义为\\,确保每个转义后的字符串都是单行,再用空行作为字符串分隔符(用户输入的内容转义后不会产生空行,因此安全)。
存储实现:
import java.io.BufferedWriter; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStreamWriter; import java.nio.charset.StandardCharsets; import java.util.List; public static void storeToFile(List<String> strings, String fileName) throws IOException { try (BufferedWriter writer = new BufferedWriter( new OutputStreamWriter(new FileOutputStream(fileName), StandardCharsets.UTF_8))) { for (int i = 0; i < strings.size(); i++) { String s = strings.get(i); // 先转义反斜杠,再转义换行符 String escaped = s.replace("\\", "\\\\").replace("\n", "\\n"); writer.write(escaped); // 非最后一个字符串后添加空行分隔 if (i != strings.size() - 1) { writer.newLine(); writer.newLine(); } } } }
读取实现:
import java.io.BufferedReader; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStreamReader; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; public static List<String> fromFile(String fileName) throws IOException { List<String> result = new ArrayList<>(); try (BufferedReader reader = new BufferedReader( new InputStreamReader(new FileInputStream(fileName), StandardCharsets.UTF_8))) { StringBuilder contentBuilder = new StringBuilder(); String line; while ((line = reader.readLine()) != null) { if (line.isEmpty()) { // 遇到空行,处理当前字符串 if (contentBuilder.length() > 0) { String unescaped = contentBuilder.toString().replace("\\n", "\n").replace("\\\\", "\\"); result.add(unescaped); contentBuilder.setLength(0); } } else { contentBuilder.append(line); } } // 处理最后一个字符串 if (contentBuilder.length() > 0) { String unescaped = contentBuilder.toString().replace("\\n", "\n").replace("\\\\", "\\"); result.add(unescaped); } } return result; }
3. Java对象序列化方案
直接使用Java内置的序列化机制,将整个List<String>写入二进制文件,读取时反序列化即可。优点是代码极简,缺点是文件不可读。
存储实现:
import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectOutputStream; import java.util.List; public static void storeToFile(List<String> strings, String fileName) throws IOException { try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(fileName))) { oos.writeObject(strings); } }
读取实现:
import java.io.FileInputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.util.List; @SuppressWarnings("unchecked") public static List<String> fromFile(String fileName) throws IOException, ClassNotFoundException { try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(fileName))) { return (List<String>) ois.readObject(); } }
4. YAML格式方案
利用YAML对多行字符串的原生支持,通过第三方库(如SnakeYAML)实现列表的序列化和反序列化,文件可读性强。
存储实现(需引入SnakeYAML依赖):
import org.yaml.snakeyaml.Yaml; import java.io.FileWriter; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.util.List; public static void storeToFile(List<String> strings, String fileName) throws IOException { Yaml yaml = new Yaml(); try (FileWriter writer = new FileWriter(fileName, StandardCharsets.UTF_8)) { yaml.dump(strings, writer); } }
读取实现:
import org.yaml.snakeyaml.Yaml; import java.io.FileReader; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.util.List; public static List<String> fromFile(String fileName) throws IOException { Yaml yaml = new Yaml(); try (FileReader reader = new FileReader(fileName, StandardCharsets.UTF_8)) { return yaml.load(reader); } }
内容的提问来源于stack exchange,提问作者moon
相关产品推荐
相关产品推荐

