2016-06-15 1 views
1

У меня есть файл данных мэйнфреймов, размер которого превышает 4 ГБ. Мне нужно читать и обрабатывать данные за каждые 500 байт. Я попытался с помощью FileChannel, однако я получаю ошибку с сообщением Integer.MAX_VALUE превысилоЧтение файла> 4 ГБ файла в java

public void getFileContent(String fileName) { 
    RandomAccessFile aFile = null; 
    FileChannel inChannel = null; 
    try { 
     aFile = new RandomAccessFile(Paths.get(fileName).toFile(), "r"); 
     inChannel = aFile.getChannel(); 
     ByteBuffer buffer = ByteBuffer.allocate(500 * 100000); 
     while (inChannel.read(buffer) > 0) { 
      buffer.flip(); 
      for (int i = 0; i < buffer.limit(); i++) { 
       byte[] data = new byte[500]; 
       buffer.get(data); 
       processData(new String(data)); 
       buffer.clear(); 
      } 
     } 
    } catch (Exception ex) { 
     // TODO 
    } finally { 
     try { 
      inChannel.close(); 
      aFile.close(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 
} 

Можете ли вы помочь мне с решением?

+4

Показать трассировку исключения и стека – assylias

+0

Вы можете попробовать обернуть «FileInputStream» с помощью «BufferedInputStream». – venture

+2

Отметьте это -> http://stackoverflow.com/questions/8076472/why-does-filechannel-map-take-up-to-integer-max-value-of-data Подумает о вашей ошибке получают – Techidiot

ответ

2

Самая большая проблема из вас кода является

catch (Exception ex) { 
    // TODO 
} 

часть, которая означает, что вы не заметите каких-либо исключений, брошенные кода. Поскольку в JRE не печатается сообщение «Integer.Max_VALUE превышено», эта проблема должна быть подключена к вашему методу processData.

Возможно, стоит отметить, что этот метод будет слишком часто вызван повторными данными.

Ваш цикл

for (int i = 0; i < buffer.limit(); i++) { 

означает, что вы итерацию столько раз, сколько байт в буфере, до 500 * 100000 раза. Вы извлекаете 500 байт из буфера на каждой итерации, обрабатывая в сумме до 500 * 500 * 100000 байт после каждого read, но поскольку у вас есть неуместное buffer.clear(); в конце тела цикла, вы никогда не испытаете BufferUnderflowException. Вместо этого вы будете вызывать processData каждый из до 500 * 100000 раз с первым байтом 500.

Но все преобразование из байтов в String излишне подробное и содержит ненужные операции копирования. Вместо этого вы можете и должны просто использовать Reader.

Кроме того, ваш код создает странный объезд. Он начинается с Java 7 API, Paths.get, чтобы преобразовать его в унаследованный объект File, создать унаследованное RandomAccessFile, чтобы в итоге получить FileChannel. Если у вас есть Path и вы хотите получить FileChannel, вам следует открыть его непосредственно через FileChannel.open. И, конечно, используйте инструкцию try(…) { … } для обеспечения правильного закрытия.

Но, как говорится, если вы хотите обрабатывать содержимое как String с, вы наверняка хотите использовать Reader вместо:

public void getFileContent(String fileName) { 
    try(Reader reader=Files.newBufferedReader(Paths.get(fileName))) { 
     CharBuffer buffer = CharBuffer.allocate(500 * 100000); 
     while(reader.read(buffer) > 0) { 
      buffer.flip(); 
      while(buffer.remaining()>500) { 
       processData(buffer.slice().limit(500).toString()); 
       buffer.position(buffer.position()+500); 
      } 
      buffer.compact(); 
     } 
     // there might be a remaining chunk of less than 500 characters 
     if(buffer.position()>0) { 
      processData(buffer.flip().toString()); 
     } 
    } catch(Exception ex) { 
     // the *minimum* to do: 
     ex.printStackTrace(); 
     // TODO real exception handling 
    } 
} 

Там нет никаких проблем с обработки файлов> 4 Гб, я просто проверял с файлом 8 ГБ. Обратите внимание, что в приведенном выше коде используется кодировка UTF-8. Если вы хотите сохранить поведение исходного кода с использованием любых случается кодирование вашей системы по умолчанию, вы можете создать Reader используя

Files.newBufferedReader(Paths.get(fileName), Charset.defaultCharset()) 

вместо этого.

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