java - FileInputStream 和 ByteArrayInputStream 的区别

标签 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 来读取文件类型?

最佳答案

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 开销太大。)

关于java - FileInputStream 和 ByteArrayInputStream 的区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52818282/

相关文章:

java - 如何将 Java 对象转换为 C++ 对象?

Java 向文件写入字节和从文件读取字节

java - 输入流的skip方法总是返回0

java - 从文本中读取 Java 中的数据

java - 使用 UTF-8 编码导出 csv

java - Hibernate JPA 联合继承

java - TomCat:使用类路径打开文件

android - LibGDX 从 base64 PNG ByteArrayInputStream 创建纹理

java - HttpURLConnection Post 请求,使用来自 javax.rs.ws.Response 对象的响应进行响应

java - Liferay Spring 集成