将具有多个字符定界符的单个字符串文本文件插入spark数据帧

时间:2018-10-07 19:04:56

标签: apache-spark

新的火花,我正在学习。我有一个很大的文本文件,其列由“ |||||”分隔我想插入spark数据框。但是,该文件只是一个字符串。该文件如下所示:

col1|||||col2|||||col3|||||col4|||||col5|||||col1|||||col2|||||col3...

因此,第1列至第5列实际上只是在一行中循环。我尝试在每第5个“ |||||”之后插入新行通过以下命令使用sed命令:

 sed -r 's/([^|||||]*|||||){5}/&\n/g'

哪个工作最多,但由于某种原因最终最终无法正常工作。我怀疑col4(这是一个巨大的文本字段)在此方面引起一些问题,但我对其执行原因的了解还不够。

现在,当我通过以下方式将单行文本文件读取到spark中时:

val df = spark.read.textFile(file) 

这会将所有内容都放在一列中,我想将其分成5列,并让数据帧每5列“包装”字符串。

我的目标是将其变成这样:

+--------------------+---------------+--------------------+--------------------+--------------------+
|                col1|           col2|                col3|                col4|                col5|
+--------------------+---------------+--------------------+--------------------+--------------------+
|                 val|            val|                 val|                 val|                 val|
|                 val|            val|                 val|                 val|                 val|
+--------------------+---------------+--------------------+--------------------+--------------------+

所以我的问题是:由于我的文件只是一个大字符串,是否有办法让数据框在5列之后输入新记录/行?

2 个答案:

答案 0 :(得分:0)

这是您第一个问题的解决方案。 通常,您将其阅读为常规文本文件,然后使用split方法将行转换为列。

df.withColumn("tmp", split($"value", "|||||")).select(
  $"tmp".getItem(0).as("first"),
  $"tmp".getItem(1).as("second"),
  $"tmp".getItem(2).as("third")
).drop("tmp")

第二个问题。您可以使用此正则表达式来匹配模式:

  

(([[a-z0-9A-Z] +)(\ | \ | \ || \ | \ ||)([a-z0-9A-Z] +)(\ | \ | \ || \\\\ |)([a-z0-9A-Z] +)(\ | \ | \ || \ | \ ||)([a-z0-9A-Z] +)(\ | \ | \\ | \\\\ |) )

如果有足够的内存,您可以读取所有文件,然后使用此模式提取文件的各个部分。

如果没有,则必须逐字节读取它,看看是否与该模式匹配。

祝你好运!

答案 1 :(得分:0)

如果文件很大,只有一行,则使用Perl解决方案。 Perl变量可以存储文件内容(甚至以GB为单位),并且您可以轻松管理。您可以在perl本身中进行所有预处理。看看下面的内容是否对您有用

Domain-Driven Design

将上面的输出重定向到另一个csv文件。现在,您可以将spark.csv作为5列的常规csv文件阅读