Как бы вы проанализировали файл, слишком большой для памяти?

Недавно рекрутер задал мне этот вопрос на живом собеседовании по программированию. Я не был уверен, как это сделать с помощью кода.

Я подумал о том, чтобы разбить файл на несколько файлов, а затем прочитать эти фрагменты через несколько потоков.

Но я не смог реализовать то же самое.

Любая помощь с реализацией или каким-либо другим подходом будет оценена по достоинству!

Это слишком широко - если бы мне задали этот вопрос в интервью, я бы спросил "что за файл, какой анализ?"

RealSkeptic 29.05.2019 18:41

такие вопросы на собеседовании абсурдны.

java-addict301 29.05.2019 18:43
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
2
473
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

В зависимости от типа/содержимого файла вы можете загрузить его в таблицу базы данных и выполнить анализ с помощью запросов к нему (например, если это был файл .csv).

Это широкая тема, но обычно такие проблемы решаются с помощью буфера.

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

Например, если вы хотите отсортировать некоторые данные, которые слишком велики для памяти, мы используем метод, известный как внешняя сортировка.

В основном реляционная база данных использует этот метод внешней сортировки для сортировки данных, когда мы используем предложение Сортировать по в нашем запросе. Для более подробной информации об этом есть замечательная лекция, ссылка на видео которой вставлена ​​ниже.

https://thewikihow.com/video_YjFI9CJy6x0&t=3506s

Я надеюсь, что это поможет вам в понимании.

Я ищу код Java для реализации этого.

testMyUnderstanding 29.05.2019 19:07

вы можете обратиться к stackoverflow.com/questions/8402106/…

Avik Kesari 29.05.2019 20:08
Ответ принят как подходящий

Я бы ответил: «Это зависит». В сценарии интервью они, вероятно, намеренно задают вам расплывчатый вопрос, чтобы увидеть, что вы с ним сделаете. Как отмечают другие, поиск информации о файле и о том, какую информацию вы хотите из него получить, является ключевым, и возможные решения могут сильно различаться в зависимости от этих факторов.

Например, если файл на самом деле CSV, и вы хотите выполнить потенциально сложный анализ данных (сортировка, подсчет, агрегирование и т. д.), то размещение его в таблице реляционной базы данных, скажем, H2, может быть неплохой идеей. . Если файл содержит больше текста в произвольной форме, вы можете проиндексировать его с помощью Lucene или поместить его в индекс ElasticSearch, а затем просмотреть его с помощью Kibana.

Однако ни одно из этих решений не анализирует файл «с кодом» и было бы совершенно неэффективным, если бы файл был, скажем, видеоклипом размером 100 ГБ. Поскольку они спрашивают, как вы будете анализировать файл «с кодом», я ожидаю, что они попытаются выяснить, знаете ли вы, как выполнять байт-ориентированный ввод-вывод (например, Java InputStream) по сравнению с символьно-ориентированным (например, Reader) и /или как прочитать потенциально большой файл с использованием буфера (т.е. без загрузки всего файла в память).

Вот простой пример кода...

import java.io.*;

public class StreamFile {
    /** Stream through a file using a buffer. */
    final static int BUFSIZE = 1024; // Use a 1K buffer.

    public static void main(String[] args) throws Exception {
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(new File(args[0])));
        long totalBytes = 0;
        byte[] buf = new byte[BUFSIZE];
        while (bis.available() > 0) {
            totalBytes += bis.read(buf, 0, BUFSIZE); // Do something here with the data in buf.
            System.out.println(totalBytes); // Show progress.
        }
        System.out.println("Read " + totalBytes + " bytes");
        bis.close();
    }
}

Точно. Я думаю, что вы попали в точку с I expect they're trying to see if you know how to do byte-oriented I/O (e.g. Java InputStream) vs character-oriented (e.g. Reader) and/or how to read through a potentially large file using a buffer (i.e. without loading the whole file into memory). Я имею в виду, как я могу это сделать? Если, по крайней мере, вы можете указать мне точное ключевое слово, чтобы я мог гуглить или что-то в этом роде? Какой буфер? я был бы очень благодарен

testMyUnderstanding 29.05.2019 19:55

Я добавил ссылку на пример кода. Я не проводил исчерпывающий поиск, чтобы найти лучший, но общая идея состоит в том, чтобы либо читать файл по одному байту за раз (до EOF), либо до определенного количества байтов в байтовый буфер (до EOF) . Вы можете использовать Reader, если знаете, что файл состоит из символов, в противном случае вам нужно использовать Steams. Учебник по Java с сайта Oracle очень хорош. В противном случае найдите что-то вроде «файл потока буфера java» и т. д.

roninjoe 29.05.2019 20:04

Я думаю, что эта статья прекрасно резюмирует это, несовместимо с тем, что вы предложили. Хотелось бы получить ваши отзывы об этой короткой, но четкой статье. baeldung.com/java-read-lines-large-file

testMyUnderstanding 29.05.2019 20:18

Конечно, статья довольно хорошая, но у нее есть пара вопросов для ваших целей. Во-первых, он демонстрирует использование сторонних пакетов (например, Guava и Apache Commons), что может быть нормально, если вы уже используете эти пакеты, но может не помочь, если вы пытаетесь изучить основную концепцию (например, как прочитать файл с использованием буфера). Кроме того, он привносит в картину управление зависимостями и потенциально временное управление зависимостями (т. е. как я могу получить эти банки и, возможно, любые банки, от которых зависят эти банки, в мой ПУТЬ К КЛАССУ). Возможно, лучше придерживаться простого JDK.

roninjoe 29.05.2019 20:42

Во-вторых (не хватило места в комментарии;), простой пример Java предполагает, что файл содержит символы (а не байты, которые могут или не могут отображаться в символы), а также что одна строка помещается в память (т.е. файл может быть 100 ГБ и не содержат новых строк).

roninjoe 29.05.2019 20:45

Да, ты прав. Это имеет смысл. Я думаю, что мне придется копать немного больше, но я получил основную идею. Необходимо использовать Input streams для чтения данных из буфера, если файл не содержит символов, и чтения побайтно, а не для загрузки всего файла в память. В противном случае используйте Buffered Reader , если он содержит символы. Спасибо за помощь. Очень ценю !

testMyUnderstanding 29.05.2019 20:56

Я попробовал пример кода для чтения файла размером 10 ГБ. Если я использую BufferedReader, я получаю исключение из памяти, но при использовании BufferedInputStream кажется, что он работает отлично. Как вы сказали, я читал еще, что если файл содержит обычный текст, мы должны использовать BufferedReader. Но, похоже, это не работает. Есть идеи ?

testMyUnderstanding 29.05.2019 22:30

Я заменил ссылку на пример небольшой программой, которая, я надеюсь, кратко демонстрирует потоковую передачу. Это должно иметь возможность передавать через действительно большой файл до переполнения «totalBytes». Трудно сказать, почему у вас не хватает памяти при использовании Reader, не видя кода. Одной из распространенных ошибок может быть использование readLine() для двоичного файла, в котором нет строк, что может привести к считыванию всего файла в память.

roninjoe 31.05.2019 20:37

Другие вопросы по теме