Android - эффективный способ извлечь данные конкретной строки из 1 440 000 строк текстового файла

1

У меня есть данные ландшафта, которые содержат отметки, как показано ниже

И каждый файл состоит из 1440 000 строк

.
.
.
183
192
127
.
.
.

как я могу получить доступ к конкретным строкам непосредственно из файла без расточительной загрузки полной памяти? (в Android)

Теги:
file
random-access

5 ответов

1
Лучший ответ

Я считаю, что ваш лучший вариант - преобразовать ваш текстовый файл в базу данных SQLite.

0

Вероятно, вы захотите использовать BufferedInputStream: http://developer.android.com/reference/java/io/BufferedInputStream.html

0

Если вы можете изменить файл в двоичном формате, вы можете напрямую искать нужную позицию и читать нужное значение. Если нет, вам, вероятно, придется читать его по очереди и возвращать нужную строку (при условии, что вы не можете вычислить позицию байта, так как строки могут иметь разную длину).

Поиграв слишком долго, я получил это (это было непроверено):

File f = new File ("yourfile.txt");
HashMap <Integer, String> result = readLines(f, 1, 5, 255);
String line5 = result.get(5); // or null if the file had no line 5

private static HashMap <Integer, String> readLines(File f, int... lines) {
    HashMap<Integer, String> result = new HashMap<Integer, String>();
    HashSet<Integer> linesSet = new HashSet<Integer>();
    for (int line : lines) {
        linesSet.add(Integer.valueOf(line));
    }
    BufferedReader br = null;
    try {
        br = new BufferedReader(new InputStreamReader(new FileInputStream(f), "UTF-8"));
        int line = 1; // starting at line 1
        String currentLine = null;
        while ((currentLine = br.readLine()) != null) {
            Integer i = Integer.valueOf(line);
            if (linesSet.contains(i))
                result.put(i, currentLine);
            line++;
        }
    } catch (FileNotFoundException e) {
        // file not found
    } catch (UnsupportedEncodingException e) {
        // bad encoding specified
    } catch (IOException e) {
        // could not read
    } finally {
        if (br != null) {
            try {
                br.close();
            } catch (IOException e) {
                // ignore.
            }
        }
    }
    return result;
}
  • 1
    Проблема не в том, что это двоичный формат, а в том, что это формат записи с фиксированной длиной .
  • 0
    @ChrisStratton Вы правы, бинарный не подразумевает записи фиксированной длины. На самом деле я имел в виду следующее: простой поток, например, int , гарантированно имеет фиксированную длину, довольно легко (возможно, -endianess) для чтения / записи, потенциально меньше по размеру («123 \ n» уже 4 байта) и легче чтобы вычислить желаемую позицию, чем текстовое представление, где вы можете иметь \r\n , заголовки спецификации и другие подводные камни.
Показать ещё 1 комментарий
0

Я думаю, вы можете использовать java.nio.FileChannel.read (буферы, начало, номер).

start означает начальное смещение, а число - количество прочитанных байтов.

0

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

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

Если нет способа идентифицировать запись, отличную от подсчета с самого начала, вам придется это сделать. В идеале вы сделали бы это таким образом, чтобы не трястись о создании объектов во время сканирования, а затем, когда сборщик мусора очистил их...

Ещё вопросы

Сообщество Overcoder
Наверх
Меню