Разница между FileInputStream и ByteArrayInputStream - PullRequest
0 голосов
/ 15 октября 2018

Я пытаюсь прочитать тип файла двумя способами.Он работает при использовании 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 для чтения типа файла?

Ответы [ 2 ]

0 голосов
/ 15 октября 2018

Метод URLConnection.guessContentTypeFromStream состоит в том, чтобы посмотреть на первые байты, так называемое волшебное печенье для идентификации файла.

Разработчики решили оставить 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")))
     );

Обратите внимание, что Files.newInputStream, как указано в javadoc, не будет поддерживать маркировку позиции для сброса.

(Использование ByteArrayInputStream будет слишком большой нагрузкой.)

0 голосов
/ 15 октября 2018

Хотя два типа входных потоков различаются во многих отношениях, причина такого поведения связана только с поддержкой пометки / сброса этих двух потоков.

Если вы проверите источник 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.

InДругими словами, guessContentTypeFromStream не может работать с потоком ввода файла (или любым потоком, который не поддерживает маркировку / сброс).

...