2016-12-23 7 views
1

特定の文字を置き換えることによってCSVに変換する必要がある大量のファイルがたくさんあります。与えられたInputStreamは文字を置き換えてOutputStreamを生成します

私は信頼できるアプローチを探しています。InputStreamはOutputStreamを返し、すべての文字をc1からc2に置き換えます。

ここでのトリックは、並列で読み書きすることです。メモリにファイル全体を収めることはできません。

同時に読み書きする場合は別のスレッドで実行する必要がありますか?

アドバイスをいただきありがとうございます。

+1

アンInputStreamがあなたにバイトを与えます。あなたがあなたのエンコーディングを知っているなら、リーダーを使って文字を得ることができます。それから、必要に応じて通過して置換する各文字を見ることができます。 –

+0

はい。ありがとうございました。すでにビルド済みのソリューションがあれば、私は考えていましたか? –

+0

おそらく。これまでに何を探しましたか? –

答えて

1

入力ストリームから出力ストリームにデータをコピーするには、バイト(または文字)または一度に1つの行を読み取っている間にデータを書き込みます。

ここでは、すべての 'x'文字を 'y'に変換するファイルを読み込む例を示します。

BufferedInputStream in = new BufferedInputStream(new FileInputStream("input.dat")); 
BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream("output.dat")); 
int ch; 
while((ch = in.read()) != -1) { 
     if (ch == 'x') ch = 'y'; 
     out.write(ch); 
} 
out.close(); 
in.close(); 

またはこのaproachを使用することができ、その後リーダーを使用して、一度にラインを処理することができる場合:

BufferedReader reader = new BufferedReader(new FileReader("input.dat")); 
PrintWriter writer = new PrintWriter(
     new BufferedOutputStream(new FileOutputStream("output.dat"))); 
String str; 
while ((str = reader.readLine()) != null) { 
    str = str.replace('x', 'y');  // replace character at a time 
    str = str.replace("abc", "ABC"); // replace string sequence 
    writer.println(str); 
} 
writer.close(); 
reader.close(); 

にBufferedInputStreamBufferedReaderの先読みしてバッファ内の文字の8Kを保ちますパフォーマンスのために。非常に大きなファイルは、同時に8Kの文字をメモリに保持しながら処理することができます。

+0

よかった、ありがとう!しかし、どのように私は並行して読み書きするのですか?私はそのファイル全体をメモリに入れることができません。 –

+0

処理中に一度に1バイトずつファイルを処理すると、Javaはファイル全体をメモリに入れません。上記のBufferedInputStreamとBufferedReaderは読み込み中に小さなメモリ内キャッシュを保持しているため、読み込み中にファイルの8Kだけが格納されます。ファイルが多くのテラバイトのサイズであり、ファイルをチャンクに分割しない限り、アプローチを並列化する必要はありません。 – JasonM1

+0

特定のファイルを処理し、各スレッドが一度に1つのファイルを処理し、完了するまで繰り返すn個のスレッドを作成するためのリーダー/ライタージョブクラスを作成できます。 – JasonM1

1
  FileWriter writer = new FileWriter("Report.csv"); 
      BufferedReader reader = new BufferedReader(new InputStreamReader(YOURSOURCE, Charsets.UTF_8)); 
      String line; 
      while ((line = reader.readLine()) != null) { 
       line.replace('c1', 'c2'); 
       writer.append(line); 
       writer.append('\n'); 
      } 
      writer.flush(); 
      writer.close(); 
0

あなたがここに関連する答えを見つけることができます:https://gist.github.com/lhr0909/e6ac2d6dd6752871eb57c4b083799947

:私は、そのスレッドでの@ aioobeの答えを取って、あなたが私のGitHubの要旨でそれを見つけることができますJavaで置き換える入力ストリームモジュールを、構築された

Filter (search and replace) array of bytes in an InputStream

ここにもソースコードを置く:

import java.io.FilterInputStream; 
import java.io.IOException; 
import java.io.InputStream; 
import java.util.Iterator; 
import java.util.LinkedList; 
import java.util.Queue; 

/** 
* Created by simon on 8/29/17. 
*/ 
public class ReplacingInputStream extends FilterInputStream { 

    private Queue<Integer> inQueue, outQueue; 
    private final byte[] search, replacement; 

    public ReplacingInputStream(InputStream in, String search, String replacement) { 
     super(in); 

     this.inQueue = new LinkedList<>(); 
     this.outQueue = new LinkedList<>(); 

     this.search = search.getBytes(); 
     this.replacement = replacement.getBytes(); 
    } 

    private boolean isMatchFound() { 
     Iterator<Integer> iterator = inQueue.iterator(); 

     for (byte b : search) { 
      if (!iterator.hasNext() || b != iterator.next()) { 
       return false; 
      } 
     } 

     return true; 
    } 

    private void readAhead() throws IOException { 
     // Work up some look-ahead. 
     while (inQueue.size() < search.length) { 
      int next = super.read(); 
      inQueue.offer(next); 

      if (next == -1) { 
       break; 
      } 
     } 
    } 

    @Override 
    public int read() throws IOException { 
     // Next byte already determined. 

     while (outQueue.isEmpty()) { 
      readAhead(); 

      if (isMatchFound()) { 
       for (byte a : search) { 
        inQueue.remove(); 
       } 

       for (byte b : replacement) { 
        outQueue.offer((int) b); 
       } 
      } else { 
       outQueue.add(inQueue.remove()); 
      } 
     } 

     return outQueue.remove(); 
    } 

    @Override 
    public int read(byte b[]) throws IOException { 
     return read(b, 0, b.length); 
    } 

    // copied straight from InputStream inplementation, just needed to to use `read()` from this class 
    @Override 
    public int read(byte b[], int off, int len) throws IOException { 
     if (b == null) { 
      throw new NullPointerException(); 
     } else if (off < 0 || len < 0 || len > b.length - off) { 
      throw new IndexOutOfBoundsException(); 
     } else if (len == 0) { 
      return 0; 
     } 

     int c = read(); 
     if (c == -1) { 
      return -1; 
     } 
     b[off] = (byte)c; 

     int i = 1; 
     try { 
      for (; i < len ; i++) { 
       c = read(); 
       if (c == -1) { 
        break; 
       } 
       b[off + i] = (byte)c; 
      } 
     } catch (IOException ee) { 
     } 
     return i; 
    } 
} 
関連する問題