16

Java で読み取りたいファイルがあり、このファイルをn(ユーザー入力) 出力ファイルに分割します。ファイルの読み取り方法は次のとおりです。

int n = 4;
BufferedReader br = new BufferedReader(new FileReader("file.csv"));
try {
    String line = br.readLine();

    while (line != null) {
        line = br.readLine();
    }
} finally {
    br.close();
}

file.csvファイルをファイルに分割するにはどうすればよいnですか?

注 - ファイルのエントリ数は 100k のオーダーであるため、ファイルの内容を配列に格納して分割し、複数のファイルに保存することはできません。

4

9 に答える 9

25

1 つのファイルが非常に大きくなる可能性があるため、各分割ファイルも同様に大きくなる可能性があります。

例:

ソースファイルサイズ: 5GB

分割数: 5: 目的地

ファイルサイズ:各1GB(5ファイル)

そのような記憶があっても、この大きな分割チャンクを一度に読み取る方法はありません。基本的に、分割ごとにbyte-array、パフォーマンスとメモリの観点から実行可能であることがわかっている修正サイズを読み取ることができます。

NumSplits: 10 MaxReadBytes: 8KB

public static void main(String[] args) throws Exception
    {
        RandomAccessFile raf = new RandomAccessFile("test.csv", "r");
        long numSplits = 10; //from user input, extract it from args
        long sourceSize = raf.length();
        long bytesPerSplit = sourceSize/numSplits ;
        long remainingBytes = sourceSize % numSplits;

        int maxReadBufferSize = 8 * 1024; //8KB
        for(int destIx=1; destIx <= numSplits; destIx++) {
            BufferedOutputStream bw = new BufferedOutputStream(new FileOutputStream("split."+destIx));
            if(bytesPerSplit > maxReadBufferSize) {
                long numReads = bytesPerSplit/maxReadBufferSize;
                long numRemainingRead = bytesPerSplit % maxReadBufferSize;
                for(int i=0; i<numReads; i++) {
                    readWrite(raf, bw, maxReadBufferSize);
                }
                if(numRemainingRead > 0) {
                    readWrite(raf, bw, numRemainingRead);
                }
            }else {
                readWrite(raf, bw, bytesPerSplit);
            }
            bw.close();
        }
        if(remainingBytes > 0) {
            BufferedOutputStream bw = new BufferedOutputStream(new FileOutputStream("split."+(numSplits+1)));
            readWrite(raf, bw, remainingBytes);
            bw.close();
        }
            raf.close();
    }

    static void readWrite(RandomAccessFile raf, BufferedOutputStream bw, long numBytes) throws IOException {
        byte[] buf = new byte[(int) numBytes];
        int val = raf.read(buf);
        if(val != -1) {
            bw.write(buf);
        }
    }
于 2013-10-04T10:37:55.190 に答える
8
import java.io.*;  
import java.util.Scanner;  
public class split {  
public static void main(String args[])  
{  
 try{  
  // Reading file and getting no. of files to be generated  
  String inputfile = "C:/test.txt"; //  Source File Name.  
  double nol = 2000.0; //  No. of lines to be split and saved in each output file.  
  File file = new File(inputfile);  
  Scanner scanner = new Scanner(file);  
  int count = 0;  
  while (scanner.hasNextLine())   
  {  
   scanner.nextLine();  
   count++;  
  }  
  System.out.println("Lines in the file: " + count);     // Displays no. of lines in the input file.  

  double temp = (count/nol);  
  int temp1=(int)temp;  
  int nof=0;  
  if(temp1==temp)  
  {  
   nof=temp1;  
  }  
  else  
  {  
   nof=temp1+1;  
  }  
  System.out.println("No. of files to be generated :"+nof); // Displays no. of files to be generated.  

  //---------------------------------------------------------------------------------------------------------  

  // Actual splitting of file into smaller files  

  FileInputStream fstream = new FileInputStream(inputfile); DataInputStream in = new DataInputStream(fstream);  

  BufferedReader br = new BufferedReader(new InputStreamReader(in)); String strLine;  

  for (int j=1;j<=nof;j++)  
  {  
   FileWriter fstream1 = new FileWriter("C:/New Folder/File"+j+".txt");     // Destination File Location  
   BufferedWriter out = new BufferedWriter(fstream1);   
   for (int i=1;i<=nol;i++)  
   {  
    strLine = br.readLine();   
    if (strLine!= null)  
    {  
     out.write(strLine);   
     if(i!=nol)  
     {  
      out.newLine();  
     }  
    }  
   }  
   out.close();  
  }  

  in.close();  
 }catch (Exception e)  
 {  
  System.err.println("Error: " + e.getMessage());  
 }  

}  

}   
于 2014-07-23T06:47:56.350 に答える
0

エントリ数をカウントするカウンターを用意します。1 行に 1 つのエントリがあるとしましょう。

step1: 最初に新しいサブファイルを作成し、counter=0 を設定します。

ステップ 2: ソース ファイルからバッファへの各エントリを読み取るたびにカウンタをインクリメントします。

step3: カウンタが各サブファイルに書き込みたいエントリ数の制限に達したら、バッファの内容をサブファイルにフラッシュします。サブファイルを閉じる

step4 : ソース ファイルにデータが読み込まれるまで、step1 にジャンプします。

于 2013-10-04T09:44:29.313 に答える
0

ファイルを 2 回ループする必要はありません。各チャンクのサイズは、ソース ファイルのサイズを必要なチャンク数で割った値として見積もることができます。次に、サイズが推定を超えているため、各カンクにデータを入力するのをやめます。

于 2013-10-04T09:47:06.103 に答える