2013-10-04 3 views
9

У меня есть файл, который я хотел бы прочитать на Java и разделить этот файл на выходные файлы n (пользовательский ввод). Вот как я прочитал файл:Java - Чтение файла и разбиение на несколько файлов

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 файлы?

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

+0

В цикле while просто собирайте столько строк, сколько хотите, в String или StringBuilder и записывайте их в отдельные файлы. Вы не можете заранее знать количество файлов, возможно, было бы лучше определить максимальное количество строк в файле. –

+0

Вам нужно либо дважды зациклиться, чтобы получить количество строк, а затем разделить. Или вы можете догадаться о количестве строк и разбить этот путь. –

+0

@ kw4nta Почему бы вам не захотеть _store_ строк. 1) OP говорит, что сохранение всех строк не является вариантом, 2) учитывая, что вы можете писать строки прямо в другой файл ... –

ответ

11

Поскольку файл может быть очень большой, разделять файлы могут сами как хорошо быть большим:

Пример:

Источник Размер файла: 5Гб

Num расколы: 5: Назначение

Размер файла: 1 ГБ каждый (5 файлов)

Невозможно прочитать этот большой кусок сплита за один раз, даже если у нас есть такая память. В основном для каждого раскола мы можем прочитать размер исправления byte-array, который, как мы знаем, должен быть осуществим с точки зрения производительности, а также памяти.

NumSplits: 10 MaxReadBytes: 8КБ

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); 
     } 
    } 
+5

Ну, он может разделить линию на полпути, и это важно для файла csv –

+0

Есть ли способ преодолеть это? так что он не разделяет среднюю линию? – Julian

+0

В моей компании у нас есть фиксированный размер записи для каждого столбца, и мы делаем дополнение в CSV, поэтому мы делим размер файла с одним размером записи, а затем разделим. Кроме того, при чтении каждой строки отправляется на MQ, чтобы она была вставлена ​​так, чтобы она была асинхронной. В любом случае ваша душа хороша. –

0

У вас есть счетчик для подсчета количества записей. Скажем, одна запись в строке.

Шаг1: Первоначально создайте новый подфайл, установите счетчик = 0;

step2: приращение счетчика, когда вы читаете каждую запись из исходного файла в буфер

step3: когда счетчик достигает предела для количества записей, которые вы хотите записать в каждом суб-файла, промойте содержимое буфера субфайловом. закрыть субфайловом

Step4: прыжок step1 до вас есть данные в исходном файле для чтения из

0

Там нет необходимости в цикле дважды по файлу. Вы можете оценить размер каждого фрагмента, так как размер исходного файла делится на количество необходимых блоков. Затем вы просто прекращаете заполнять каждый бит данных данными, поскольку размер превышает его.

5
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()); 
} 

} 

} 
+1

Это не делает то, что хотел OP (установить количество файлов), но он делает то, что я хочу (установить количество строк). Хороший код! Изменено это как функция, принимающая имя файла и динамическое именование созданных файлов. –

+0

C & P от http://javaprogramming.language-tutorial.com/2012/10/split-huge-files-into-small-text-files.html? (Запись в блоге с 2012 года) – bish

2

Хотя св старый вопрос, но для справки я пречисление код, который я использовал для разделения больших файлов любых размеров и он работает с любые версии Java выше 1.4.

Sample разделение и соединение блоков были, как показано ниже:

public void join(String FilePath) { 
    long leninfile = 0, leng = 0; 
    int count = 1, data = 0; 
    try { 
     File filename = new File(FilePath); 
     //RandomAccessFile outfile = new RandomAccessFile(filename,"rw"); 

     OutputStream outfile = new BufferedOutputStream(new FileOutputStream(filename)); 
     while (true) { 
      filename = new File(FilePath + count + ".sp"); 
      if (filename.exists()) { 
       //RandomAccessFile infile = new RandomAccessFile(filename,"r"); 
       InputStream infile = new BufferedInputStream(new FileInputStream(filename)); 
       data = infile.read(); 
       while (data != -1) { 
        outfile.write(data); 
        data = infile.read(); 
       } 
       leng++; 
       infile.close(); 
       count++; 
      } else { 
       break; 
      } 
     } 
     outfile.close(); 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
} 

public void split(String FilePath, long splitlen) { 
    long leninfile = 0, leng = 0; 
    int count = 1, data; 
    try { 
     File filename = new File(FilePath); 
     //RandomAccessFile infile = new RandomAccessFile(filename, "r"); 
     InputStream infile = new BufferedInputStream(new FileInputStream(filename)); 
     data = infile.read(); 
     while (data != -1) { 
      filename = new File(FilePath + count + ".sp"); 
      //RandomAccessFile outfile = new RandomAccessFile(filename, "rw"); 
      OutputStream outfile = new BufferedOutputStream(new FileOutputStream(filename)); 
      while (data != -1 && leng < splitlen) { 
       outfile.write(data); 
       leng++; 
       data = infile.read(); 
      } 
      leninfile += leng; 
      leng = 0; 
      outfile.close(); 
      count++; 
     } 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
} 

кода Полная Java доступна здесь в File Split in Java Program ссылке.

+1

Хотя эта ссылка может ответить на вопрос, лучше включить здесь основные части ответа и предоставить ссылку для справки. Ответные ссылки могут стать недействительными, если связанная страница изменится. - [Из обзора] (/ review/low-quality-posts/12423371) – CubeJockey

+1

Спасибо, Обновлен комментарий. – user1472187

0

Вот один из них, который работал на меня, и я использовал его для разбиения файла на 10 ГБ. он также позволяет добавлять заголовок и нижний колонтитул.очень полезно при разбиении формата на основе документов, такого как XML и JSON, потому что вам нужно добавить обертку документа в новые разделенные файлы.

import java.io.BufferedReader; 
import java.io.BufferedWriter; 
import java.io.File; 
import java.io.IOException; 
import java.nio.file.Files; 
import java.nio.file.Path; 
import java.nio.file.Paths; 
import java.nio.file.StandardOpenOption; 

public class FileSpliter 
{ 
    public static void main(String[] args) throws IOException 
    { 
     splitTextFiles("D:\\xref.csx", 750000, "", "", null); 
    } 

    public static void splitTextFiles(String fileName, int maxRows, String header, String footer, String targetDir) throws IOException 
    { 
     File bigFile = new File(fileName); 
     int i = 1; 
     String ext = fileName.substring(fileName.lastIndexOf(".")); 

     String fileNoExt = bigFile.getName().replace(ext, ""); 
     File newDir = null; 
     if(targetDir != null) 
     { 
      newDir = new File(targetDir);   
     } 
     else 
     { 
      newDir = new File(bigFile.getParent() + "\\" + fileNoExt + "_split"); 
     } 
     newDir.mkdirs(); 
     try (BufferedReader reader = Files.newBufferedReader(Paths.get(fileName))) 
     { 
      String line = null; 
      int lineNum = 1; 
      Path splitFile = Paths.get(newDir.getPath() + "\\" + fileNoExt + "_" + String.format("%02d", i) + ext); 
      BufferedWriter writer = Files.newBufferedWriter(splitFile, StandardOpenOption.CREATE); 
      while ((line = reader.readLine()) != null) 
      { 
       if(lineNum == 1) 
       { 
        System.out.print("new file created '" + splitFile.toString()); 
        if(header != null && header.length() > 0) 
        { 
         writer.append(header); 
         writer.newLine(); 
        } 
       } 
       writer.append(line); 

       if (lineNum >= maxRows) 
       { 
        if(footer != null && footer.length() > 0) 
        { 
         writer.newLine(); 
         writer.append(footer); 
        } 
        writer.close(); 
        System.out.println(", " + lineNum + " lines written to file"); 
        lineNum = 1; 
        i++; 
        splitFile = Paths.get(newDir.getPath() + "\\" + fileNoExt + "_" + String.format("%02d", i) + ext); 
        writer = Files.newBufferedWriter(splitFile, StandardOpenOption.CREATE); 
       } 
       else 
       { 
        writer.newLine(); 
        lineNum++; 
       } 
      } 
      if(lineNum <= maxRows) // early exit 
      { 
       if(footer != null && footer.length() > 0) 
       { 
        writer.newLine(); 
        lineNum++; 
        writer.append(footer); 
       } 
      } 
      writer.close(); 
      System.out.println(", " + lineNum + " lines written to file"); 
     } 

     System.out.println("file '" + bigFile.getName() + "' split into " + i + " files"); 
    } 
} 
0

Ниже код, используемый для разбиения большого файла на мелкие файлы с меньшими линиями.

long linesWritten = 0; 
    int count = 1; 

    try { 
     File inputFile = new File(inputFilePath); 
     InputStream inputFileStream = new BufferedInputStream(new FileInputStream(inputFile)); 
     BufferedReader reader = new BufferedReader(new InputStreamReader(inputFileStream)); 

     String line = reader.readLine(); 

     String fileName = inputFile.getName(); 
     String outfileName = outputFolderPath + "\\" + fileName; 

     while (line != null) { 
      File outFile = new File(outfileName + "_" + count + ".split"); 
      Writer writer = new OutputStreamWriter(new FileOutputStream(outFile)); 

      while (line != null && linesWritten < linesPerSplit) { 
       writer.write(line); 
       line = reader.readLine(); 
       linesWritten++; 
      } 

      writer.close(); 
      linesWritten = 0;//next file 
      count++;//nect file count 
     } 

     reader.close(); 

    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
+0

Код, который я написал выше, работает, и я проверил файл с 40L records/line. Требуется около 10 секунд, чтобы разбить файл на строки 1 литра на файл. –

Смежные вопросы