我需要使用 逐行读取文件java.nio
,但nio
没有像readline()
一次读取一个完整行的方法。有哪些解决方案?
9 回答
我知道你们不喜欢限制,但如果询问者无权访问 IO 包或由于某种原因不允许导入它,那么最佳答案没有帮助......
完全免费的两种方法:
java.nio.file.Files.lines
, 返回一个行流,它是 .util 包的一部分,而不是像 bufferedReader 这样的 .io 包。java.nio.file.Files.readAllLines
, 返回可迭代的行集合。继续使用iterator
或for each
提取单行。
干杯
为什么?NIO 不支持读线。你可以每秒阅读数百万行,BufferedReader.readLine().
我认为这就足够了。
Oracle 在教程中介绍了一个示例。 https://docs.oracle.com/javase/tutorial/essential/io/file.html#streams
Path file = ...;
try (InputStream in = Files.newInputStream(file);
BufferedReader reader =
new BufferedReader(new InputStreamReader(in))) {
String line = null;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
} catch (IOException x) {
System.err.println(x);
}
使用java.nio.file.Files
您可以执行以下操作:
Path path = FileSystems.getDefault().getPath("/path/to", "file.txt");
Files.lines(path).forEach(line ->
// consume line
);
当该lines(path)
方法返回 aStream
时,您可以利用 Stream API 的任何其他方法,例如仅读取第一行(如果存在):
Optional<String> firstLine = Files.lines(path).findFirst();
这个对我有用....
public static void main(String[] args) throws IOException
{
RandomAccessFile aFile = new RandomAccessFile
("F:\\DetailsMy1.txt", "r");
FileChannel inChannel = aFile.getChannel();
ByteBuffer buffer = ByteBuffer.allocate(1);
StringBuffer line = new StringBuffer();
while(inChannel.read(buffer) > 0)
{
buffer.flip();
for (int i = 0; i < buffer.limit(); i++)
{
char ch = ((char) buffer.get());
if(ch=='\r'){
System.out.print(line+"[EOL]");
line=new StringBuffer();
}else{
line.append(ch);
}
}
buffer.clear(); // do something with the data and clear/compact it.
}
inChannel.close();
aFile.close();
}
为了支持 EJP 和上面的其他内容,您可以参考这篇文章:http ://www.javaworld.com/article/2078654/java-se/java-se-five-ways-to-maximize-java-nio-and- nio-2.html
特别是:“虽然 NIO 经常因其性能优势而被宣传,但更准确的说法是它具有高响应性。在某些情况下,NIO 的性能实际上比基本的 Java I/O 还要差。例如,对于小文件的简单顺序读取和写入, 一个简单的流实现可能比相应的面向事件的基于通道的编码快两到三倍。此外, 非多路复用通道 - 即单独线程中的通道 - 可能比注册其选择器的通道慢得多在一个线程中。”
我要强调 NIO在某些情况下 [...] 的性能比基本 Java I/O 差。作者随后列出了一系列问题,以推动快速分析 NIO 是否是正确的选择。如果您(或接下来的人)仍然决定追求 NIO,那么可以通过代码示例很好地解释它的使用。
1)您可以使用 lines 方法将 BufferedReader 转换为 Stream
List<String> list = new ArrayList<>();
try (BufferedReader br = new BufferedReader(new FileReader(file))) {
list = br.lines().collect(Collectors.toList());
}
2) 直接使用 Files.lines 方法获取一个 Stream:
try (Stream<String> stream = Files.lines(Paths.get(fileName))) {
stream
.filter(s -> s.endswith("/"))
.map(String::toUpperCase)
.forEach(System.out::println);
}
正如 DanielBraun 在他的回答中指出的那样,您也可以使用 readAllLines 方法而不是 lines 方法,区别在于,直接来自文档:
与 readAllLines 不同,此方法不会将所有行读入 List,而是在使用流时延迟填充。
Java 文档中的包摘要页面提供了关于 Streams 的简洁明了的概述,本文还列出了一些其他在 Java 中逐行读取文件的方法。
NIO 通常用于执行直接内存访问或块介导的批量数据传输。它确实做其他事情,但其他功能更多地与阻塞和非阻塞数据访问有关。
因此,您可能希望使用 NIO 快速(或以非阻塞方式)获取数据;但是,如果您想“逐行读取”,则最好在 NIO 读取可用数据后进行行检测。这可以通过在 NIO 刚刚读取的缓冲区上放置一个“行读取”外观来轻松实现。
只需使用: https ://docs.oracle.com/javase/8/docs/api/java/nio/file/Files.html#lines-java.nio.file.Path-
编辑(人类可读的翻译,关于 MeetTitan):这意味着:使用java.nio.file.Files.lines(Path)
- 它返回一个Stream<String>
代表文件行的。它是 Java API 提供的一种方法。可以查阅 Javadoc 以查看详细信息。因此,最相关的信息是:Files.lines()
自 Java 1.8 以来就存在。用它。