【问题标题】:Difference between FileInputStream and ByteArrayInputStreamFileInputStream 和 ByteArrayInputStream 的区别
【发布时间】:2018-10-15 13:50:33
【问题描述】:

我尝试使用两种方式读取文件类型。它在使用 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 来读取文件类型?

【问题讨论】:

  • 您使用的是什么 Java 版本?
  • 我使用的是java 1.8.0_181
  • 您的第一个代码 sn-p 未在 Java 8 上编译...The constructor FileInputStream(Path) is undefined
  • 看看这个link,这样可以得到确切的想法
  • @ernest_k:我现在已经更正了 sn-p

标签: java fileinputstream bytearrayinputstream


【解决方案1】:

URLConnection.guessContentTypeFromStream 的技术是查看第一个字节,即所谓的 magic 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

可以通过用BufferedInputStream 包装FileInputStream 来解决它,无论如何这会更快。

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

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

(使用ByteArrayInputStream 开销太大。)

【讨论】:

    【解决方案2】:

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

    如果您查看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 不能用于文件输入流(或任何不支持标记/重置的流)。

    【讨论】:

      猜你喜欢
      • 2015-01-09
      • 2012-12-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-09-06
      • 1970-01-01
      • 1970-01-01
      • 2013-07-06
      相关资源
      最近更新 更多