我想跳过CSV文件中的标题行。截至目前,我在将其加载到谷歌存储之前手动删除标题。
以下是我的代码:
PCollection<String> financeobj =p.apply(TextIO.read().from("gs://storage_path/Financials.csv"));
PCollection<ClassFinance> pojos5 = financeobj.apply(ParDo.of(new DoFn<String, ClassFinance>() { // converting String into classtype
private static final long serialVersionUID = 1L;
@ProcessElement
public void processElement(ProcessContext c) {
String[] strArr = c.element().split(",");
ClassFinance fin = new ClassFinance();
fin.setBeneficiaryFinance(strArr[0]);
fin.setCatlibCode(strArr[1]);
fin.set_rNR_(Double.valueOf(strArr[2]));
fin.set_rNCS_(Double.valueOf(strArr[3]));
fin.set_rCtb_(Double.valueOf(strArr[4]));
fin.set_rAC_(Double.valueOf(strArr[5]));
c.output(fin);
}
}));
我已经检查了stackoverflow中的现有问题,但我发现它很有希望:Skipping header rows - is it possible with Cloud DataFlow?
任何帮助?
编辑:我尝试了类似下面的内容并且有效:
PCollection<String> financeobj = p.apply(TextIO.read().from("gs://google-bucket/final_input/Financials123.csv"));
PCollection<ClassFinance> pojos5 = financeobj.apply(ParDo.of(new DoFn<String, ClassFinance>() { // converting String into classtype
private static final long serialVersionUID = 1L;
@ProcessElement
public void processElement(ProcessContext c) {
String[] strArr2 = c.element().split(",");
String header = Arrays.toString(strArr2);
ClassFinance fin = new ClassFinance();
if(header.contains("Beneficiary"))
System.out.println("Header");
else {
fin.setBeneficiaryFinance(strArr2[0].trim());
fin.setCatlibCode(strArr2[1].trim());
fin.setrNR(Double.valueOf(strArr2[2].trim().replace("", "0")));
fin.setrNCS(Double.valueOf(strArr2[3].trim().replace("", "0")));
fin.setrCtb(Double.valueOf(strArr2[4].trim().replace("", "0")));
fin.setrAC(Double.valueOf(strArr2[5].trim().replace("", "0")));
c.output(fin);
}
}
}));
答案 0 :(得分:2)
此代码对我有用。我已经使用Filter.by()从csv文件中过滤出标题行。
static void run(GcsToDbOptions options) {
Pipeline p = Pipeline.create(options);
// Read the CSV file from GCS input file path
p.apply("Read Rows from " + options.getInputFile(), TextIO.read()
.from(options.getInputFile()))
// filter the header row
.apply("Remove header row",
Filter.by((String row) -> !((row.startsWith("dwid") || row.startsWith("\"dwid\"")
|| row.startsWith("'dwid'")))))
// write the rows to database using prepared statement
.apply("Write to Auths Table in Postgres", JdbcIO.<String>write()
.withDataSourceConfiguration(JdbcIO.DataSourceConfiguration.create(dataSource(options)))
.withStatement(INSERT_INTO_MYTABLE)
.withPreparedStatementSetter(new StatementSetter()));
PipelineResult result = p.run();
try {
result.getState();
result.waitUntilFinish();
} catch (UnsupportedOperationException e) {
// do nothing
} catch (Exception e) {
e.printStackTrace();
}}
答案 1 :(得分:1)
您分享的旧版Stack Overflow帖子( Skipping header rows - is it possible with Cloud DataFlow? )确实包含您问题的答案。
Apache Beam SDK中的此选项目前不可用,但Apache Beam JIRA问题跟踪器BEAM-123中有开放功能请求。请注意,在编写时,此功能请求仍处于打开状态且尚未解决,并且已经存在2年了。但是,看起来在这个意义上已经做了一些努力,问题的最新更新是从2018年2月开始,所以我建议你保持对JIRA问题的最新更新,因为它最后移到了{{1}组件,它可能会得到更多关注。
考虑到这些信息,我会说您正在使用的方法(在将文件上传到GCS之前删除标题)是您的最佳选择。我不会手动操作,因为您可以轻松编写脚本并自动执行删除标题⟶上传文件过程。
<强> 编辑: 强>
我已经能够使用sdk-java-core
提出一个简单的过滤器。它可能不是最优雅的解决方案(我自己不是Apache Beam专家),但它确实有效,您可以根据自己的需要进行调整。它要求您事先知道正在上传的CSV文件的标题(因为它将按元素内容进行过滤),但同样,请将此视为您可以根据需要修改的模板:
DoFn
答案 2 :(得分:-2)
https://medium.com/@baranitharan/the-textio-write-1be1c07fbef0 数据流中的TextIO.Write现在具有withHeader函数,用于向数据添加标题行。此功能已在版本 1.7.0 中添加。
因此,您可以像这样在csv中添加标头:
TextIO.Write.named("WriteToText")
.to("/path/to/the/file")
.withHeader("col_name1,col_name2,col_name3,col_name4")
.withSuffix(".csv"));
withHeader函数自动在标题行的末尾添加换行符。