Java 在Producer范例中读取文本文件

Java 在Producer范例中读取文本文件,java,io,producer-consumer,Java,Io,Producer Consumer,在producer范例中有一个读取文本文件的任务。生产者接口定义如下: public interface Producer<ITEM> { /** * Produces the next item. * * @return produced item */ ITEM next(); /** * Tells if there are more items available. * * @re

在producer范例中有一个读取文本文件的任务。生产者接口定义如下:

public interface Producer<ITEM> {
    /**
     * Produces the next item.
     *
     * @return produced item
     */
    ITEM next();

    /**
     * Tells if there are more items available.
     *
     * @return true if there are more items, false otherwise
     */
    boolean hasNext();
}
公共接口生成器{
/**
*生成下一项。
*
*@退回生产的物品
*/
下一项();
/**
*告知是否有更多可用项目。
*
*@如果有更多项目,则返回true,否则返回false
*/
布尔hasNext();
}
读取文本文件的当前代码为:

public static void readTextFile(File file, Charset charset, Consumer<String> consumer) {
    try (InputStreamReader isr = new InputStreamReader(new FileInputStream(file), charset);
         BufferedReader in = new BufferedReader(isr, BUFFER_SIZE)) {
        String line;

        while ((line = in.readLine()) != null) {
            consumer.accept(line);
        }
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
}
publicstaticvoidreadtextfile(文件文件、字符集字符集、使用者){
try(InputStreamReader isr=newinputstreamreader(newfileinputstream(file),字符集);
BufferedReader in=新的BufferedReader(isr,缓冲区大小)){
弦线;
而((line=in.readLine())!=null){
消费者接受(行);
}
}捕获(IOE异常){
抛出新的运行时异常(e);
}
}
任务是将其转换为:

public static Producer<String> readTextFileRetProducer(File file, Charset charset) {
    // ???

    return null;
}
公共静态生产者readTextFileRetProducer(文件文件,字符集字符集){
// ???
返回null;
}
接下来是一系列问题:

  • 如何正确支持hasNext,因为它需要提前阅读文本行
  • 如何正确管理异常
  • 如何正确地释放外部资源,因为在producer范例中不再提供一个方便的try-with-resources块
  • 在读取文件的最后一行后,将释放p.S.资源。(它是在之后生产的)

    p.p.S.如果有库和/或代码引用可以作为我的任务指南,请与我分享。

    快速和肮脏:

    public static Producer<String> readFile(File file, Charset charset) {
        Stream<String> stream;
        try {
            stream = Files.lines(file.toPath(), charset);
        } catch (IOException e) {
            throw new UncheckedIOException(e);
        }
        Iterator<String> iter = stream.iterator();
        return new Producer<String>() {
            @Override
            public boolean hasNext() {
                if (!iter.hasNext()) {
                    stream.close();
                    return false;
                }
                return true;
            }
            @Override
            public String next() {
                return iter.next();
            }
        };
    }
    
    publicstaticproducerreadfile(文件文件文件,字符集字符集){
    溪流;
    试一试{
    stream=Files.lines(file.toPath(),charset);
    }捕获(IOE异常){
    抛出新的未选中异常(e);
    }
    迭代器iter=stream.Iterator();
    返回新制作人(){
    @凌驾
    公共布尔hasNext(){
    如果(!iter.hasNext()){
    stream.close();
    返回false;
    }
    返回true;
    }
    @凌驾
    公共字符串next(){
    返回iter.next();
    }
    };
    }
    
    通常,对文件等资源拆分“hasNext”和“getNext”操作是不安全的,这些文件可以由多个编写器修改。您可以考虑在内存中读取整个文件,在列表中,然后使用列表迭代器来实现HasNeXT()和NEXT()方法。@亚历克斯对该方法有一个巨大的“否”,因为所讨论的文件相当大。总体任务是构建一个及时的管道,其中包含合理数量的缓存,以节省资源并使用它们仅保留可行的任务数据。@Alex此外,在hasNext方法中始终可以选择执行实际读取,并使用next仅返回实际数据。(就像java.sql.ResultSet一样)总体思路是明确的,但是这个实现不允许改变读取缓冲区大小(我相信它仍然存在)。