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是一个文件(约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)) >= 0InputStream规范中没有任何内容表明read()不能读取0字节当read()读取0字节时,您可能需要根据您的情况处理特殊情况。对于本地文件,我从未经历过这样的情况;然而,在读取远程资源时,我实际上看到read()不断读取0个字节,导致上面的代码进入无限循环。我通过计算读取0字节的次数来解决无限循环问题,当计数器超过阈值时,我将抛出异常。你可能不会遇到这个问题,但请记住:)

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

InputStream耗尽时,

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);
}

希望这能有所帮助。

相关内容

  • 没有找到相关文章

最新更新