У меня очень большой файл (~ 6 ГБ), который имеет текст фиксированной ширины, разделенный символом \ r \ n, и поэтому я использую буферизованный считыватель для чтения по строкам. Этот процесс может быть прерван или остановлен, и если это так, он использует контрольную точку «lastProcessedLineNbr» для быстрой пересылки в нужное место для возобновления чтения. Так инициализируется читатель.Почему BufferedReader readLine читает прошлое EOF
private void initializeBufferedReader(Integer lastProcessedLineNbr) throws IOException {
reader = new BufferedReader(new InputStreamReader(getInputStream(), "UTF-8"));
if(lastProcessedLineNbr==null){lastProcessedLineNbr=0;}
for(int i=0; i<lastProcessedLineNbr;i++){
reader.readLine();
}
currentLineNumber = lastProcessedLineNbr;
}
Это, кажется, работает хорошо, и я прочитал и обрабатывать данные в этом методе:
public Object readItem() throws Exception {
if((currentLine = reader.readLine())==null){
return null;
}
currentLineNumber++;
return parse(currentLine);
}
И опять же, все работает отлично, пока я не достигну последнюю строку в документе. ReadLine() в последнем методе выдает ошибку:
17:06:49,980 ERROR [org.jberet] (Batch Thread - 1) JBERET000007: Failed to run job ProdFileRead, parse, [email protected]: java.lang.OutOfMemoryError: Requested array size exceeds VM limit
at java.util.Arrays.copyOf(Arrays.java:3332)
at java.lang.AbstractStringBuilder.expandCapacity(AbstractStringBuilder.java:137)
at java.lang.AbstractStringBuilder.ensureCapacityInternal(AbstractStringBuilder.java:121)
at java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:569)
at java.lang.StringBuffer.append(StringBuffer.java:369)
at java.io.BufferedReader.readLine(BufferedReader.java:370)
at java.io.BufferedReader.readLine(BufferedReader.java:389)
at com.rational.batch.reader.TextLineReader.readItem(TextLineReader.java:55)
Любопытно, что, кажется, чтение после конца файла и выделения так много места, что она бежит из памяти. Я попытался посмотреть содержимое файла с помощью Cygwin и «tail file.txt», а в консоли он дал мне ожидаемые 10 строк. Но когда я сделал «tail file.txt> output.txt» output.txt оказался как 1.8GB, намного больше, чем 10 строк, которые я ожидал. Так кажется Cygwin делает то же самое. Насколько я могу судить, нет особого характера EOF. Это всего лишь последний байт данных, и он заканчивается внезапно.
У кого-нибудь есть идеи, как я могу заставить это работать? Я думаю, что могу прибегнуть к подсчету количества прочитанных байтов, пока не получу полный размер файла, но я надеялся, что есть лучший способ.
Конечно, добавление EOF к файлу мне также пришло в голову, но я также не уверен, что это java-способ поместить символ EOF, так как это зависит от ОС. Я бы хотел, чтобы он работал как в Windows, так и в Linux. – joshuar
В Windows или Linux нет «символов EOF». Ctrl-D или Ctrl-Z интерпретируются подсистемой ввода-вывода терминала и сигналом EOF для процесса чтения. Помещение одного из них в файл не будет иметь предполагаемого эффекта. Реальный вопрос в том, что такое содержимое файла в «последней» записи. Из-за исключения появляется последняя «строка» очень большая, достаточно большая, чтобы переполнять доступную память. Вы _sure_ все строки '\ r \ n' разделены? Есть ли пустое пространство, выделенное в файле _after_ последней строки, которая возвращается? –