2016-07-12 3 views
-2

У меня проблема с чтением файла большего размера в JAVA. Файл, который я использовал для чтения имеет размер 750 Мб так, когда я использовал для чтения файла с помощью BufferedReader, сканера и LineNumberReader все не в состоянии читать и приводит к OutOfMemoryError.Как читать указанное количество строк в текстовом файле?

Есть ли какой-либо простой способ прочитать этот файл большего размера? Есть ли способ, пропуская некоторое количество строк и прочитав конкретную строку после пропусков строк.

код, который я использовал для чтения файла:

FileInputStream inputStream = null; 
Scanner sc = null; 
try 
{ 
    inputStream = new FileInputStream(path); 
    sc = new Scanner(inputStream, "UTF-8"); 
    while (sc.hasNextLine()) 
    { 
      String line = sc.nextLine(); 
    }  
    if (sc.ioException() != null) 
    { 
     throw sc.ioException(); 
    } 
} 
finally 
{ 
    inputStream.close(); 
    sc.close(); 
} 

Например:

Если я думаю, что читать несколько строк из 1001 до 2000, как я могу читать те отдельные строки из этого файла большего размера.

Заранее спасибо.

+0

Просто используйте ['RandomAccessFile'] (https://docs.oracle.com/javase/7/docs/api/java/io/RandomAccessFile.html) –

+0

При чтении вы продолжаете обновлять переменную' int line' что вы увеличиваете после (или до, в зависимости от того, хотите ли вы цифры на основе 0 или 1), читая строку. Теперь, когда эта переменная находится в диапазоне от 1001 до 2000, вы делаете что-то с линией. Иначе вы его отбросите. –

+0

Как вы хотите обработать файл? Построчно? В блоках с фиксированным или переменным размером? Возможно, вы захотите прочитать файл за один проход, но выполните обработку между чтением записей и не сохраните их все в памяти. –

ответ

0

Проблема заключается в том, чтобы знать, где заканчивается линия. Это просто невозможно, не заглядывая в этот файл. Нет такой функции, которая позволяет вам читать на номер определенной строки. Если вы задали вопрос о определенной позиции байта, ответ будет java.io.RandomAccessFile.

Так у вас есть два варианта:

  1. Каждый раз, когда вы хотите прочитать на определенное количество линий, создать новый BufferedReader (и основные потоки) и пропустить все строки, пока вы не достигли своего желающий. Как следует из названия, BufferedReader буферизует входной источник в кусках из 4096 символов - 8192 байта. Этого должно быть достаточно для большинства целей.
  2. Если первый вариант слишком медленный для вашей цели (например, вы должны читать несколько раз в секунду), проиндексируйте свой файл. Что я имею в виду: создайте новый RandomAccessFile, ищите все вхождения разрывов строк и помните их смещение байтов. Каждый раз, когда вы хотите читать по определенной строке, просто отмените поиск смещения байта. Вы можете использовать массив int для этого, где индекс - номер строки. Это приводит к временной сложности O (1) для поиска. Но Будьте осторожны: Если файл изменяется после индексации, все смещения байта становятся недействительными. Поэтому вам нужно снова индексировать файл.

Редактировать: Второй вариант требует, чтобы файл не содержал только пустые строки. В этом случае lookup-array также инициирует OutOfMemoryError. Каждому java int требуется 4 байта. Если предположить, что разрыв строки, записанный в файл, должен содержать не менее 1 байт, коэффициент будет равен 4. Поэтому при индексировании 750-мегабайтного большого файла для массива требуется не менее 4 * 750 МБ = 3 ГБ. Поэтому вам нужно увеличить кучу JVM с помощью опции командной строки -Xmx.

второй Редактировать: Как piet.t указано выше, если файл содержит только одну строку, вы также должны увеличить JVM кучи с помощью опции командной строки -Xmx.

Смежные вопросы