I have found this question in other languages, but have yet to find a solution to this issue in a java application.
I have a large .txt
file with millions of records. Each record is /n
delimited. Basically it is a single column of data from a table. The goal is to read the data from the input file and partition it. Then write the partitioned data to a new file. For example, a file with 2 million records will become 200 files with 10,000 records each (with the last file containing <10,000.)
I am successfully reading and partitioning the data. I am successfully creating the first file and it is being named properly.
The problem is only 1 file is created and it is empty. The code as is compiles and runs without errors or exceptions.
My code is below:
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
public class ChunkTextFile {
private static final String inputFilename = "inputFile.txt";
public static void main(String[] args) {
BufferedReader reader = null;
BufferedWriter fileWriter = null;
BufferedWriter lineWriter = null;
StringWriter stringWriter = null;
// Create an ArrayList object to hold the lines of input file
List<String> lines = new ArrayList<String>();
try {
// Creating BufferedReader object to read the input file
reader = new BufferedReader(new FileReader("src" + "//" + inputFilename));
// Reading all the lines of input file one by one and adding them into ArrayList
String currentLine = reader.readLine();
while (currentLine != null) {
lines.add(currentLine);
currentLine = reader.readLine();
}
// End of file read.
//Partition ArrayList into a collection of smaller Lists<String>
final AtomicInteger counter = new AtomicInteger(0);
final int size = 10000;
Collection<List<String>> partitioned = lines.stream()
.collect(Collectors.groupingBy(it -> counter.getAndIncrement() / size)).values();
//Printing partitions. Each partition will be written to a file.
//Testing confirms the partitioning works correctly.
partitioned.forEach(System.out::println);
//Iterate through the Collections and create a file for List<String> object.
//Testing confirms that multiple files are created and properly named.
Integer count = 0;
for (List<String> chunks : partitioned) {
// Prepare new incremented file name.
String outputFile = "batched_items_file_";
String txt = ".txt";
count++;
String filename = outputFile + count + txt;
// Write file to directory.
fileWriter = new BufferedWriter(new FileWriter("src" + "//" + outputFile));
fileWriter = new BufferedWriter(new FileWriter(filename));
//Iterate through the List of Strings and write each String to the file.
//Writing is not successful. Only 1 file is created and it is empty.
for (String chunk : chunks) {
stringWriter = new StringWriter();
lineWriter = new BufferedWriter(stringWriter);
// Prepare list of strings to be written to new file.
// Write each item number to file.
lineWriter.write(chunk);
lineWriter.flush();
}
lineWriter.close(); // <- flush the BufferedWriter
fileWriter.close();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
// Closing the resources
System.out.println("Finished");
try {
if (reader != null) {
reader.close();
}
if (fileWriter != null) {
fileWriter.close();
}
if (stringWriter != null) {
stringWriter.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
Input file example:
230449
235659
295377
329921
348526
359836
361447
384723
396202
571490
Thank you in advance.
You don't need all those extra writers in your for and the writer supposed to write (fileWriter) to the file is not being called. Replace your for by this one:
for (String chunk : chunks) {
fileWriter.write(chunk);
}
Tip: Just call fileWriter.close() once inside the finally block. The close method will automatically flush the writer for you (there's no need to call fileWriter.flush()).