java InputStream能否从方法中连续读取数据?

java InputStream能否从方法中连续读取数据?,java,io,Java,Io,我有一段代码 ... InputStream inputStream = new BufferedInputStream(new ByteArrayInputStream("test".getBytes())); ... 这一行使字符串“test”成为InputStream的输入,然而这是一个静态InputStream。 在没有扫描仪、System.in或用户外部输入的情况下,是否有办法使此InputStream动态 我需要的是这样的东西 ... InputStream i

我有一段代码

...
InputStream inputStream = new BufferedInputStream(new ByteArrayInputStream("test".getBytes()));
...
这一行使字符串“test”成为InputStream的输入,然而这是一个静态InputStream。 在没有扫描仪、System.in或用户外部输入的情况下,是否有办法使此InputStream动态

我需要的是这样的东西

...
InputStream inputStream = new BufferedInputStream(new 
ByteArrayInputStream(generateContinuousDynamicString().getBytes()));
// So, basically input stream will be blocked until generateContinuousDynamicString()
// returns a result?
...
private static byte[] generateContinuousDynamicString(String s) {
    String t = "";
    // here comes the realization
    // that the source for an input stream 
    // cannot be generated dynamically on the 
    // fly it only can be read from already 
    // existing (fully generated and available 
    // resource). Am I right? Otherwise how 
    // can I adjust this method in such a way that
    // input stream would continuously have a new
    // string to read from? 
    for (int i = 0; i < 1000; i++){
        t += "<str>"+s+i+"</str>";
    }
    return ("<test>"+t+"</test>").getBytes();
}
我试过这样的东西

...
InputStream inputStream = new BufferedInputStream(new 
ByteArrayInputStream(generateContinuousDynamicString().getBytes()));
// So, basically input stream will be blocked until generateContinuousDynamicString()
// returns a result?
...
private static byte[] generateContinuousDynamicString(String s) {
    String t = "";
    // here comes the realization
    // that the source for an input stream 
    // cannot be generated dynamically on the 
    // fly it only can be read from already 
    // existing (fully generated and available 
    // resource). Am I right? Otherwise how 
    // can I adjust this method in such a way that
    // input stream would continuously have a new
    // string to read from? 
    for (int i = 0; i < 1000; i++){
        t += "<str>"+s+i+"</str>";
    }
    return ("<test>"+t+"</test>").getBytes();
}

这也不是动态输入流,因为数据库中已有资源。

当然。但是您有一个问题:无论是什么代码生成了无止境的动态数据流,都不能只在“返回inputstream”的方法中,这就是您的实现

您有两个主要选择:

线程 相反,您可以启动一个不断生成数据的线程。请注意,它“生成”的任何内容都需要缓存;例如,如果您想要动态生成一个只提供无限量的0字节的inputstream,那么这不是一个好的匹配。如果数据来自(比如)一个USB连接的arduino,它会时不时地发送它所连接的温度传感器的信息,这是一个很好的选择。注意,您需要线程将它接收到的数据存储到某个地方,然后有一个inputstream,它将从您正在生成的数据队列中“拉入”。要生成从队列中提取的inputstream,请参阅下一节。由于这将涉及线程,请使用
java.util.concurrent
中的一些内容,例如-这有双重好处,即您也不会得到无限的缓冲区(如果缓冲区已满,则将某些内容放入缓冲区的行为将被阻止)

子类化 你也可以做的是把能生成新值的代码放在信封里——你可以把它传递出去。您希望生成一些代码,但不运行它-您希望稍后在将inputstream交给的对象调用
.read()
时运行它

一种简单的方法是扩展InputStream,然后实现自己的zero方法。看起来像这样:


class InfiniteZeroesInputStream extends InputStream {
    public int read() {
        return 0;
    }
}
就这么简单。鉴于:

try (InputStream in = new InfiniteZeroesInputStream()) {
    in.read(); // returns 0.. and will always do so.
    byte[] b = new byte[65536];
    in.read(b); // fills the whole array with zeroes.
}
你想要个烟斗。具体来说,您需要以下一对类:

您的问题要求输入流,但由于您处理的是文本,您可能应该使用一个用于字符的阅读器。特别要注意的是,对于任何带有非ASCII字符的字符串,
getBytes()
将在Windows系统上返回与非Windows系统不同的值。使用读写器将消除对此的担忧

无论哪种方式,方法都是相同的:创建管道的可读端,然后创建管道的可写端并将其送入另一个线程

使用PipedWriter和PipedWriter:

PipedReader pipedReader = new PipedReader();
Reader reader = new BufferedReader(pipedReader);

ExecutorService executor = Executors.newSingleThreadExecutor();
Future<?> pipeFeeder = executor.submit(
    () -> generateContinuousDynamicString(pipedReader));

// ...

private Void generateContinuousDynamicString(PipedReader pipedReader)
throws IOException {

    try (Writer writer = new PipedWriter(pipedReader)) {
        writer.write("<test>");

        for (int i = 0; i < 1000; i++) {
            writer.write("<str>" + i + "</str>");
        }

        writer.write("</test>");
    }

    return null;
}
PipedReader PipedReader=新的PipedReader();
读卡器=新的BufferedReader(pipedReader);
ExecutorService executor=Executors.newSingleThreadExecutor();
Future pipeFeeder=executor.submit(
()->generateContinuousDynamicString(pipedReader));
// ...
私有Void generateContinuousDynamicString(PipedReader PipedReader)
抛出IOException{
try(Writer-Writer=newpipedwriter(pipedReader)){
作者:写(“”);
对于(int i=0;i<1000;i++){
writer.write(“+i+”);
}
作者:写(“”);
}
返回null;
}
使用PipedInputStream和PipedOutStream:

PipedInputStream pipedInputStream = new PipedInputStream();
InputStream inputStream = new BufferedInputStream(pipedInputStream);

ExecutorService executor = Executors.newSingleThreadExecutor();
Future<?> pipeFeeder = executor.submit(
    () -> generateContinuousDynamicString(pipedInputStream));

// ...

private Void generateContinuousDynamicString(PipedInputStream pipedInputStream)
throws IOException {

    Charset charset = StandardCharsets.UTF_8;

    try (Writer writer = new OutputStreamWriter(
            new PipedInputStream(pipedinputStream),
            StandardCharsets.UTF_8)) {

        writer.write("<test>");

        for (int i = 0; i < 1000; i++) {
            writer.write("<str>" + i + "</str>");
        }

        writer.write("</test>");
    }

    return null;
}
PipedInputStream PipedInputStream=new PipedInputStream();
InputStream InputStream=新的BufferedInputStream(pipedInputStream);
ExecutorService executor=Executors.newSingleThreadExecutor();
Future pipeFeeder=executor.submit(
()->generateContinuousDynamicString(pipedInputStream));
// ...
私有Void generateContinuousDynamicString(PipedInputStream PipedInputStream)
抛出IOException{
Charset Charset=StandardCharsets.UTF_8;
try(Writer-Writer=newoutputstreamwriter(
新的PipedInputStream(PipedInputStream),
标准字符集(UTF_8)){
作者:写(“”);
对于(int i=0;i<1000;i++){
writer.write(“+i+”);
}
作者:写(“”);
}
返回null;
}

谢谢您的回答。是否有可能获得与管道提供的功能相同的功能,但没有任何额外的线程或线程是必须的?如果您希望通过读取器或InputStream获得数据,则需要单独的线程。您也可以使用ByteArrayInputStream或StringReader,就像您已经在做的那样,但这需要提前生成所有内容,如果内容太多,您的程序可能会发现内存不足。