0

セミコロンで区切られた入力ファイルがあります。最初の列は3文字の固定幅コードで、残りの列は文字列データです。

001;first_data_str;second_data_str;third_data_str;fourth_data_str
001;first_data_str;second_data_str;third_data_str;fourth_data_str
002;first_data_str;second_data_str;third_data_str;fourth_data_str
003;first_data_str;second_data_str;third_data_str;fourth_data_str
001;first_data_str;second_data_str;third_data_str;fourth_data_str
003;first_data_str;second_data_str;third_data_str;fourth_data_str
001;first_data_str;second_data_str;third_data_str;fourth_data_str
002;first_data_str;second_data_str;third_data_str;fourth_data_str
002;first_data_str;second_data_str;third_data_str;fourth_data_str
003;first_data_str;second_data_str;third_data_str;fourth_data_str
003;first_data_str;second_data_str;third_data_str;fourth_data_str
003;first_data_str;second_data_str;third_data_str;fourth_data_str
002;first_data_str;second_data_str;third_data_str;fourth_data_str
001;first_data_str;second_data_str;third_data_str;fourth_data_str

上記のファイルを、最初の列のさまざまな値に基づいていくつかのファイルに分割したいと思います。

たとえば、上記の例では、最初の列に3つの異なる値があるため、ファイルを3つのファイルに分割します。001.txt、002.txt、003.txt

出力ファイルには、1行目としてアイテム数、残りの行としてデータが含まれている必要があります。

つまり、5 001行あるので、001.txtは次のようになります。

5
first_data_str;second_data_str;third_data_str;fourth_data_str
first_data_str;second_data_str;third_data_str;fourth_data_str
first_data_str;second_data_str;third_data_str;fourth_data_str
first_data_str;second_data_str;third_data_str;fourth_data_str
first_data_str;second_data_str;third_data_str;fourth_data_str

同様に、002ファイルの最初の行は4行、次に4行のデータになり、003ファイルの最初の行は5行、次に5行のデータになります。

100,000行を超える非常に大きな入力ファイルを考慮して、これを実現するための最も効率的な方法は何でしょうか。

ファイルから行を読み取るために、以下のコードを記述しました。

try{
          FileInputStream fstream = new FileInputStream(this.inputFilePath);
          DataInputStream in = new DataInputStream(fstream);
          BufferedReader br = new BufferedReader(new InputStreamReader(in));
          String strLine;

          while ((strLine = br.readLine()) != null)   {
              String[] tokens = strLine.split(";");
         }

          in.close();
    }catch(IOException e){
        e.printStackTrace();
    }
4

5 に答える 5

1
  • 各行について
  • チャンク名を抽出します(例:001)
  • 「001-tmp.txt」という名前のファイルを探します
  • 存在する場合は、最初の行を読み取ります。行数が表示され、値をインクリメントし、引数0のseek関数を使用して同じファイルに書き込み、 writeUTFを使用して文字列をオーバーライドします。おそらく、ここで文字列の長さの計算を適用する必要があります。たとえば、プレースホルダーを10スペース残します。
  • 存在しない場合は、1つ作成し、最初の行として1を書き込み、10個のスペースを埋めます
  • 現在の行をファイルに追加します
  • 現在のファイルを閉じる
  • ソースファイルの次の行に進みます
于 2012-09-17T13:02:35.043 に答える
1

頭に浮かぶ解決策の1つは、「マップ」を保持し、すべてのファイルを1回だけ開くことです。ただし、lac行が約1つあるため、これを行うことはできません。そのため、これほど多くのファイル記述子を開くことができるOSはありません。

したがって、1つの方法は、ファイルを追加モードで開き、書き込みを続けて閉じることです。ただし、ファイルを開いて閉じる呼び出しが非常に多いため、プロセスが遅くなる可能性があります。ただし、自分でテストすることはできます。

上記で満足のいく結果が得られない場合は、アプローチ1と2を組み合わせて試してみてください。この方法では、開いているファイルを常に100個だけ開き、まだ開いていない新しいファイルを書き込む必要がある場合にのみファイルを閉じます。 ...。

于 2012-09-17T13:02:56.663 に答える
0

3文字コードごとに、入力行のリストがあります。私にとって明らかな解決策は、すべての行を含む対応MapするStringキー(3つの文字コード)を指すキー(3つの文字コード)を使用することです。List

これらのキーごとに、関連する名前のファイルを作成します。最初の行はリストのサイズになり、次にそれを繰り返して残りの行を書き込みます。

于 2012-09-17T13:00:56.243 に答える
0

3つのファイルに固定されていないので、3文字のコードをキーとして、ライターを値として、ライターのマップを作成することをお勧めします。

読み取る行ごとに、必要なリーダーを選択または作成して、行を書き込みます。また、すべてのファイルの行数の値を維持するために2番目のマップが必要です。

ソースファイルの読み取りが終了したら、すべてのライターをフラッシュして閉じ、ファイルを1つずつもう一度読み取ります。今回は、ファイルの前に行数を追加するだけです。ファイル全体をバッファリングして再書き込みせずにファイルの先頭に何かを直接追加することは不可能であるため、私の知る限りファイル全体を再書き込みする以外に方法はありません。これには一時ファイルを使用することをお勧めします。

この回答は、ファイルが大きすぎてメモリに完全に保存できない場合にのみ適用されます。保存が可能な場合、これに対するより高速な解決策があります。StringBufferファイルに書き込む前に、ファイルの内容をオブジェクトに完全に保存するようなものです。

于 2012-09-17T13:01:44.333 に答える
0

まず、HashMap<String, ArrayList<String>> mapファイルからすべてのデータを収集するために作成します。次に、strLine.split(";",2)の代わりに使用しstrLine.split(";")ます。結果は長さ2の配列になり、最初の要素はコード、2番目の要素はデータになります。次に、デコードされた文字列をマップに追加します。

ArrayList<String> list=map.get(tokens[0]);
if (list==null) {
   map.put(tokens[0], list=new ArrayList<String>();
}
list.add(tokens[1]);

最後に、とをスキャンしmap.keySet()て各キーをスキャンし、そのキーという名前のファイルを作成して、リストのサイズとコンテンツを書き込みます。

于 2012-09-17T13:06:13.657 に答える