首页 > 编程笔记 > Java笔记 阅读:17

Java文本的读取和写入(附带实例)

在 Java 程序中,如果需要读取文本输入,那么可以使用 Reader。可以通过 InputStreamReader 适配器从任何输入流获取 Reader:
InputStream inStream = ...;
var in = new InputStreamReader(inStream, charset);

如果想一次处理一个 UTF-16 代码单元,可以调用 read() 方法:
int ch = in.read();
该方法返回一个 0~65536 的代码单元,或者在读取到输入末尾时返回 −1。当然,这种方法并不是很方便。

也可以使用以下几种替代方案:
1) 对于一个较短的文本文件,可以将其读入字符串,例如:
String content = Files.readString(path, charset);

2) 如果希望文件是一个行序列,那么可以调用:
List<String> lines = Files.readAllLines(path, charset);

3) 如果文件很大,那么可以使用 Stream<String> 进行惰性处理:
try (Stream<String> lines = Files.lines(path, charset){
    ...
}
注意,如果在流读取行时发生了 IOException 异常,这种异常将被封装为 UncheckedIOException,并从流操作中抛出。(这种伪装很有必要,因为流操作没有声明抛出任何检查型异常。)

要从文件中读取数值或单词,可以使用 Scanner,例如:
var in = new Scanner(path, StandardCharsets.UTF_8);
while (in.hasNextDouble()) {
    double value = in.nextDouble();
    ...
}

如果要读取字母单词,可以将扫描器的分隔符设置为正则表达式,即通过正则表达式来补充和确定要读取的符号。例如:
in.useDelimiter("\\PL+");
扫描器将读取字母,因为任何非字母序列都是分隔符。

可以通过以下方式获得所有单词的流:
Stream<String> words = in.tokens();

如果输入不是来自文件,那么可以将 InputStream 封装到 BufferedReader:
try (var reader =  new BufferedReader(new InputStreamReader(url.openStream()))) {
    Stream<String> lines = reader.lines();
    ...
}
BufferedReader 以数据块的形式读取输入以提高效率。(奇怪的是,这不是基本读取器的功能选项。)BufferedReader 可以通过 readLine() 方法单独读取一行,或者通过 lines() 方法生成行的流。

如果一个方法需要使用 Reader,并且你希望它能够从文件读取数据,那么可以调用:
Files.newBufferedReader(path, charset)

Java文本的写入

如果要写入文本,那么应当使用 Writer。通过 write() 方法,可以写入字符串。可以将任何输出流转换为一个 Writer:
OutputStream outStream = ...;
var out = new OutputStreamWriter(outStream, charset);
out.write(str);

如果要创建一个文件的写入器,可以使用:
Writer out = Files.newBufferedWriter(path, charset);
更方便的方法是使用 PrintWriter(),它拥有 print()、println() 和 printf ()方法,这些方法需要与 System.out 一起使用。可以直接使用它们输出数值并使用格式化输出。

如果需要写入文件,可以构造一个 PrintWriter:
var out = new PrintWriter(Files.newBufferedWriter(path, charset));

如果要写入另一个流,可以使用:
var out = new PrinterWriter(new OutputStreamWriter(outStream, charset));
注意,System.out 是 PrintStream 的一个实例,而不是 PrintWriter 的实例。这种状况是 Java 较早版本遗留下来的。但是,print()、println() 和 printf() 方法在 PrintStream 和 PrintWriter 类中的工作方式相同,都使用字符编码的方式将字符转换为字节。

如果已经有了要写入字符串的文本,可以调用:
String content = ...;
Files.write(path, content.getBytes(charset));
或者:
Files.write(path, lines, charset);
上面代码中的 lines 可以是 Collection<String>,或者是更通用的 Iterable<? extends CharSequence>。

如果要将内容附加到文件末尾,可以使用:
Files.write(path, content.getBytes(charset), StandardOpenOption.APPEND);
Files.write(path, lines, charset, StandardOpenOption.APPEND);

在使用 ISO 8859-1 等部分字符集写入文本时,任何无法映射的字符都会被自动更改为“替换字符”。在大多数情况下,替换字符是字符? 或 Unicode 替换字符 U+FFFD。

有时,一些库方法希望通过 Writer 写入输出。如果希望将输出捕获到字符串中,那么可以使用 StringWriter。如果需要使用 PrintWriter,那么应当将 StringWriter 进行如下形式的封装:
var writer = new StringWriter();
throwable.printStackTrace(new PrintWriter(writer));
String stackTrace = writer.toString();

相关文章