I try to read file type using two ways. It is working while using ByteArrayInputStream
but not FileInputStream
Using FileInputStream
with URLConnection
,
String fileType = URLConnection
.guessContentTypeFromStream(
new FileInputStream(new File("C:\\image.jpeg"))
); //fileType = null
Using ByteArrayInputStream
with URLConnection
String fileType = URLConnection
.guessContentTypeFromStream(
new ByteArrayInputStream(Files.readAllBytes(new File("C:\\image.jpeg").toPath()))
); //fileType = image/jpeg
Why is the difference in the result ?
Also, is there anywhere mentioned to use only ByteArrayInputStream
to read the file type?
The technique of URLConnection.guessContentTypeFromStream
is to look at the first bytes, the so called magic cookie to identify the file.
The implementors chose to leave the Stream in an unaltered state, so continue reading will start (again) with at the beginning.
For that it does a reset():
to the previous marked stream position (actual the beginning).
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();
....
For a sequential FileInputStream markSupported()
returns the default false
.
One can solve it by wrapping the FileInputStream
by a BufferedInputStream
, which would be faster anyhow.
String fileType = URLConnection
.guessContentTypeFromStream(
new BufferedInputStream(Files.newInputStream(Paths.get("C:\\image.jpeg")))
);
Note that Files.newInputStream
as stated in the javadoc will not support marking a position for reset.
(Using a ByteArrayInputStream
would be a too large overhead.)