简体   繁体   English

使用 Reactor 非阻塞读取文件

[英]Non-blocking reading from the file using Reactor

Do you know if it's possible to create Flux of file lines really non-blocking way?你知道是否有可能以非阻塞方式创建文件行的 Flux 吗?

The best solution I've found is next:我找到的最佳解决方案是下一个:

Flux.using(
           () -> Files.lines(PATH),
           Flux::fromStream,
           Stream::close
 );

Even though it looks non-blocking but it is blocking under the hood.即使它看起来没有阻塞,但它在引擎盖下是阻塞的。

https://docs.oracle.com/javase/8/docs/api/java/nio/file/Files.html#lines-java.nio.file.Path-java.nio.charset.Charset- https://docs.oracle.com/javase/8/docs/api/java/nio/file/Files.html#lines-java.nio.file.Path-java.nio.charset.Charset-

Read all lines from a file as a Stream.从文件中读取所有行作为 Stream。 Unlike readAllLines, this method does not read all lines into a List, but instead populates lazily as the stream is consumed.与 readAllLines 不同,此方法不会将所有行读入 List,而是在 stream 被消耗时延迟填充。

The returned stream encapsulates a Reader.返回的 stream 封装了一个 Reader。

Is it possible to create Flux from AsynchronousFileChannel?是否可以从 AsynchronousFileChannel 创建 Flux?

Thank you in advance先感谢您

Files.lines(PATH) is completely IO-free. Files.lines(PATH)完全没有 IO。 It's part of the NIO (NIO stands for non-blocking I/O or New I/O) Java API.它是 NIO 的一部分(NIO 代表非阻塞 I/O 或新 I/O)Java API。 It lazily returns a stream of lines, which is part of .util package and not .io package like BufferedReader . It lazily returns a stream of lines, which is part of .util package and not .io package like BufferedReader .

If you have Spring Framework on classpath, then you can do the following:如果您在类路径上有 Spring 框架,那么您可以执行以下操作:

import org.springframework.core.codec.StringDecoder;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.core.io.buffer.DefaultDataBufferFactory;

import java.nio.channels.AsynchronousFileChannel;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;

public class AsyncFileRead {
    public static void main(String[] args) {
        StringDecoder stringDecoder = StringDecoder.textPlainOnly();

        DataBufferUtils.readAsynchronousFileChannel(() -> AsynchronousFileChannel.open(Path.of("test/sample.txt"),
                StandardOpenOption.READ), DefaultDataBufferFactory.sharedInstance, 4096)
            .transform(dataBufferFlux -> stringDecoder.decode(dataBufferFlux, null, null, null))
            .blockLast();
    }
}

Alternatively, you can use RxIo library which provides a nice abstraction similar to java.nio.file.Files just with async/reactive support:或者,您可以使用RxIo库,它提供了类似于java.nio.file.Files的漂亮抽象,仅支持异步/反应式:

import org.javaync.io.AsyncFiles;
import reactor.core.publisher.Flux;

import java.nio.file.Path;

public class AsyncFileRead {
    public static void main(String[] args) {
        Flux.from(AsyncFiles.lines(Path.of("test/sample.txt")))
            .blockLast();
    }
}

Although, it's important to note that even these solutions are not truly non-blocking as depending on the platform (Windows, Linux) AsynchronousFileChannel implementation can be blocking under the hood but at least it delegates that task to a dedicated thread pool.虽然,重要的是要注意,即使这些解决方案也不是真正的非阻塞,因为取决于平台(Windows、Linux), AsynchronousFileChannel实现可能在后台阻塞,但至少它将该任务委托给专用线程池。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM