2009-06-30 2 views
54

Мне нужно написать огромные данные в текстовом файле [csv]. Я использовал BufferedWriter для записи данных, и потребовалось около 40 секунд для записи 174 мб данных. Это самая быстрая скорость, которую может предложить java?Самый быстрый способ записи огромных данных в текстовый файл Java

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

Примечание: Этих 40 секунд включают время переборе и извлечения записей из результирующих а. :). 174 мб для 400000 строк в наборе результатов.

+3

Вы случайно не имеют анти-вирус, активный на компьютере, на котором работает этот код? –

ответ

87

Вы может попытаться удалить BufferedWriter и просто использовать FileWriter напрямую. В современной системе есть хороший шанс, что вы все равно пишете в кэш-память накопителя.

Мне требуется 4-5 секунд для записи 175 МБ (4 миллиона строк) - это двухъядерный 2,4 ГГц Dell с Windows XP с диском Hitachi емкостью 80 ГБ, 7200 об/мин.

Можете ли вы выделить, сколько времени занимает извлечение записей и сколько написано в файле?

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 каждый вызов для записи должен производить только около 175 МБ, а затем удалять себя.если нет, вы получите 175 Мбайт x 4 разных вызова для записи x 5 итераций = 3,5 ГБ данных. вы можете проверить возвращаемое значение из файла file.delete(), а если оно ложно, выведите исключение. –

+0

Обратите внимание, что 'writer.flush()' в этом случае не требуется, потому что 'writer.close()' [сбрасывает память] (http://docs.oracle.com/javase/7/docs/api/java/io /BufferedWriter.html). BTW: лучшие практики рекомендуют использовать [try resource close] (https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html), вместо этого явно вызывая 'close()'. –

+2

FWIW, это было написано для Java 5, которое, по крайней мере, не было документировано для кратковременного закрытия, и у которого не было ресурсов try-with-resources. Вероятно, он может использовать обновление. –

4

Ваша скорость передачи, вероятно, не будет ограничена Java. Вместо этого я подозреваю (в произвольном порядке)

  1. скорость передачи из базы данных
  2. скорость передачи на диск

Если вы читали полный набор данных, а затем записать его на диск, то это займет больше времени, поскольку JVM придется выделять память, а запись db rea/disk будет происходить последовательно. Вместо этого я напишу буферизованному писателю для каждого чтения, которое вы делаете из db, и поэтому операция будет ближе к параллельной (я не знаю, делаете вы это или нет)

28

попытка памяти отображаются файлы (Берет 300 м/с, чтобы написать 174Мб в моем м/с, 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(), предназначенное для представления, когда вы создаете ByteBuffer? – Hotel

+2

Jut fyi, работающий на MacBook Pro (конец 2013 года), 2,6 ГГц Core i7, с Apple 1tb SSD занимает около 140 мс для 185 мегабайт (линии = 4 миллиона) – Egwor

+0

Что такое точка «number_of_lines»? –

14

только ради статистики :

машина старая Dell с новым SSD

процессор: Intel Pentium D 2,8 ГГц

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 

Как мы видим сырьевой метод медленнее буфер.

+0

Однако буферизованный метод становится медленнее всякий раз, когда размер текста больше. – 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

Пожалуйста, добавьте текст, объясняющий, почему этот ответ лучше, чем другие ответы. Недостаточно комментариев в коде. –

+0

Причина, по которой это может быть лучше: это сценарий реального времени, и он находится в рабочем состоянии. Другие преимущества этого, он обрабатывает асинхронно чтение, обработку и запись ... Он использует эффективный файл java api (i.e), который является потокобезопасным, и несколько потоков могут читать и писать на нем одновременно. Это не приводит к непредвиденным издержкам памяти во время выполнения, а также не приводит к сбою системы ... это многоцелевое решение для устранения сбоев в обработке записей, которые можно отслеживать в соответствующей теме. Пожалуйста, дайте мне знать, если я могу помочь больше. – RAM

+1

Спасибо, это информация, необходимая для вашего сообщения. Возможно, подумайте о добавлении его в тело сообщения :) –

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