Подтвердить что ты не робот

Java: InputStream слишком медленный, чтобы читать огромные файлы

Мне нужно прочитать символ файла 53 Мб по символу. Когда я делаю это на С++, используя ifstream, он завершается в миллисекундах, но с использованием Java InputStream требуется несколько минут. Нормально ли для Java это медленное или я что-то упускаю?

Кроме того, мне нужно завершить программу на Java (она использует сервлеты, из которых я должен вызывать функции, которые обрабатывают эти символы). Я думал, может быть, написав часть обработки файлов на C или С++, а затем используя Java Native Interface для взаимодействия этих функций с моими Java-программами... Как эта идея?

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

Отредактировано: Мой код охватывает несколько файлов, и он очень грязный, поэтому я даю синопсис

import java.io.*;

public class tmp {
    public static void main(String args[]) {
        try{
        InputStream file = new BufferedInputStream(new FileInputStream("1.2.fasta"));
        char ch;        
        while(file.available()!=0) {
            ch = (char)file.read();
                    /* Do processing */
            }
        System.out.println("DONE");
        file.close();
        }catch(Exception e){}
    }
}
4b9b3361

Ответ 1

Я запустил этот код с файлом размером 183 МБ. Он напечатал "Истекшие 250 мс".

final InputStream in = new BufferedInputStream(new FileInputStream("file.txt"));
final long start = System.currentTimeMillis();
int cnt = 0;
final byte[] buf = new byte[1000];
while (in.read(buf) != -1) cnt++;
in.close();
System.out.println("Elapsed " + (System.currentTimeMillis() - start) + " ms");

Ответ 2

Я бы попробовал это

// create the file so we have something to read.
final String fileName = "1.2.fasta";
FileOutputStream fos = new FileOutputStream(fileName);
fos.write(new byte[54 * 1024 * 1024]);
fos.close();

// read the file in one hit.
long start = System.nanoTime();
FileChannel fc = new FileInputStream(fileName).getChannel();
ByteBuffer bb = fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size());
while (bb.remaining() > 0)
    bb.getLong();
long time = System.nanoTime() - start;
System.out.printf("Took %.3f seconds to read %.1f MB%n", time / 1e9, fc.size() / 1e6);
fc.close();
((DirectBuffer) bb).cleaner().clean();

печатает

Took 0.016 seconds to read 56.6 MB

Ответ 3

Используйте BufferedInputStream:

InputStream buffy = new BufferedInputStream(inputStream);

Ответ 4

Как отмечено выше, используйте BufferedInputStream. Вы также можете использовать пакет NIO. Обратите внимание, что для большинства файлов BufferedInputStream будет таким же быстрым, как NIO. Однако для чрезвычайно больших файлов NIO может улучшиться, потому что вы можете выполнять операции с файлами в памяти. Кроме того, пакет NIO делает прерывание ввода-вывода, а пакет java.io - нет. Это означает, что если вы хотите отменить операцию из другого потока, вы должны использовать NIO, чтобы сделать его надежным.

ByteBuffer buf = ByteBuffer.allocate(BUF_SIZE);
FileChannel fileChannel = fileInputStream.getChannel();
int readCount = 0;
while ( (readCount = fileChannel.read(buf)) > 0) {
  buf.flip();
  while (buf.hasRemaining()) {
    byte b = buf.get();
  }
  buf.clear();
}