Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Java Новый топик    Ответить
Топик располагается на нескольких страницах: 1 2      [все]
 BufferedReader, пропустить строку  [new]
Павел Гужанов
Member

Откуда: Наро-Фоминск
Сообщений: 453
Здравствуйте.
Для чтения строк из файла большого размера использую BufferReader.

BufferedReader reader = new BufferedReader(                     
            		new InputStreamReader(                             
            				new FileInputStream(pathToFile), charset));

String line = reader.readLine();
while(line != null){
   // обработка строки
   .....
   try{
      line = reader.readLine();
   }catch (OutOfMemoryError e){
      // Обрабтка ошибки
   }
}

На одной из строк ловлю OutOfMemoryError.
Проверяю, вижу, что эта строка в файле некорректная, и имеет огромную длину, так что OutOfMemory вполне логичен.
Думаю, что правильнее всего будет в секции catch перейти на следующую строку, чтобы продолжить обработку файла.
Но никак не могу сделать этот переход, у BufferReader для перехода на следующую строку есть только метод readLine(), а он опять пытается прочитать ту же строку, и опять ловит OutOfMemory.
BufferReader использую потому, что он нормально и быстро работает с большими файлами, и ему можно указать кодировку файла.

Подскажите, как мне решить проблему?
3 июл 19, 12:43    [21919753]     Ответить | Цитировать Сообщить модератору
 Re: BufferedReader, пропустить строку  [new]
PetroNotC Sharp
Member

Откуда:
Сообщений: 2041
Павел Гужанов
Думаю, что правильнее всего будет в секции catch перейти на следующую строку, чтобы продолжить обработку файла.
может тогда не читать построчно а ПРЕДВАРИТЕЛЬНО узнавать размер строк?
Это от бизнес логики зависит.
3 июл 19, 12:58    [21919772]     Ответить | Цитировать Сообщить модератору
 Re: BufferedReader, пропустить строку  [new]
PetroNotC Sharp
Member

Откуда:
Сообщений: 2041
Как вариант:
- у оси спрашиваете размер.
- посчитали нужную память для целиком в память. Либо поиск конца строки в цикле и имеем размер строк
3 июл 19, 13:13    [21919790]     Ответить | Цитировать Сообщить модератору
 Re: BufferedReader, пропустить строку  [new]
Павел Гужанов
Member

Откуда: Наро-Фоминск
Сообщений: 453
В файле строки разные по длине.
Искать конец строки - не вариант, файл может быть в несколько гигабайт, миллионы строк. И имеются требования по быстродействию
3 июл 19, 13:16    [21919794]     Ответить | Цитировать Сообщить модератору
 Re: BufferedReader, пропустить строку  [new]
PetroNotC Sharp
Member

Откуда:
Сообщений: 2041
Павел Гужанов,
То есть нужно быстро, но с пропусками так как памяти мало. Так?
3 июл 19, 13:20    [21919795]     Ответить | Цитировать Сообщить модератору
 Re: BufferedReader, пропустить строку  [new]
Павел Гужанов
Member

Откуда: Наро-Фоминск
Сообщений: 453
Да, если проблемная строка, то ее пропустить, записав информацию в лог
3 июл 19, 13:21    [21919797]     Ответить | Цитировать Сообщить модератору
 Re: BufferedReader, пропустить строку  [new]
PetroNotC Sharp
Member

Откуда:
Сообщений: 2041
Павел Гужанов
Да, если проблемная строка, то ее пропустить, записав информацию в лог
читай с начальной позиции Следующая. Но для этого надо знать размпр проблемной.
3 июл 19, 13:28    [21919804]     Ответить | Цитировать Сообщить модератору
 Re: BufferedReader, пропустить строку  [new]
Павел Гужанов
Member

Откуда: Наро-Фоминск
Сообщений: 453
Предполагаю, что размер проблемной строки может быть любым.
Единственное, что может быть можно использовать - мне известен максимальный возможный размер правильной строки
3 июл 19, 13:31    [21919807]     Ответить | Цитировать Сообщить модератору
 Re: BufferedReader, пропустить строку  [new]
PetroNotC Sharp
Member

Откуда:
Сообщений: 2041
Павел Гужанов
Предполагаю, что размер проблемной строки может быть любым.
я намекал что без поиска конца строки по спецсимволу и выхода на размер проблемной НЕ ВЫЙДЕТ.
ИМХО
3 июл 19, 13:34    [21919810]     Ответить | Цитировать Сообщить модератору
 Re: BufferedReader, пропустить строку  [new]
Павел Гужанов
Member

Откуда: Наро-Фоминск
Сообщений: 453
Но получаю строку я в line = reader.readLine(), ловлю ошибку, и ридер не переходит на следующую строку. В catch я вижу, что в line осталась предыдущая строка, которая корректна. Если я в catch пытаюсь пойти дальше (line = reader.readLine(), то опять получаю ту же ошибку.
3 июл 19, 13:35    [21919811]     Ответить | Цитировать Сообщить модератору
 Re: BufferedReader, пропустить строку  [new]
lleming
Member

Откуда:
Сообщений: 1638
Если имеется ввиду где в jre готовая реализация то такой нет если неошибаюсь, придется руки испачкать и написать самому.
3 июл 19, 13:35    [21919813]     Ответить | Цитировать Сообщить модератору
 Re: BufferedReader, пропустить строку  [new]
PetroNotC Sharp
Member

Откуда:
Сообщений: 2041
Павел Гужанов,
Думаю поиск в тексте будет несравнимо быстрее чем логика обработки.
3 июл 19, 13:36    [21919818]     Ответить | Цитировать Сообщить модератору
 Re: BufferedReader, пропустить строку  [new]
PetroNotC Sharp
Member

Откуда:
Сообщений: 2041
Павел Гужанов
Но получаю строку я в line = reader.readLine(), ловлю ошибку, и ридер не переходит на следующую строку. В catch я вижу, что в line осталась предыдущая строка, которая корректна. Если я в catch пытаюсь пойти дальше (line = reader.readLine(), то опять получаю ту же ошибку.
позиция не сменилась так как не прочитано. Что удивляет?
3 июл 19, 13:37    [21919820]     Ответить | Цитировать Сообщить модератору
 Re: BufferedReader, пропустить строку  [new]
PetroNotC Sharp
Member

Откуда:
Сообщений: 2041
lleming
Если имеется ввиду где в jre готовая реализация то такой нет если неошибаюсь, придется руки испачкать и написать самому.
готового чего? Найти символ в гиговом файле?
3 июл 19, 13:39    [21919822]     Ответить | Цитировать Сообщить модератору
 Re: BufferedReader, пропустить строку  [new]
Павел Гужанов
Member

Откуда: Наро-Фоминск
Сообщений: 453
PetroNotC Sharp,

Не удивляет. Просто говорю, что я эту строку не получил, поэтому с ее размером играться не могу
3 июл 19, 13:41    [21919825]     Ответить | Цитировать Сообщить модератору
 Re: BufferedReader, пропустить строку  [new]
Dmitry.
Member

Откуда: Львів
Сообщений: 841
ловить outofmemory стремно.
екстенднуть bufferedreader и сделать свой readLine с лимитом по длине строки.
3 июл 19, 13:43    [21919827]     Ответить | Цитировать Сообщить модератору
 Re: BufferedReader, пропустить строку  [new]
PetroNotC Sharp
Member

Откуда:
Сообщений: 2041
Павел Гужанов
PetroNotC Sharp,

Не удивляет. Просто говорю, что я эту строку не получил, поэтому с ее размером играться не могу
еще раз.
Алгоритм такой что нужно искать конец строки прежде чем читать в память.
Понял?
3 июл 19, 13:54    [21919840]     Ответить | Цитировать Сообщить модератору
 Re: BufferedReader, пропустить строку  [new]
Павел Гужанов
Member

Откуда: Наро-Фоминск
Сообщений: 453
PetroNotC Sharp,
Это я понял. Но вот никак не могу придумать, как это реализовать. Ведь если строка не в памяти, то как с ней манипулировать?
Если же я ее прочитаю (reader.readLine()), то получу outOfMemory
3 июл 19, 13:59    [21919848]     Ответить | Цитировать Сообщить модератору
 Re: BufferedReader, пропустить строку  [new]
PetroNotC Sharp
Member

Откуда:
Сообщений: 2041
Павел Гужанов,
Если нет indexOf("\n
То циклом искать.
3 июл 19, 14:01    [21919853]     Ответить | Цитировать Сообщить модератору
 Re: BufferedReader, пропустить строку  [new]
PetroNotC Sharp
Member

Откуда:
Сообщений: 2041
Павел Гужанов,
Есть метод read по символьный. Дай сюда скорость прохода по всему файлу.
3 июл 19, 14:02    [21919856]     Ответить | Цитировать Сообщить модератору
 Re: BufferedReader, пропустить строку  [new]
Павел Гужанов
Member

Откуда: Наро-Фоминск
Сообщений: 453
по файлу в 1300000 строк (файл для отладки, реальный больше) с обработкой и сохранением строк в БД тратится примерно 2.5 - 3 минуты
3 июл 19, 14:08    [21919863]     Ответить | Цитировать Сообщить модератору
 Re: BufferedReader, пропустить строку  [new]
Павел Гужанов
Member

Откуда: Наро-Фоминск
Сообщений: 453
indexOf("\n") надо искать в строке. А у меня этой строки нет, т.к. вылетаю с ошибкой
Если все строки читать посимвольно, то, есть опасение, что я зависну совсем надолго
3 июл 19, 14:11    [21919866]     Ответить | Цитировать Сообщить модератору
 Re: BufferedReader, пропустить строку  [new]
PetroNotC Sharp
Member

Откуда:
Сообщений: 2041
Павел Гужанов,
1. Дай скорость посимвольного чтения БЕЗ ВСЕГО.
2. ПЕРЕД reaLine прочти в буфер 100 символов и там ищи конец строки.
3 июл 19, 14:14    [21919871]     Ответить | Цитировать Сообщить модератору
 Re: BufferedReader, пропустить строку  [new]
PetroNotC Sharp
Member

Откуда:
Сообщений: 2041
Павел Гужанов
1300000 строк
3. Валидируй в фоне файлы на входе.
3 июл 19, 14:16    [21919873]     Ответить | Цитировать Сообщить модератору
 Re: BufferedReader, пропустить строку  [new]
Павел Гужанов
Member

Откуда: Наро-Фоминск
Сообщений: 453
Метод read() возвращает число
The character read, as an integer in the range 0 to 65535 (0x00-0xffff), or -1 if the end of the stream has been reached
3 июл 19, 14:28    [21919887]     Ответить | Цитировать Сообщить модератору
 Re: BufferedReader, пропустить строку  [new]
PetroNotC Sharp
Member

Откуда:
Сообщений: 2041
Павел Гужанов,
А причем тут что возвращает?
"Прочитать 100 символов в буфер" выше писал.
3 июл 19, 14:32    [21919892]     Ответить | Цитировать Сообщить модератору
 Re: BufferedReader, пропустить строку  [new]
Павел Гужанов
Member

Откуда: Наро-Фоминск
Сообщений: 453
Если предположить, что я считал посимвольно 100 символов и не нашел там конец строки, то мне надо перейти на следующую строку. А как это сделать? Переход в BufferedReader происходит при readLine(), а он вызывает ошибку
3 июл 19, 14:32    [21919893]     Ответить | Цитировать Сообщить модератору
 Re: BufferedReader, пропустить строку  [new]
Basil A. Sidorov
Member

Откуда:
Сообщений: 9404
А \r и \n имеют вполне конкретные коды. Удивительно, да?
3 июл 19, 14:33    [21919895]     Ответить | Цитировать Сообщить модератору
 Re: BufferedReader, пропустить строку  [new]
PetroNotC Sharp
Member

Откуда:
Сообщений: 2041
Павел Гужанов
Если предположить, что я считал посимвольно 100 символов и не нашел там конец строки, то мне надо перейти на следующую строку. А как это сделать? Переход в BufferedReader происходит при readLine(), а он вызывает ошибку
да. Тогда читай по символьно до конца. Раз нельзя отбросить целиком невалидный файл. Парси его весь.
Цифры сюда дать 10 минут.
3 июл 19, 14:35    [21919898]     Ответить | Цитировать Сообщить модератору
 Re: BufferedReader, пропустить строку  [new]
lleming
Member

Откуда:
Сообщений: 1638
PetroNotC Sharp
lleming
Если имеется ввиду где в jre готовая реализация то такой нет если неошибаюсь, придется руки испачкать и написать самому.
готового чего? Найти символ в гиговом файле?


топикстартер спрашивает нет ли чтото вроде этого

while(line != null || !reader.lastState().isLineTooLong()){


найти символ подразумевает его искать т.е писать код алгоритма поиска.
3 июл 19, 14:56    [21919938]     Ответить | Цитировать Сообщить модератору
 Re: BufferedReader, пропустить строку  [new]
PetroNotC Sharp
Member

Откуда:
Сообщений: 2041
lleming,
ОК
3 июл 19, 15:03    [21919950]     Ответить | Цитировать Сообщить модератору
 Re: BufferedReader, пропустить строку  [new]
Павел Гужанов
Member

Откуда: Наро-Фоминск
Сообщений: 453
Всем спасибо за помощь.
Сделал так:
try {
        line = reader.readLine();
} catch (OutOfMemoryError e) {
	logger.error("Слишком большая строка " + counter);
	int symbol = reader.read()ж
	int i = 0;
	while(symbol != 10 && symbol != 13) {
		i++;
		symbol = reader.read();
	}
	logger.error("Длина строки " + i);
	line = reader.readLine();
	if(line != null && line.length() == 0)
	        line = reader.readLine();
}
3 июл 19, 15:34    [21919988]     Ответить | Цитировать Сообщить модератору
 Re: BufferedReader, пропустить строку  [new]
PetroNotC Sharp
Member

Откуда:
Сообщений: 2041
Павел Гужанов,
+1
Только лучше не доводить до райзе по памяти.
Ну и цифры не дал. Жаль.
Удачи!
3 июл 19, 16:14    [21920042]     Ответить | Цитировать Сообщить модератору
 Re: BufferedReader, пропустить строку  [new]
mayton
Member

Откуда: loopback
Сообщений: 42343
Павел Гужанов
BufferedReader reader = new BufferedReader(                     
            		new InputStreamReader(                             
            				new FileInputStream(pathToFile), charset));

String line = reader.readLine();
while(line != null){
   // обработка строки
   .....
   try{
      line = reader.readLine();
   }catch (OutOfMemoryError e){
      // Обрабтка ошибки
   }
}

Несколько мыслей.

Предположительно. Файл который ты читаешь - не совсем текстовый.
Потому-как сломать мозг хипу можно реально ооооочень длинными строками.
По факту Java поддерживает индексацию символов до 2 млрд. Но беря во внимание
что BufferedReader внутри использует StringBuffer который может делать реаллокации.
А реаллокации требуют 2 * n памяти плюс хвостик на расширение. Тут возможны варианты
что не хватило не памяти. А не хватило временной памяти которая нужна буферному ридеру
для копирования староого символьного массива в новое место. Но это моё предположение.
Я не изучал как работает этот ридер.

Железное решение твоей проблемы - читать файл не построчно а посимвольно. И принимать
решение на каждый символ. Формировать строки. С пониманием предметной области.
3 июл 19, 18:01    [21920150]     Ответить | Цитировать Сообщить модератору
 Re: BufferedReader, пропустить строку  [new]
mayton
Member

Откуда: loopback
Сообщений: 42343
}catch (OutOfMemoryError e){
      // Обрабтка ошибки
}

Так обычно не делают. Ошибка OOM не предполагает ее оперативного решения.
Она просто к сведению перед тем как исполнительная среда упадет. Обычно
если это происходит то память не удалось освободить и нет ресурсов на ее решение.
3 июл 19, 18:21    [21920168]     Ответить | Цитировать Сообщить модератору
Топик располагается на нескольких страницах: 1 2      [все]
Все форумы / Java Ответить