Java 将字符串列表写入文件,但文件为空
Java writing a list of strings to a file, but the file is empty
我在其他语言中发现了这个问题,但还没有在 java 应用程序中找到解决这个问题的方法。
我有一个包含数百万条记录的大型 .txt
文件。每条记录都是 /n
分隔的。基本上它是来自 table 的单列数据。目标是从输入文件中读取数据并对其进行分区。然后将分区后的数据写入新文件。例如,一个有 200 万条记录的文件将变成 200 个文件,每个文件有 10,000 条记录(最后一个文件包含 <10,000。)
我正在成功读取和分区数据。我成功地创建了第一个文件,并且命名正确。
问题是只创建了 1 个文件,而且它是空的。代码按原样编译和运行,没有错误或异常。
我的代码如下:
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();
}
}
}
}
输入文件示例:
230449
235659
295377
329921
348526
359836
361447
384723
396202
571490
提前致谢。
一个StringWriter
不是写字符串,是写到一个字符串.
您的 for 中不需要所有那些额外的编写器,并且应该写入 (fileWriter) 到文件的编写器没有被调用。
用这个替换你的:
for (String chunk : chunks) {
fileWriter.write(chunk);
}
提示:只需在 finally 块内调用 fileWriter.close() 一次。 close 方法会自动为你刷新 writer(不需要调用 fileWriter.flush())。
您可以只使用
Path file = Paths.get(filename);
Files.write(file, chunks, Charset.forName("UTF-8"));
而且,你应该在循环之前加上count=0,否则它总是0。
总体来说是这样的:
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
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;
// 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(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 = 10;
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 the file is 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;
Path file = Paths.get(filename);
Files.write(file, chunks, Charset.forName("UTF-8"));
}
} catch (IOException e) {
e.printStackTrace();
} finally {
// Closing the resources
System.out.println("Finished");
try {
if (reader != null) {
reader.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
我接受上面的答案,因为它解决了我的问题,但我想为找到这个问题和答案的任何人扩展它。为了使创建的文件与输入文件的格式相同(换行符分隔),我使用接受的答案更改了代码并添加了 System.lineSeparator()
.
最终的解决方案如下所示。
fileWriter.write(chunk + System.lineSeparator());
再次感谢您的快速回复。
这是工作版本。我建议注释掉或删除 partitioned.forEach(System.out::println);
以提高性能。
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;
// 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.
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 the file is 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) {
// Prepare list of strings to be written to new file.
// Write each item number to file.
fileWriter.write(chunk + System.lineSeparator());
}
}
} catch (IOException e) {
e.printStackTrace();
} finally {
// Closing the resources
System.out.println("Finished");
try {
if (reader != null) {
reader.close();
}
if (fileWriter != null) {
fileWriter.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
您的代码存在几个问题。文件是空的,因为您没有关闭编写器。您甚至按照此顺序创建冗余编写器
fileWriter = new BufferedWriter(new FileWriter("src" + "//" + outputFile));
fileWriter = new BufferedWriter(new FileWriter(filename));
要以最佳方式处理读者和作者等资源,请使用 try-with-resources statement。
缺少新行只是一个小问题。
此外,您不必要地将整个输入文件读入堆内存,只是为了能够对其执行有问题的 Stream 操作。虽然可以直接流式传输文件,例如使用 Files.lines
,使用 AtomicInteger
进行分组并不是使用 Stream
的预期方式。并且最终结果仍会将整个输入行保存在内存中,同时直接将这些行立即写入目标文件。
一个简单有效的解决方案是
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
public class ChunkTextFile {
private static final String inputFilename = "inputFile.txt";
public static void main(String[] args) {
final int size = 10000;
try(BufferedReader reader=Files.newBufferedReader(Paths.get("src", inputFilename))) {
String line = reader.readLine();
for(int count = 0; line != null; count++) {
try(BufferedWriter writer = Files.newBufferedWriter(
Paths.get("batched_items_file_" + count + ".txt"))) {
for(int i = 0; i < size && line != null; i++) {
writer.write(line);
writer.newLine();
line = reader.readLine();
}
}
}
}
catch(IOException ex) {
ex.printStackTrace();
}
}
}
我在其他语言中发现了这个问题,但还没有在 java 应用程序中找到解决这个问题的方法。
我有一个包含数百万条记录的大型 .txt
文件。每条记录都是 /n
分隔的。基本上它是来自 table 的单列数据。目标是从输入文件中读取数据并对其进行分区。然后将分区后的数据写入新文件。例如,一个有 200 万条记录的文件将变成 200 个文件,每个文件有 10,000 条记录(最后一个文件包含 <10,000。)
我正在成功读取和分区数据。我成功地创建了第一个文件,并且命名正确。
问题是只创建了 1 个文件,而且它是空的。代码按原样编译和运行,没有错误或异常。
我的代码如下:
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();
}
}
}
}
输入文件示例:
230449
235659
295377
329921
348526
359836
361447
384723
396202
571490
提前致谢。
一个StringWriter
不是写字符串,是写到一个字符串.
您的 for 中不需要所有那些额外的编写器,并且应该写入 (fileWriter) 到文件的编写器没有被调用。 用这个替换你的:
for (String chunk : chunks) {
fileWriter.write(chunk);
}
提示:只需在 finally 块内调用 fileWriter.close() 一次。 close 方法会自动为你刷新 writer(不需要调用 fileWriter.flush())。
您可以只使用
Path file = Paths.get(filename);
Files.write(file, chunks, Charset.forName("UTF-8"));
而且,你应该在循环之前加上count=0,否则它总是0。
总体来说是这样的:
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
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;
// 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(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 = 10;
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 the file is 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;
Path file = Paths.get(filename);
Files.write(file, chunks, Charset.forName("UTF-8"));
}
} catch (IOException e) {
e.printStackTrace();
} finally {
// Closing the resources
System.out.println("Finished");
try {
if (reader != null) {
reader.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
我接受上面的答案,因为它解决了我的问题,但我想为找到这个问题和答案的任何人扩展它。为了使创建的文件与输入文件的格式相同(换行符分隔),我使用接受的答案更改了代码并添加了 System.lineSeparator()
.
最终的解决方案如下所示。
fileWriter.write(chunk + System.lineSeparator());
再次感谢您的快速回复。
这是工作版本。我建议注释掉或删除 partitioned.forEach(System.out::println);
以提高性能。
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;
// 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.
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 the file is 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) {
// Prepare list of strings to be written to new file.
// Write each item number to file.
fileWriter.write(chunk + System.lineSeparator());
}
}
} catch (IOException e) {
e.printStackTrace();
} finally {
// Closing the resources
System.out.println("Finished");
try {
if (reader != null) {
reader.close();
}
if (fileWriter != null) {
fileWriter.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
您的代码存在几个问题。文件是空的,因为您没有关闭编写器。您甚至按照此顺序创建冗余编写器
fileWriter = new BufferedWriter(new FileWriter("src" + "//" + outputFile));
fileWriter = new BufferedWriter(new FileWriter(filename));
要以最佳方式处理读者和作者等资源,请使用 try-with-resources statement。
缺少新行只是一个小问题。
此外,您不必要地将整个输入文件读入堆内存,只是为了能够对其执行有问题的 Stream 操作。虽然可以直接流式传输文件,例如使用 Files.lines
,使用 AtomicInteger
进行分组并不是使用 Stream
的预期方式。并且最终结果仍会将整个输入行保存在内存中,同时直接将这些行立即写入目标文件。
一个简单有效的解决方案是
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
public class ChunkTextFile {
private static final String inputFilename = "inputFile.txt";
public static void main(String[] args) {
final int size = 10000;
try(BufferedReader reader=Files.newBufferedReader(Paths.get("src", inputFilename))) {
String line = reader.readLine();
for(int count = 0; line != null; count++) {
try(BufferedWriter writer = Files.newBufferedWriter(
Paths.get("batched_items_file_" + count + ".txt"))) {
for(int i = 0; i < size && line != null; i++) {
writer.write(line);
writer.newLine();
line = reader.readLine();
}
}
}
}
catch(IOException ex) {
ex.printStackTrace();
}
}
}