Итерация в двух чрезвычайно больших файлах одновременно в Java - PullRequest
0 голосов
/ 01 октября 2011

Мне нужно объединить два очень больших файла (> 1G каждый), записав 4 строки из первого в выходной файл, а затем записать 4 из второго. И так до конца. Оба файла имеют одинаковое количество строк, и это число делится на четыре. Какой самый эффективный способ сделать это на Java?

Ответы [ 3 ]

0 голосов
/ 01 октября 2011

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

import java.io.*;
class Time {
    Time() {}
    long dt() {
        return System.currentTimeMillis() - t0;
    }
    final long t0 = System.currentTimeMillis();
}
public class Main {
    public static void create(File file1, File file2, int n) throws Exception {
        BufferedWriter bw1 = new BufferedWriter(new FileWriter(file1));
        write(bw1, n, "foo");
        bw1.close();
        BufferedWriter bw2 = new BufferedWriter(new FileWriter(file2));
        write(bw2, n, "bar");
        bw2.close();
    }
    private static void write(BufferedWriter bw, int n, String line) throws IOException {
        for (int i = 0; i < n; i++) {
            bw.write(line);
            bw.write(lineSeparator);
        }
    }
    private static void write4(BufferedReader br1, BufferedWriter bw, String line) throws IOException {
        bw.write(line);
        bw.write(lineSeparator);
        for (int i = 0; i < 3; i++) {
            line = br1.readLine();
            bw.write(line);
            bw.write(lineSeparator);
        }
    }
    public static void main(String[] args) throws Exception {
        File file1 = new File("file1");
        File file2 = new File("file2");
        if (!file1.exists()) {
            create(file1, file2, 10000000);
        }
        File file3 = new File("file3");
        Time time=new Time();
        BufferedReader br1 = new BufferedReader(new FileReader(file1));
        BufferedReader br2 = new BufferedReader(new FileReader(file2));
        BufferedWriter bw = new BufferedWriter(new FileWriter(file3));
        String line1, line2;
        while ((line1 = br1.readLine()) != null) {
            write4(br1, bw, line1);
            line2 = br2.readLine();
            write4(br2, bw, line2);
        }
        br1.close();
        br2.close();
        bw.close();
        System.out.println(time.dt()/1000.+" s.");
    }
    static final String lineSeparator = System.getProperty("line.separator");
}
0 голосов
/ 01 октября 2011

Извините, если эта идея уже была дана:)

Я думаю, что самый быстрый способ сделать это - создать 3 потока.t1 и t2 будут читать из двух входных файлов, каждый поток будет иметь свою собственную очередь (которая является потокобезопасной), и поток будет читать 4 строки и помещать их в свою очередь.t3 будет записывающим потоком, он будет взаимозаменяемо считывать узлы из двух очередей и помещать их в новый объединенный файл.Я думаю, что это хорошее решение, потому что оно позволяет выполнять параллельный ввод во все три файла (а здесь - бутылочное горлышко) и минимальное взаимодействие между потоками.

0 голосов
/ 01 октября 2011

Я люблю использовать Decorator шаблон.Создайте два класса, каждый класс представляет экземпляр BufferedReader.

Например,

class First
{
   BufferedReader br;
   ...
   public String getLine()
    {
       return br.readLine();
     }
}

class Second
{
  BufferedReader br;
  ...
  public String [] getLines()
   {
     //read four lines and return it
   }
}
...