2009-06-30 37 views
54

Tôi phải ghi dữ liệu lớn trong tệp văn bản [csv]. Tôi đã sử dụng BufferedWriter để ghi dữ liệu và mất khoảng 40 giây để viết 174 mb dữ liệu. Đây có phải là tốc độ nhanh nhất mà java có thể cung cấp không?Cách nhanh nhất để ghi dữ liệu lớn trong tệp văn bản Java

bufferedWriter = new BufferedWriter (new FileWriter ("fileName.csv")); 

Lưu ý: Những 40 giây bao gồm thời điểm đi làm lại và lấy hồ sơ từ resultset là tốt. :). 174 mb là 400000 hàng trong resultset.

+3

Bạn sẽ không xảy ra để có anti-virus hoạt động trên máy tính mà bạn chạy mã này? –

Trả lời

87

Bạn có thể thử xóa BufferedWriter và chỉ sử dụng FileWriter trực tiếp. Trên một hệ thống hiện đại có một cơ hội tốt bạn chỉ cần ghi vào bộ nhớ cache của ổ đĩa anyway.

Tôi mất trong khoảng 4-5 giây để viết 175MB (4 triệu dây) - đây là trên một lõi kép 2.4GHz Dell chạy Windows XP với ổ đĩa Hitachi 80GB 7200 RPM.

Bạn có thể cô lập khoảng thời gian thu hồi bản ghi và số lượng tệp được ghi không?

import java.io.BufferedWriter; 
import java.io.File; 
import java.io.FileWriter; 
import java.io.IOException; 
import java.io.Writer; 
import java.util.ArrayList; 
import java.util.List; 

public class FileWritingPerfTest { 


private static final int ITERATIONS = 5; 
private static final double MEG = (Math.pow(1024, 2)); 
private static final int RECORD_COUNT = 4000000; 
private static final String RECORD = "Help I am trapped in a fortune cookie factory\n"; 
private static final int RECSIZE = RECORD.getBytes().length; 

public static void main(String[] args) throws Exception { 
    List<String> records = new ArrayList<String>(RECORD_COUNT); 
    int size = 0; 
    for (int i = 0; i < RECORD_COUNT; i++) { 
     records.add(RECORD); 
     size += RECSIZE; 
    } 
    System.out.println(records.size() + " 'records'"); 
    System.out.println(size/MEG + " MB"); 

    for (int i = 0; i < ITERATIONS; i++) { 
     System.out.println("\nIteration " + i); 

     writeRaw(records); 
     writeBuffered(records, 8192); 
     writeBuffered(records, (int) MEG); 
     writeBuffered(records, 4 * (int) MEG); 
    } 
} 

private static void writeRaw(List<String> records) throws IOException { 
    File file = File.createTempFile("foo", ".txt"); 
    try { 
     FileWriter writer = new FileWriter(file); 
     System.out.print("Writing raw... "); 
     write(records, writer); 
    } finally { 
     // comment this out if you want to inspect the files afterward 
     file.delete(); 
    } 
} 

private static void writeBuffered(List<String> records, int bufSize) throws IOException { 
    File file = File.createTempFile("foo", ".txt"); 
    try { 
     FileWriter writer = new FileWriter(file); 
     BufferedWriter bufferedWriter = new BufferedWriter(writer, bufSize); 

     System.out.print("Writing buffered (buffer size: " + bufSize + ")... "); 
     write(records, bufferedWriter); 
    } finally { 
     // comment this out if you want to inspect the files afterward 
     file.delete(); 
    } 
} 

private static void write(List<String> records, Writer writer) throws IOException { 
    long start = System.currentTimeMillis(); 
    for (String record: records) { 
     writer.write(record); 
    } 
    writer.flush(); 
    writer.close(); 
    long end = System.currentTimeMillis(); 
    System.out.println((end - start)/1000f + " seconds"); 
} 
} 
+2

@rozario mỗi cuộc gọi viết chỉ nên tạo khoảng 175MB và sau đó xóa chính nó.nếu không, bạn sẽ kết thúc với 175MB x 4 cuộc gọi viết khác nhau x 5 lần lặp = 3.5GB dữ liệu. bạn có thể kiểm tra giá trị trả về từ tệp.delete() và nếu nó sai, hãy ném một ngoại lệ. –

+0

Lưu ý rằng 'writer.flush()' là không cần thiết trong trường hợp này vì 'writer.close()' [flushes memory] (http://docs.oracle.com/javase/7/docs/api/java/io /BufferedWriter.html) implicity. BTW: thực hành tốt nhất khuyên bạn nên sử dụng [cố gắng đóng tài nguyên] (https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html) thay vì gọi một cách rõ ràng 'close()'. –

+2

FWIW, điều này được viết cho Java 5, mà ít nhất là không được ghi lại để tuôn ra khi đóng và không có tài nguyên thử. Nó có thể có thể sử dụng cập nhật. –

4

Tốc độ truyền của bạn có thể không bị giới hạn bởi Java. Thay vào đó tôi sẽ nghi ngờ (không theo thứ tự đặc biệt)

  1. tốc độ đường truyền từ cơ sở dữ liệu
  2. tốc độ đường truyền vào ổ

Nếu bạn đọc các tập dữ liệu đầy đủ và sau đó viết nó ra vào đĩa, sau đó sẽ mất nhiều thời gian hơn, vì JVM sẽ phải cấp phát bộ nhớ và ghi rea/disk db sẽ xảy ra tuần tự. Thay vào đó, tôi sẽ viết cho người viết đệm cho mỗi lần đọc mà bạn tạo từ db, và do đó hoạt động sẽ gần hơn với một đồng thời (tôi không biết bạn có đang làm việc đó hay không)

28

nhớ thử ánh xạ file (mất 300 m/s để viết 174MB trong m của tôi/c, core 2 duo, 2.5GB RAM):

byte[] buffer = "Help I am trapped in a fortune cookie factory\n".getBytes(); 
int number_of_lines = 400000; 

FileChannel rwChannel = new RandomAccessFile("textfile.txt", "rw").getChannel(); 
ByteBuffer wrBuf = rwChannel.map(FileChannel.MapMode.READ_WRITE, 0, buffer.length * number_of_lines); 
for (int i = 0; i < number_of_lines; i++) 
{ 
    wrBuf.put(buffer); 
} 
rwChannel.close(); 
+0

aMessage.length() có nghĩa là đại diện cho khi bạn đang khởi tạo ByteBuffer? – Hotel

+2

Jut fyi, chạy trên MacBook Pro (cuối năm 2013), 2.6 Ghz Core i7, với Apple 1TB SSD mất khoảng 140ms cho 185 meg (dòng = 4million) – Egwor

+0

whats điểm của "number_of_lines"? –

14

Chỉ vì lợi ích của thống kê :

máy cũ Dell với SSD mới

CPU: Intel Pentium D 2,8 Ghz

SSD: Patriot Inferno 120GB SSD

4000000 'records' 
175.47607421875 MB 

Iteration 0 
Writing raw... 3.547 seconds 
Writing buffered (buffer size: 8192)... 2.625 seconds 
Writing buffered (buffer size: 1048576)... 2.203 seconds 
Writing buffered (buffer size: 4194304)... 2.312 seconds 

Iteration 1 
Writing raw... 2.922 seconds 
Writing buffered (buffer size: 8192)... 2.406 seconds 
Writing buffered (buffer size: 1048576)... 2.015 seconds 
Writing buffered (buffer size: 4194304)... 2.282 seconds 

Iteration 2 
Writing raw... 2.828 seconds 
Writing buffered (buffer size: 8192)... 2.109 seconds 
Writing buffered (buffer size: 1048576)... 2.078 seconds 
Writing buffered (buffer size: 4194304)... 2.015 seconds 

Iteration 3 
Writing raw... 3.187 seconds 
Writing buffered (buffer size: 8192)... 2.109 seconds 
Writing buffered (buffer size: 1048576)... 2.094 seconds 
Writing buffered (buffer size: 4194304)... 2.031 seconds 

Iteration 4 
Writing raw... 3.093 seconds 
Writing buffered (buffer size: 8192)... 2.141 seconds 
Writing buffered (buffer size: 1048576)... 2.063 seconds 
Writing buffered (buffer size: 4194304)... 2.016 seconds 

Như chúng ta có thể thấy phương pháp thô là chậm hơn các đệm.

+0

Tuy nhiên, phương thức đệm trở nên chậm hơn bất cứ khi nào kích thước của văn bản lớn hơn. – FSm

1

package all.is.well; 
 
import java.io.IOException; 
 
import java.io.RandomAccessFile; 
 
import java.util.concurrent.ExecutorService; 
 
import java.util.concurrent.Executors; 
 
import junit.framework.TestCase; 
 

 
/** 
 
* @author Naresh Bhabat 
 
* 
 
Following implementation helps to deal with extra large files in java. 
 
This program is tested for dealing with 2GB input file. 
 
There are some points where extra logic can be added in future. 
 

 

 
Pleasenote: if we want to deal with binary input file, then instead of reading line,we need to read bytes from read file object. 
 

 

 

 
It uses random access file,which is almost like streaming API. 
 

 

 
* **************************************** 
 
Notes regarding executor framework and its readings. 
 
Please note :ExecutorService executor = Executors.newFixedThreadPool(10); 
 

 
* \t for 10 threads:Total time required for reading and writing the text in 
 
*   :seconds 349.317 
 
* 
 
*   For 100:Total time required for reading the text and writing : seconds 464.042 
 
* 
 
*   For 1000 : Total time required for reading and writing text :466.538 
 
*   For 10000 Total time required for reading and writing in seconds 479.701 
 
* 
 
* 
 
*/ 
 
public class DealWithHugeRecordsinFile extends TestCase { 
 

 
\t static final String FILEPATH = "C:\\springbatch\\bigfile1.txt.txt"; 
 
\t static final String FILEPATH_WRITE = "C:\\springbatch\\writinghere.txt"; 
 
\t static volatile RandomAccessFile fileToWrite; 
 
\t static volatile RandomAccessFile file; 
 
\t static volatile String fileContentsIter; 
 
\t static volatile int position = 0; 
 

 
\t public static void main(String[] args) throws IOException, InterruptedException { 
 
\t \t long currentTimeMillis = System.currentTimeMillis(); 
 

 
\t \t try { 
 
\t \t \t fileToWrite = new RandomAccessFile(FILEPATH_WRITE, "rw");//for random write,independent of thread obstacles 
 
\t \t \t file = new RandomAccessFile(FILEPATH, "r");//for random read,independent of thread obstacles 
 
\t \t \t seriouslyReadProcessAndWriteAsynch(); 
 

 
\t \t } catch (IOException e) { 
 
\t \t \t // TODO Auto-generated catch block 
 
\t \t \t e.printStackTrace(); 
 
\t \t } 
 
\t \t Thread currentThread = Thread.currentThread(); 
 
\t \t System.out.println(currentThread.getName()); 
 
\t \t long currentTimeMillis2 = System.currentTimeMillis(); 
 
\t \t double time_seconds = (currentTimeMillis2 - currentTimeMillis)/1000.0; 
 
\t \t System.out.println("Total time required for reading the text in seconds " + time_seconds); 
 

 
\t } 
 

 
\t /** 
 
\t * @throws IOException 
 
\t * Something asynchronously serious 
 
\t */ 
 
\t public static void seriouslyReadProcessAndWriteAsynch() throws IOException { 
 
\t \t ExecutorService executor = Executors.newFixedThreadPool(10);//pls see for explanation in comments section of the class 
 
\t \t while (true) { 
 
\t \t \t String readLine = file.readLine(); 
 
\t \t \t if (readLine == null) { 
 
\t \t \t \t break; 
 
\t \t \t } 
 
\t \t \t Runnable genuineWorker = new Runnable() { 
 
\t \t \t \t @Override 
 
\t \t \t \t public void run() { 
 
\t \t \t \t \t // do hard processing here in this thread,i have consumed 
 
\t \t \t \t \t // some time and eat some exception in write method. 
 
\t \t \t \t \t writeToFile(FILEPATH_WRITE, readLine); 
 
\t \t \t \t \t // System.out.println(" :" + 
 
\t \t \t \t \t // Thread.currentThread().getName()); 
 

 
\t \t \t \t } 
 
\t \t \t }; 
 
\t \t \t executor.execute(genuineWorker); 
 
\t \t } 
 
\t \t executor.shutdown(); 
 
\t \t while (!executor.isTerminated()) { 
 
\t \t } 
 
\t \t System.out.println("Finished all threads"); 
 
\t \t file.close(); 
 
\t \t fileToWrite.close(); 
 
\t } 
 

 
\t /** 
 
\t * @param filePath 
 
\t * @param data 
 
\t * @param position 
 
\t */ 
 
\t private static void writeToFile(String filePath, String data) { 
 
\t \t try { 
 
\t \t \t // fileToWrite.seek(position); 
 
\t \t \t data = "\n" + data; 
 
\t \t \t if (!data.contains("Randomization")) { 
 
\t \t \t \t return; 
 
\t \t \t } 
 
\t \t \t System.out.println("Let us do something time consuming to make this thread busy"+(position++) + " :" + data); 
 
\t \t \t System.out.println("Lets consume through this loop"); 
 
\t \t \t int i=1000; 
 
\t \t \t while(i>0){ 
 
\t \t \t 
 
\t \t \t \t i--; 
 
\t \t \t } 
 
\t \t \t fileToWrite.write(data.getBytes()); 
 
\t \t \t throw new Exception(); 
 
\t \t } catch (Exception exception) { 
 
\t \t \t System.out.println("exception was thrown but still we are able to proceeed further" 
 
\t \t \t \t \t + " \n This can be used for marking failure of the records"); 
 
\t \t \t //exception.printStackTrace(); 
 

 
\t \t } 
 

 
\t } 
 
}

+0

Vui lòng thêm một số văn bản giải thích lý do tại sao câu trả lời này tốt hơn câu trả lời khác. Có ý kiến ​​trong mã là không đủ. –

+0

Lý do điều này có thể tốt hơn: đó là một kịch bản thời gian thực và nó đang ở trong một ví dụ trạng thái làm việc. Các lợi ích khác của nó, nó xử lý việc đọc, xử lý và viết không đồng bộ ... Nó sử dụng tệp java api (tức là) truy cập ngẫu nhiên là luồng an toàn và nhiều luồng có thể đọc và ghi trên cùng một lúc. Nó không gây ra phí trên bộ nhớ trong thời gian chạy, nó cũng không làm hỏng hệ thống ... nó là giải pháp đa năng để xử lý sự thất bại của xử lý bản ghi có thể được theo dõi trong chuỗi tương ứng. Vui lòng cho tôi biết nếu tôi có thể trợ giúp thêm. – RAM

+1

Cảm ơn bạn, đó là thông tin mà bài đăng của bạn cần. Có lẽ xem xét thêm nó vào bài viết cơ thể :) –

Các vấn đề liên quan