Java InputStream读取问题

我有一个Java类,我通过InputStream读取数据

byte[] b = null; try { b = new byte[in.available()]; in.read(b); } catch (IOException e) { e.printStackTrace(); } 

当我从IDE(Eclipse)运行我的应用程序时,它非常有效。

但是当我导出我的项目并将其打包在JAR中时,read命令不会读取所有数据。 我该怎么办呢?

当InputStream是File(~10kb)时,通常会发生此问题。

谢谢!

通常我更喜欢在从输入流中读取时使用固定大小的缓冲区。 正如evilone指出的那样,使用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)) >= 0InputStream规范中没有任何内容表明read()不能读取0个字节。 当read()根据您的情况读取0字节作为特殊情况时,您可能需要处理这种情况。 对于本地文件,我从未遇到过这种情况; 但是,当读取远程资源时,我实际上看到read()不断读取0个字节,导致上面的代码进入无限循环。 我通过计算读取0字节的次数来解决无限循环问题,当计数器超过阈值时,我将抛出exception。 你可能不会遇到这个问题,但请记住这一点:)

出于性能原因,我可能会远离为每次读取创建新的字节数组。

当InputStream耗尽时, read()将返回-1 。 还有一个带有数组的read版本,这允许你进行分块读取。 它返回实际读取的字节数,或者在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,…)并将其写入表示HttpServletResponse的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); } 

希望这可以帮助。