FileInputStream和ByteArrayInputStream之间的区别

时间:2018-10-15 13:50:34

标签: java fileinputstream bytearrayinputstream

我尝试使用两种方式读取文件类型。在使用ByteArrayInputStream而不是FileInputStream

时可以正常工作

FileInputStreamURLConnection一起使用,

String fileType = URLConnection
  .guessContentTypeFromStream(
    new FileInputStream(new File("C:\\image.jpeg"))
   ); //fileType = null

ByteArrayInputStreamURLConnection一起使用

String fileType = URLConnection
.guessContentTypeFromStream(
  new ByteArrayInputStream(Files.readAllBytes(new File("C:\\image.jpeg").toPath()))
 ); //fileType = image/jpeg

为什么结果不同? 另外,是否有提到仅使用ByteArrayInputStream来读取文件类型的地方?

2 个答案:

答案 0 :(得分:3)

URLConnection.guessContentTypeFromStream的技术是查看第一个字节,即所谓的魔术cookie 来识别文件。

实现者选择将Stream保持不变,因此继续阅读将从头开始(再次)。

为此,它将对先前标记的流位置(实际上是开始位置)进行reset():

static public String guessContentTypeFromStream(InputStream is)
                    throws IOException {
    // If we can't read ahead safely, just give up on guessing
    if (!is.markSupported())
        return null;

    is.mark(16);
    int c1 = is.read();
    int c2 = is.read();
    int c3 = is.read();
    ...
    int c14 = is.read();
    int c15 = is.read();
    int c16 = is.read();
    is.reset();
    ....

对于顺序FileInputStream markSupported()返回默认值false

一个人可以通过用FileInputStream包裹BufferedInputStream来解决它,无论如何都会更快。

String fileType = URLConnection
    .guessContentTypeFromStream(
        new BufferedInputStream(Files.newInputStream(Paths.get("C:\\image.jpeg")))
     );

请注意,javadoc中所述的Files.newInputStream不支持标记重置位置。

(使用ByteArrayInputStream会产生很大的开销。)

答案 1 :(得分:1)

尽管两种输入流类型在很多方面都不同,但是这种行为的原因仅与这两种流的标记/重置支持有关。

如果您查看URLConnection.guessContentTypeFromStream的来源,则会注意到:

// If we can't read ahead safely, just give up on guessing
if (!is.markSupported())
    return null;

然后ByteArrayInputStream覆盖markSupported以返回true,而FileInputStream继承了默认的InputStream.markSupported方法,该方法返回了false

换句话说,guessContentTypeFromStream不能与文件输入流(或任何不支持标记/重置的流)一起使用。