首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用Cactoos从Stdin读取行

用Cactoos从Stdin读取行
EN

Stack Overflow用户
提问于 2020-11-02 23:58:26
回答 1查看 65关注 0票数 2

我正在搜索一种使用Cactoos库从Stdin读取单行的方法。我可以这样做:

代码语言:javascript
复制
System.out.println(
  new TextOf(
    new ReaderOf(
      new Stdin()
    )
  ).asString()
);

但是这段代码会阻塞并读取Stdin/System.in,在关闭之前,我使用Ctrl+D停止读取并打印文本。有类似于BufferedReader#readLine()的行为的方法吗?

此外,我还想在阅读Stdin之前打印一些提示,如下所示:

代码语言:javascript
复制
System.out.println(
  new TextOf(
    new PromptedReaderOf( // desired decorator if I get Cactoos ideas right
      output,             // Output to display prompt-string to user
      "Type your text and press Enter: ",  // the prompt-string
      new ReaderOf(
        new Stdin()
      )
    )
  ).asString()
);

是否可以使用Cactoos,或者应该为这样的交互式控制台应用程序在Stdin周围编写自己的装饰器?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-08-09 18:29:33

,但这段代码阻塞并读取Stdin/System.in。在关闭之前,我使用Ctrl+D停止读取

这是因为读取器必须读取所有内容,包括'newline‘(\n\r)字符,直到没有任何可读取的字符(Ctrl+D,流变得有限)。

当您按下“enter”键输入换行符时,您将等待读取器停止读取无限流。例如,这种行为是在BufferedReader::read**Line**内部复制的。

TextOf(读取器)使用Reader::read (实际上它发生在ReaderAsBytes::asBytes中)。

还想在阅读Stdin之前打印一些提示,是否可以使用Cactoos,或者是否应该为这样的交互式控制台应用程序编写自己的装饰器?

因此,是的,您需要实现新的装饰师来处理您的问题。

您可能需要使用TextOf(输入)并创建一个Input装饰器,在出现'newline‘字符时生成有限的流。

代码语言:javascript
复制
public class ReaderReadLineInput implements Input {
    //we don't want to use 'new' in methods
    private final Scalar<InputStream> inputStreamScalar;

    private ReaderReadLineInput(BufferedReader bufferedReader) {
        this.inputStreamScalar = new ScalarOf<InputStream>(
            br -> new InputStreamOf(
                br.readLine() //produces finite InputStream
            ),
            bufferedReader
        );
    }
    
    public ReaderReadLineInput(Reader reader){
        this(new BufferedReader(reader));
    }

    @Override
    public InputStream stream() throws Exception {
        return inputStreamScalar.value();
    }
}

然后,您可能希望将其与实际用例(通过输入从控制台获取输入)连接起来,而不会丢失以前代码的可重用性,因此创建另一个Input装饰器。

代码语言:javascript
复制
public class ManualConsoleInput implements Input {
    //and you still don't like 'new' in methods
    private final Scalar<Input> iptScalar;

    public ManualConsoleInput(Text charsetName) {
        // do you like Cactoos primitives?
        // there's a some workaround
        this.iptScalar = new ScalarOf<Input>(
            charset -> {
                return new ReaderReadLineInput(
                    new InputStreamReader(
                        new Stdin().stream(), 
                        charset.asString() 
                    )
                )
            },
            charsetName
        );
    }

    @Override
    public InputStream stream() throws Exception {
        return this.iptScalar.value().stream();
    }
}

要在获得用户输入之前将提示文本打印到控制台,您还可能需要创建另一个装饰器。

代码语言:javascript
复制
public class InputPrintsToConsole implements Input {  
    private final Runnable printingRunnable;
    private final Input origin;

    public InputPrintsToConsole(Text textToConsole, Input origin) {
        this.printingRunnable = new ConsolePrinting(textToConsole);
        this.origin = origin;
    }

    @Override
    public InputStream stream() throws Exception {
        printingRunnable.run();
        return origin.stream();
    }
}

还请记住,例如,有些人在使用您的代码将standart输出输送到文件时可以使用System::setOut。因此,您不能仅仅依靠系统上帝-对象来获得控制台输出流,而只能使用它获得对控制台输出流的引用,当您确定:

代码语言:javascript
复制
public class ConsolePrinting extends RunnableEnvelope {
    public ConsolePrinting(Text textToPrint) {
        super(
            new OutputStreamPrinting(
                System.out, // and encapsulate somewhere 
                textToPrint
            )
        );
    }
}

// splitting responsibility of objects
// and using decorators
public class OutputStreamPrinting implements Runnable { 
    private final PrintStream printStream;
    private final Text text;

    public OutputStreamPrinting(PrintStream printStream, Text text) {
        this.printStream = printStream;
        this.text = text;
    }
    
    public OutputStreamPrinting(OutputStream outputStream, Text text) {
        this(new PrintStream(outputStream), text);
    }
    
    @Override
    public void run() {
        this.printStream.println(this.text);
    }
}

示例中的顶级代码可能如下所示:

代码语言:javascript
复制
System.out.println(
    new TextOf(
        new InputPrintsToConsole(
            new TextOf("Type your text and press Enter:"),
            new ManualConsoleInput(new TextOf("utf-8"))
        )
    )
);
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/64654957

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档