我需要使用 java.nio
逐行读取文件,但 nio
没有像 readline()
这样的方法可以一次性读取一整行。有哪些解决方案?
我知道你们不喜欢限制,但是如果提问者没有访问IO包的权限,或者由于某些原因不能导入该包,则排名前几位的答案并不实用...
有两种完全不需要IO的方法:
java.nio.file.Files.lines
,
返回一系列行,这是.util包中的一部分,而不是像bufferedReader那样在.io包中。
java.nio.file.Files.readAllLines
,
返回可迭代的一系列行。使用iterator
或for each
来提取单行内容。
干杯
Files.lines
和Files.readAllLines
)实际上都是使用java.io.BufferedReader
实现的。因此,我不确定这对于想要使用非阻塞IO的OP有什么用处。 - typeracer为什么?NIO 不支持读取行。你可以使用 BufferedReader.readLine()
每秒读取数百万行。我建议这已经足够了。
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)
方法返回一个Stream
,因此您可以利用Stream API的任何其他方法,例如只读取第一行(如果存在):
Optional<String> firstLine = Files.lines(path).findFirst();
Files.lines()
是使用普通的 BufferedReader
实现的,因此仍然具有老式的阻塞 IO。顺便说一下,BufferedReader
还有一个 lines()
方法,允许将其与 Stream
API 一起使用。 - typeracer对我来说它有效....
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方法直接获取流:
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文档中的package summary页面提供了有关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以来就存在。请使用它。
BufferedReader
会带来什么好处? - Jesper