FileInputStream 和 ByteArrayInputStream 的区别
Difference between FileInputStream and ByteArrayInputStream
我尝试使用两种方式读取文件类型。它在使用 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
来读取文件类型?
虽然这两种输入流类型在很多方面都不同,但这种行为的原因仅与这两种流的 mark/reset 支持有关。
如果您查看 URLConnection.guessContentTypeFromStream
的来源,您会注意到:
// If we can't read ahead safely, just give up on guessing
if (!is.markSupported())
return null;
并且 ByteArrayInputStream
将 markSupported
覆盖为 return true
而 FileInputStream
继承默认的 InputStream.markSupported
方法 returns false
.
换句话说,guessContentTypeFromStream
无法使用文件输入流(或任何不支持 mark/reset 的流)。
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()
returns 默认 false
.
可以通过用 BufferedInputStream
包裹 FileInputStream
来解决它,无论如何这样会更快。
String fileType = URLConnection
.guessContentTypeFromStream(
new BufferedInputStream(Files.newInputStream(Paths.get("C:\image.jpeg")))
);
请注意,javadoc 中所述的 Files.newInputStream
将不支持标记要重置的位置。
(使用ByteArrayInputStream
开销太大。)
我尝试使用两种方式读取文件类型。它在使用 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
来读取文件类型?
虽然这两种输入流类型在很多方面都不同,但这种行为的原因仅与这两种流的 mark/reset 支持有关。
如果您查看 URLConnection.guessContentTypeFromStream
的来源,您会注意到:
// If we can't read ahead safely, just give up on guessing
if (!is.markSupported())
return null;
并且 ByteArrayInputStream
将 markSupported
覆盖为 return true
而 FileInputStream
继承默认的 InputStream.markSupported
方法 returns false
.
换句话说,guessContentTypeFromStream
无法使用文件输入流(或任何不支持 mark/reset 的流)。
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()
returns 默认 false
.
可以通过用 BufferedInputStream
包裹 FileInputStream
来解决它,无论如何这样会更快。
String fileType = URLConnection
.guessContentTypeFromStream(
new BufferedInputStream(Files.newInputStream(Paths.get("C:\image.jpeg")))
);
请注意,javadoc 中所述的 Files.newInputStream
将不支持标记要重置的位置。
(使用ByteArrayInputStream
开销太大。)