Java FileInputStream和ByteArrayInputStream之间的差异

Java FileInputStream和ByteArrayInputStream之间的差异,java,fileinputstream,bytearrayinputstream,Java,Fileinputstream,Bytearrayinputstream,我尝试用两种方法读取文件类型。它在使用ByteArrayInputStream而不是FileInputStream时工作 将FileInputStream与URLConnection一起使用 将ByteArrayInputStream与URLConnection一起使用 为什么结果不同? 此外,是否有提及仅使用ByteArrayInputStream读取文件类型的地方 虽然这两种输入流类型在许多方面不同,但这种行为的原因仅与这两种流的标记/重置支持有关 如果检查URLConnection.gue

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

将FileInputStream与URLConnection一起使用

将ByteArrayInputStream与URLConnection一起使用

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

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

如果检查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无法处理文件输入流或任何不支持标记/重置的流。

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

如果检查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无法处理文件输入流或任何不支持标记/重置的流。

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

实现者选择让流保持不变的状态,因此继续读取将从开始处重新开始

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();
    ....
为此,它会进行重置:从实际开始重置到先前标记的流位置

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

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

实现者选择让流保持不变的状态,因此继续读取将从开始处重新开始

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();
    ....
为此,它会进行重置:从实际开始重置到先前标记的流位置

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

您使用的是什么Java版本?我使用的是Java 1.8.0\u 181您的第一个代码段没有在Java 8上编译。。。构造函数FileInputStreamPath未定义请检查此项,以便获得准确的idea@ernest_k:我现在已经更正了代码段您使用的是什么Java版本?我使用的是Java 1.8.0\u 181您的第一个代码段没有在Java 8上编译。。。构造函数FileInputStreamPath未定义请检查此项,以便获得准确的idea@ernest_k:我现在已经更正了代码段