Хороший дизайн: как передать InputStreams в качестве аргумента?
У меня есть большой файл, в котором я открываю FileInputStream. Этот файл содержит несколько файлов, каждый из которых имеет смещение от начала и размер. Кроме того, у меня есть парсер, который должен оценивать такой файл.
File file = ...; // the big file
long offset = 1734; // a contained file's offset
long size = 256; // a contained file's size
FileInputStream fis = new FileInputStream(file );
fis.skip(offset);
parse(fis, size);
public void parse(InputStream is, long size) {
// parse stream data and insure we don't read more than size bytes
is.close();
}
Я чувствую, что это не хорошая практика. Есть ли лучший способ сделать это, возможно, с помощью буферизации?
кроме того, я чувствую, что метод skip() сильно замедляет процесс чтения.
5 ответов
похоже, что вам действительно нужен своего рода" частичный " входной поток - немного похожий на ZipInputStream, где у вас есть поток в потоке.
вы можете написать это сами, проксируя все методы InputStream к исходному входному потоку, делая соответствующие корректировки для смещения и проверки чтения после конца подфайла.
Это то, о чем ты говоришь?
во-первых,FileInputStream.skip () имеет ошибку что может заставить файл под пропустить за маркер EOF файла, поэтому будьте осторожны с этим.
Я лично обнаружил, что работа с Input / OutputStreams является болью по сравнению с использованием FileReader и FileWriter, и вы показываете основную проблему, которую я имею с ними: необходимость закрыть потоки после использования. Одна из проблем заключается в том, что вы никогда не можете быть уверены, правильно ли вы закрыли все ресурсы, если вы не сделаете код немного слишком осторожен, как это:
public void parse(File in, long size) {
try {
FileInputStream fis = new FileInputStream(in);
// do file content handling here
} finally {
fis.close();
}
// do parsing here
}
Это конечно плохо в том смысле, что это приведет к созданию новых объектов, все время, что может в конечном итоге едят много ресурсов. Хорошей стороной этого, конечно, является то, что поток будет закрыт, даже если код обработки файлов выдает исключение.
это звучит как типичная вложенная проблема с файлом "zip".
общий способ справиться с этим-фактически иметь отдельный экземпляр InputStream для каждого вложенного логического потока. Они будут выполнять необходимые операции над базовым потоком phsycial, а буферизация может быть как на базовом потоке, так и на логическом потоке, в зависимости от того, что подходит лучше всего. Это означает, что логический поток инкапсулирует всю информацию о размещении в базовом поток.
можно например есть метод фабрики, который бы подпись такой:
List<InputStream> getStreams(File inputFile)
вы можете сделать то же самое с OutputStreams.
есть некоторые детали, но это может быть достаточно для вас ?
В общем, код, открывающий файл, должен закрыть файл -- функция parse () не должна закрывать входной поток, так как для нее крайне самонадеянно предположить, что остальная часть программы не захочет продолжать чтение других файлов, содержащихся в большом.
вы должны решить, должен ли интерфейс для синтаксического анализа() быть просто потоком и длиной (с функцией, способной предположить, что файл правильно расположен) или интерфейс должен включать смещение (поэтому функция сначала позиционирует, а затем считывает). Обе конструкции возможны. Я был бы склонен позволить parse () выполнять позиционирование, но это не четкое решение.
вы можете использовать класс-оболочку в RandomAccessFile-try этой
вы также можете попробовать обернуть это в BufferedInputStream и посмотреть, улучшится ли производительность.