我尝试使用两种方式读取文件类型。在使用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
来读取文件类型的地方?
答案 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
不能与文件输入流(或任何不支持标记/重置的流)一起使用。