Как кэшировать InputStream для совместного использования

@Voicu имеет правильное решение и спасибо за подсказку.

Для будущих посетителей: в новом HttpClient (Angular 4.3+) объектом ответа по умолчанию является JSON, поэтому вам больше не нужно выполнять response.json (). Data. Просто используйте ответ напрямую.

25
задан Azder 29 May 2009 в 15:04
поделиться

5 ответов

вы можете украсить InputStream, передаваемый в POIFSFileSystem , версией, которая при вызове close () отвечает с помощью reset ():

class ResetOnCloseInputStream extends InputStream {

    private final InputStream decorated;

    public ResetOnCloseInputStream(InputStream anInputStream) {
        if (!anInputStream.markSupported()) {
            throw new IllegalArgumentException("marking not supported");
        }

        anInputStream.mark( 1 << 24); // magic constant: BEWARE
        decorated = anInputStream;
    }

    @Override
    public void close() throws IOException {
        decorated.reset();
    }

    @Override
    public int read() throws IOException {
        return decorated.read();
    }
}

testcase

static void closeAfterInputStreamIsConsumed(InputStream is)
        throws IOException {
    int r;

    while ((r = is.read()) != -1) {
        System.out.println(r);
    }

    is.close();
    System.out.println("=========");

}

public static void main(String[] args) throws IOException {
    InputStream is = new ByteArrayInputStream("sample".getBytes());
    ResetOnCloseInputStream decoratedIs = new ResetOnCloseInputStream(is);
    closeAfterInputStreamIsConsumed(decoratedIs);
    closeAfterInputStreamIsConsumed(decoratedIs);
    closeAfterInputStreamIsConsumed(is);
}

EDIT 2

вы можете прочитать весь файл в байтах [] (режим slurp), а затем передать его в ByteArrayInputStream

18
ответ дан 28 November 2019 в 20:49
поделиться

Что именно вы имеете в виду под "кешем"? Вы хотите, чтобы другая система POIFSFileSystem запускалась в начале потока? Если это так, то нет никакого смысла кэшировать что-либо в вашем Java-коде; это будет сделано ОС, просто откройте новый поток.

Или вы хотите продолжить чтение с точки, где остановилась первая система POIFSFileSystem? Это не кеширование, и это очень сложно сделать. Единственный способ, который я могу придумать, если вы не можете избежать закрытия потока, - это написать тонкую оболочку, которая подсчитывает, сколько байтов было прочитано, а затем открывает новый поток и пропускает это количество байтов. Но это может потерпеть неудачу, если POIFSFileSystem внутренне использует что-то вроде BufferedInputStream.

1
ответ дан 28 November 2019 в 20:49
поделиться

Если файл не такой большой, считайте его в массив byte [] и присвойте POI ByteArrayInputStream , созданный из этого массива.

Если файл большой, тогда вам не стоит беспокоиться, так как ОС сделает кеширование за вас как можно лучше.

[РЕДАКТИРОВАТЬ] Используйте Apache commons-io для эффективного считывания файла в массив байтов. Не используйте int read () , так как он читает файл побайтно, что на очень медленно!

Если вы хотите сделать это самостоятельно, используйте File , чтобы получить длину, создать массив и цикл, который читает байты из файла. Вы должны выполнить цикл, так как read (byte [], int offset, int len) может читать меньше len байтов (и обычно так и есть).

1
ответ дан 28 November 2019 в 20:49
поделиться

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

Когда я впервые просматриваю список, я ищу вещи, с которыми у меня большой опыт. Это вещи, в которых, основываясь на моем предыдущем опыте, я могу очень точно оценить время, которое потребуется.

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

В последний раз, когда я просматриваю список, я предполагаю, что каждая задача займет у одного программиста один день работы завершить. Иногда кто-то может сделать целую группу за один день. Замечательно. Но иногда в одной задаче есть всевозможные скрытые неприятности, которых никто никогда не ожидал, и кому-то понадобится неделя, чтобы разобраться в ней. В конце концов, все уравняется.

Это не даст вам очень точной оценки. Вы не можете иметь точную оценку. Вы никогда не сможете точно предсказать, в какой день вы что-то закончите. Однако это даст вам очень хорошую консервативную и точную оценку. Точность и точность - разные вещи.

это даст вам очень хорошую консервативную и точную оценку. Точность и точность - разные вещи.

это даст вам очень хорошую консервативную и точную оценку. Точность и точность - разные вещи.

  • вы даже можете вызвать release () из finalize , чтобы убедиться, что временный файл является освобожденным, на случай, если вы забудете вызвать release () (в большинстве случаев вам следует избегать использования finalize ], всегда вызывайте метод для освобождения ресурсов объекта). см. Зачем вообще реализовывать finalize ()?
  • 1
    ответ дан 28 November 2019 в 20:49
    поделиться

    Попробуйте BufferedInputStream, который добавляет функции отметки и сброса в другой входной поток и просто переопределяет его метод закрытия:

    public class UnclosableBufferedInputStream extends BufferedInputStream {
    
        public UnclosableBufferedInputStream(InputStream in) {
            super(in);
            super.mark(Integer.MAX_VALUE);
        }
    
        @Override
        public void close() throws IOException {
            super.reset();
        }
    }
    

    Итак:

    UnclosableBufferedInputStream  bis = new UnclosableBufferedInputStream (inputStream);
    

    и используйте bis везде, где раньше использовался inputStream.

    20
    ответ дан 28 November 2019 в 20:49
    поделиться
    Другие вопросы по тегам:

    Похожие вопросы: