java InputStream 的自定义实现
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4805191/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Custom implementation of InputStream
提问by John Manak
To send data to a file on my FTP server, I need to create a custom InputStream implementation that reads database data row by row, converts it to CSV and publishes it via its read() methods: from the database, I get a List<Application>
object with the data. For each Application
object, I want to create a line in the CSV file.
要将数据发送到我的 FTP 服务器上的文件,我需要创建一个自定义 InputStream 实现,它逐行读取数据库数据,将其转换为 CSV 并通过其 read() 方法发布:从数据库中,我得到一个List<Application>
对象数据。对于每个Application
对象,我想在 CSV 文件中创建一行。
My idea is to load all the data in the constructor and then override the read method. Do I need to override all InputStream's methods? I tried googling for some examples but didn't succeed - could you eventually give me a link to one?
我的想法是在构造函数中加载所有数据,然后覆盖读取方法。我是否需要覆盖所有 InputStream 的方法?我试过在谷歌上搜索一些例子,但没有成功——你最终能给我一个链接吗?
采纳答案by maaartinus
For possibly large data you can use com.google.common.io.FileBackedOutputStreamfrom guava.
对于可能的大数据,您可以使用来自guava 的com.google.common.io.FileBackedOutputStream。
Javadoc: An OutputStream that starts buffering to a byte array, but switches to file buffering once the data reaches a configurable size.
Javadoc:一个 OutputStream,它开始缓冲到一个字节数组,但一旦数据达到可配置的大小就切换到文件缓冲。
Using out.getSupplier().getInput()
you get your InputStream.
使用out.getSupplier().getInput()
你得到你的 InputStream。
回答by Joachim Sauer
You only nead to implement the read()
method without parameters. All other methods are implemented as calls to that method. For performance reasons (and even ease of implementation) it might be easier to implement the three-argument read()
method insteadand re-implement the no-args read()
method in terms of that method.
您只需要实现不带参数的read()
方法。所有其他方法都实现为对该方法的调用。出于性能原因(甚至易于实现),实现三参数read()
方法并read()
根据该方法重新实现无参数方法可能更容易。
回答by Tony
Some very important points which I met when implementing my InputStream
.
我在实现我的InputStream
.
Override available(). As the Javadoc says:
The available method for class InputStream always returns 0. This method should be overridden by subclasses.
not overriding this method will causes that any tempt to test whether this stream is readable return false. For example, if you feed your
inputStream
to ainputStreamReader
, this reader will always return falsewhen you invokereader.ready()
.return -1 in the
read()
. The doc didn't emphasize it:If no byte is available because the end of the stream has been reached, the value -1 is returned. This method blocks until input data is available, the end of the stream is detected, or an exception is thrown.
if you choose to block
read()
when no data is available, you have to remember toreturn -1
at some situations. Not doing this may causes that anotherread(byte b[], int off, int len)
blocks for the following code in the source:for (; i < len ; i++) {// default len is a relative large number (8192 - readPosition) c = read(); if (c == -1) { break; } b[off + i] = (byte)c; }
And this causes some(if not all) high level read block, like a reader's
readLine(), read()
etc.
覆盖可用()。正如 Javadoc 所说:
InputStream 类的可用方法始终返回 0。此方法应由子类覆盖。
不覆盖此方法将导致任何测试此流是否可读的尝试都返回 false。例如,如果您将您的内容提供
inputStream
给 ainputStreamReader
,则该阅读器在您调用 时将始终返回 falsereader.ready()
。在
read()
. 文档没有强调它:如果由于已到达流末尾而没有可用字节,则返回值 -1。此方法会阻塞,直到输入数据可用、检测到流结束或抛出异常为止。
如果您选择
read()
在没有数据可用时阻止,则必须记住return -1
在某些情况下。不这样做可能会导致read(byte b[], int off, int len)
源中以下代码的另一个块:for (; i < len ; i++) {// default len is a relative large number (8192 - readPosition) c = read(); if (c == -1) { break; } b[off + i] = (byte)c; }
这会导致一些(如果不是全部)高级读取块,例如读取器
readLine(), read()
等。
回答by jtahlborn
Why do you need a custon inputstream? why not just write the csv data as you generate it to the outputstream being written to the ftp server?
为什么需要自定义输入流?为什么不直接将生成的 csv 数据写入正在写入 ftp 服务器的输出流?
回答by Sean Patrick Floyd
There's absolutely no need to create a custom InputStream
. Use ByteArrayInputStream
, something like this:
绝对没有必要创建自定义InputStream
. 使用ByteArrayInputStream
,像这样:
public static InputStream createStream(){
final String csv = createCsvFromDataBaseValues();
return new ByteArrayInputStream(csv.getBytes());
}
Especially given this quote:
特别是考虑到这句话:
My idea is to load all the data in the constructor and then override the read method.
我的想法是在构造函数中加载所有数据,然后覆盖读取方法。
If you do it like this, you gain absolutely nothing by implementing a custom InputStream
. It's pretty much equivalent to the approach I outlined above.
如果您这样做,则通过实现自定义InputStream
. 它几乎等同于我上面概述的方法。
回答by Bart van Heukelom
If the data is not too large, you could:
如果数据不是太大,你可以:
- Read it all
- Convert to CSV (text)
- Get the text bytes (via
String.getBytes(encoding)
) - But the byte array in a
ByteArrayInputStream
- 全部阅读
- 转换为 CSV(文本)
- 获取文本字节(通过
String.getBytes(encoding)
) - 但是字节数组中的
ByteArrayInputStream