我有一个Java类,通过InputStream 读取数据
byte[] b = null;
try {
b = new byte[in.available()];
in.read(b);
} catch (IOException e) {
e.printStackTrace();
}
当我从IDE(Eclipse)运行我的应用程序时,它可以完美地工作。
但是,当我导出项目并将其打包在JAR中时,read命令不会读取所有数据。我该怎么修?
这个问题主要发生在InputStream是一个文件(约10kb)时。
谢谢!
通常我更喜欢在从输入流读取时使用固定大小的缓冲区。正如evivone所指出的,使用available()作为缓冲区大小可能不是一个好主意,因为例如,如果您正在读取远程资源,那么您可能事先不知道可用的字节数。您可以阅读InputStream的javadoc来获得更多的见解。
以下是我通常用于读取输入流的代码片段:
byte[] buffer = new byte[BUFFER_SIZE];
int bytesRead = 0;
while ((bytesRead = in.read(buffer)) >= 0){
for (int i = 0; i < bytesRead; i++){
//Do whatever you need with the bytes here
}
}
我在这里使用的read()版本将尽可能多地填充给定的缓冲区返回实际读取的字节数。这意味着您的缓冲区可能包含尾随垃圾数据,因此只使用bytesRead
以下的字节非常重要。
请注意行(bytesRead = in.read(buffer)) >= 0
,InputStream规范中没有任何内容表明read()不能读取0字节当read()读取0字节时,您可能需要根据您的情况处理特殊情况。对于本地文件,我从未经历过这样的情况;然而,在读取远程资源时,我实际上看到read()不断读取0个字节,导致上面的代码进入无限循环。我通过计算读取0字节的次数来解决无限循环问题,当计数器超过阈值时,我将抛出异常。你可能不会遇到这个问题,但请记住:)
出于性能原因,我可能不会为每次读取创建新的字节数组。
read()
将返回-1
。还有一个读取版本,它采用一个数组,这允许您进行分块读取。它在InputStream结束时返回实际读取的字节数或-1
。将其与ByteArrayOutputStream等动态缓冲区相结合,可以获得以下内容:
InputStream in = ...
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
int read;
byte[] input = new byte[4096];
while ( -1 != ( read = in.read( input ) ) ) {
buffer.write( input, 0, read );
}
input = buffer.toByteArray()
这大大减少了您必须调用的方法的数量,并允许ByteArrayOutputStream更快地增加其内部缓冲区。
File file = new File("/path/to/file");
try {
InputStream is = new FileInputStream(file);
byte[] bytes = IOUtils.toByteArray(is);
System.out.println("Byte array size: " + bytes.length);
} catch (IOException e) {
e.printStackTrace();
}
以下是下载文件(*.Png,*.Jpeg,*.Gif,…)并将其写入表示HttpServlet响应的BufferedOutputStream的代码片段。
BufferedInputStream inputStream = bo.getBufferedInputStream(imageFile);
try {
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
int bytesRead = 0;
byte[] input = new byte[DefaultBufferSizeIndicator.getDefaultBufferSize()];
while (-1 != (bytesRead = inputStream.read(input))) {
buffer.write(input, 0, bytesRead);
}
input = buffer.toByteArray();
response.reset();
response.setBufferSize(DefaultBufferSizeIndicator.getDefaultBufferSize());
response.setContentType(mimeType);
// Here's the secret. Content-Length should equal the number of bytes read.
response.setHeader("Content-Length", String.valueOf(buffer.size()));
response.setHeader("Content-Disposition", "inline; filename="" + imageFile.getName() + """);
BufferedOutputStream outputStream = new BufferedOutputStream(response.getOutputStream(), DefaultBufferSizeIndicator.getDefaultBufferSize());
try {
outputStream.write(input, 0, buffer.size());
} finally {
ImageBO.close(outputStream);
}
} finally {
ImageBO.close(inputStream);
}
希望这能有所帮助。