Не успел я написать утилиту для работы с архивными файлами, как пришла пора отправить её на заслуженный отдых.
Когда писал парсер JSON-файла, вспомнил, что есть библиотека java.uti.zip и когда-то давно я с её помощью читал заархивированные в zip-формате файлы, без предварительного их разархивирования. Посмотрел в документацию и нашёл, что ровно то же самое можно делать и с gzip-файлами.
Отлично. Одним рефакторингом мы избавляемся:
- от утилиты,
- от необходимости придумывать, из какого класса её вызывать,
- от необходимости её тестировать и сопровождать,
- от распакованных файлов, которые будут занимать лишнее место на диске.
Теперь наш парсер будет читать файлы из архивов:
public <T> void parse(String path, Function<? super String, T> create, Consumer<T> save) { log.info("Start parsing file: {}", path); try (FileInputStream fis = new FileInputStream(path); GZIPInputStream gzis = new GZIPInputStream(fis); InputStreamReader isr = new InputStreamReader(gzis, StandardCharsets.UTF_8); BufferedReader br = new BufferedReader(isr)) { br.lines() .parallel() .map(create) .forEach(save); log.info("Finish parsing file: {}", path); } catch (Exception e) { log.error("Error parsing file: {}", path, e); } }
На вход метод получает путь к файлу и две функции: функцию, которая будет преобразовывать строки из JSON-файла в нашу модель Review и функцию, которая будет сохранять распарсенные данные в кеш.
Как это работает, можно посмотреть в тесте:
@Test public void parseFile() { Gson gson = new Gson(); CacheRepository<String, Review> reviewRepository = new ReviewTestRepository(); String path = Objects.requireNonNull( getClass().getClassLoader().getResource("reviews_Electronics_5_short.json.gz") ).getPath(); FileParser parser = new FileParser(); parser.parse(path, line -> gson.fromJson(line, Review.class), reviewRepository::save); assertEquals(26, reviewRepository.count()); }
Комментариев нет:
Отправить комментарий