Java文本的读取和写入(附带实例)
在 Java 程序中,如果需要读取文本输入,那么可以使用 Reader。可以通过 InputStreamReader 适配器从任何输入流获取 Reader:
如果想一次处理一个 UTF-16 代码单元,可以调用 read() 方法:
也可以使用以下几种替代方案:
1) 对于一个较短的文本文件,可以将其读入字符串,例如:
2) 如果希望文件是一个行序列,那么可以调用:
3) 如果文件很大,那么可以使用 Stream<String> 进行惰性处理:
要从文件中读取数值或单词,可以使用 Scanner,例如:
如果要读取字母单词,可以将扫描器的分隔符设置为正则表达式,即通过正则表达式来补充和确定要读取的符号。例如:
可以通过以下方式获得所有单词的流:
如果输入不是来自文件,那么可以将 InputStream 封装到 BufferedReader:
如果一个方法需要使用 Reader,并且你希望它能够从文件读取数据,那么可以调用:
如果要创建一个文件的写入器,可以使用:
如果需要写入文件,可以构造一个 PrintWriter:
如果要写入另一个流,可以使用:
如果已经有了要写入字符串的文本,可以调用:
如果要将内容附加到文件末尾,可以使用:
在使用 ISO 8859-1 等部分字符集写入文本时,任何无法映射的字符都会被自动更改为“替换字符”。在大多数情况下,替换字符是字符? 或 Unicode 替换字符 U+FFFD。
有时,一些库方法希望通过 Writer 写入输出。如果希望将输出捕获到字符串中,那么可以使用 StringWriter。如果需要使用 PrintWriter,那么应当将 StringWriter 进行如下形式的封装:
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();