Обратный массивный текстовый файл в Java

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

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

Я думал об использовании Java NIO для обработки файла как массива на диске (чтобы мне не приходилось рассматривать файл как строковый буфер в памяти). Кроме того, я думаю об использовании MapReduce, чтобы разбить файл и обработать его на разных компьютерах.

10
задан tshepang 30 June 2014 в 19:12
поделиться

3 ответа

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

Вы, вероятно, захотите определить размер блока (например, 1 КБ?) и перевернуть его в памяти перед записью в файл.

4
ответ дан 4 December 2019 в 03:16
поделиться

Это довольно сложная задача. Если вы можете убедиться, что заголовки HTTP Content-Length и Content-Type присутствуют в запросе загрузки (или в составном теле, когда это multipart / form-data, request), тогда это будет несложная работа с помощью RandomAccessFile . Длина содержимого является обязательной, чтобы RandomAccessFile знал, какой длины будет файл, и записывал символ в желаемой позиции.Кодировка символов (которая обычно присутствует как атрибут заголовка типа содержимого) является обязательной, чтобы знать, сколько байтов будет принимать во внимание символ (поскольку RandomAccessFile основан на байтах и, например, кодировка UTF-8 является переменная длина в байтах).

Вот начальный пример (оставляя в стороне очевидную обработку исключений):

package com.stackoverflow.q2725897;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.RandomAccessFile;
import java.io.Reader;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
import java.nio.charset.CharsetEncoder;

public class Test {

    public static void main(String... args) throws Exception {

        // Stub input. You need to gather it yourself from your sources.
        File file = new File("/file.txt");
        long length = file.length(); // Get it from HTTP request header using file upload API in question (Commons FileUpload?).
        String encoding = "UTF-8"; // Get it from HTTP request header using file upload API in question (Commons FileUpload?).
        InputStream content = new FileInputStream(file); // Get it from HTTP request body using file upload API in question (Commons FileUpload?).

        // Now the real job.
        Reader input = new InputStreamReader(content, encoding);
        RandomAccessFile output = new RandomAccessFile(new File("/filereversed.txt"), "rwd");
        CharsetEncoder encoder = Charset.forName(encoding).newEncoder();

        for (int data; (data = input.read()) != -1;) {
            ByteBuffer bytes = encoder.encode(CharBuffer.wrap(new char[] { (char) data }));
            length -= bytes.limit();
            output.seek(length);
            output.write(bytes.array());
        }

        // Should actually be done in finally.
        input.close();
        output.close();
    }

}

Если эти заголовки отсутствуют (особенно важна Content-length ), то вам действительно нужно сохранить их на диске. сначала до конца потока, а затем перечитайте и отмените его таким же образом с помощью RandomAccessFile .

Обновление : это будет сложнее, чем кажется. Всегда ли гарантируется одинаковая кодировка входных символов? Если да, то что бы это было? Кроме того, что бы вы хотели сделать, например, с суррогатными символами и символами новой строки? В приведенном выше примере это неправильно учитывается. Но это, по крайней мере, дает основную идею.

2
ответ дан 4 December 2019 в 03:16
поделиться

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

Будет ли 1 МБ разумным размером, учитывая тот объем, который сейчас доступен для обычного Java-приложения?

0
ответ дан 4 December 2019 в 03:16
поделиться
Другие вопросы по тегам:

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