1

我尝试使用两种方式读取文件类型。它在使用时工作ByteArrayInputStream但不是FileInputStream

FileInputStream与 一起使用URLConnection

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

ByteArrayInputStream_URLConnection

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

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

4

2 回答 2

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();
    ....

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

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

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

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

(使用 aByteArrayInputStream的开销太大。)

于 2018-10-15T14:22:20.947 回答
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不能使用文件输入流(或任何不支持标记/重置的流)。

于 2018-10-15T14:21:56.403 回答