[英]Write List<CSVRecord> to HDFS
我有一个 CSV 记录列表。
import org.apache.commons.csv.CSVRecord
List<CSVRecord> records = getRecords();
我将记录格式化为字符串生成器。
private StringBuilder formatRecords(final List<CSVRecord> records, final List<String> headersList) {
final StringBuilder sb = new StringBuilder();
final String headers = String.join(",", headersList);
sb.append(headers + "\n");
if (!records.isEmpty()) {
for (final CSVRecord r : records) {
for (int i = 0; i < r.size(); i++) {
sb.append(r.get(i));
// add comma if not last element
if (i < (r.size() - 1)) {
sb.append(",");
}
}
sb.append("\n");
}
}
return sb;
}
然后将字符串写入 HDFS 文件。
DataOutputStream outputStream = getHdfsOutputStream(destPath);
outputStream.writeBytes(records.toString());
这适用于一个小列表。
但是如果列表很大(比如 > 100000),JVM 已经因 OOME 而崩溃。
Administratively Yielded for 1 sec: java.lang.OutOfMemoryError: Java heap space
java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOfRange(Arrays.java:3664)
at java.lang.String.<init>(String.java:207)
at java.lang.StringBuilder.toString(StringBuilder.java:407)
是否可以绕过创建字符串生成器和 stream 到 HDFS 的列表内容?
这可能涉及 2 个步骤。
伪代码
outputStream.write(records.stream().map(<format to add commas and new line>))
但我不确定第 1 步的最佳选择是什么。
这将返回一个字符串列表,因此它不会流式传输任何内容。
recs.stream().map(v -> v.get(0) + "," + v.get(1)).collect(toList());
这将返回对象的 stream。
records.stream().map(v -> v.get(0) + "," + v.get(1) + "\n"));
如何将此 stream 输入 HDFS?
任何帮助/提示将不胜感激。
**** 编辑: ****
这种方法似乎适用于第 2 步(写入流),但没有记录格式。
final FSDataOutputStream outputStream = getHdfsOutputStream(destPath);
BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream, StandardCharsets.UTF_8));
for(CSVRecord r: records) {
bufferedWriter.write(r.toString());
bufferedWriter.newLine();
}
bufferedWriter.close();
configOutputStream.close();
这里是最终代码。 创建一个字符串生成器 p/record 并一次写入一个字符串。
private void persistRecords(final List<CSVRecord> records, final String targetDir, final String targetFile,
final List<String> headers) throws IOException {
final String targetPath = targetDir + targetFile;
try (final FSDataOutputStream outputStream = getHdfsOutputStream(targetPath);
final BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream, StandardCharsets.UTF_8))) {
bufferedWriter.write(String.join(",", headers));
bufferedWriter.newLine();
for (final CSVRecord r : records) {
final StringBuilder sb = format(r);
bufferedWriter.write(sb.toString());
bufferedWriter.newLine();
}
}
}
private StringBuilder format(final CSVRecord r) {
final StringBuilder sb = new StringBuilder();
for (int i = 0; i < r.size(); i++) {
sb.append(r.get(i));
// add comma if not last element
if (i < (r.size() - 1)) {
sb.append(",");
}
}
return sb;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.