Apache spark Spark:使用与新行不同的分隔符读取文件

Apache spark Spark:使用与新行不同的分隔符读取文件,apache-spark,Apache Spark,我正在使用ApacheSpark1.0.1。我有许多文件是用UTF8\u0001分隔的,而不是通常的新行\n分隔的。如何在Spark中读取此类文件?也就是说,sc.textfile(“hdfs:///myproject/*“是\n,我想将其更改为\u0001您可以使用textinputformat.record.delimiter设置textinputformat的分隔符,例如 import org.apache.hadoop.conf.Configuration import org.apac

我正在使用ApacheSpark1.0.1。我有许多文件是用UTF8
\u0001
分隔的,而不是通常的新行
\n
分隔的。如何在Spark中读取此类文件?也就是说,
sc.textfile(“hdfs:///myproject/*“
\n
,我想将其更改为
\u0001

您可以使用
textinputformat.record.delimiter
设置
textinputformat
的分隔符,例如

import org.apache.hadoop.conf.Configuration
import org.apache.hadoop.mapreduce.Job
import org.apache.hadoop.io.{LongWritable, Text}
import org.apache.hadoop.mapreduce.lib.input.TextInputFormat

val conf = new Configuration(sc.hadoopConfiguration)
conf.set("textinputformat.record.delimiter", "X")
val input = sc.newAPIHadoopFile("file_path", classOf[TextInputFormat], classOf[LongWritable], classOf[Text], conf)
val lines = input.map { case (_, text) => text.toString}
println(lines.collect)
例如,我的输入是一个包含一行的文件
aXbXcXd
。将输出上述代码

Array(a, b, c, d)

在Spark shell中,我根据以下公式提取数据:

$spark shell
...
scala>import org.apache.hadoop.io.LongWritable
导入org.apache.hadoop.io.LongWritable
scala>import org.apache.hadoop.io.Text
导入org.apache.hadoop.io.Text
scala>import org.apache.hadoop.conf.Configuration
导入org.apache.hadoop.conf.Configuration
scala>import org.apache.hadoop.mapreduce.lib.input.TextInputFormat
导入org.apache.hadoop.mapreduce.lib.input.TextInputFormat
scala>val conf=新配置
conf:org.apache.hadoop.conf.Configuration=Configuration:core-default.xml、core-site.xml、mapred-default.xml、mapred-site.xml、warn-default.xml、warn-site.xml
scala>conf.set(“textinputformat.record.delimiter”,“\u0001”)
scala>val data=sc.newAPIHadoopFile(“mydata.txt”,classOf[TextInputFormat],classOf[LongWritable],classOf[Text],conf).map(u.\u 2.toString)
数据:org.apache.spark.rdd.rdd[(org.apache.hadoop.io.LongWritable,org.apache.hadoop.io.Text)]=NewHadoopRDD[0]位于newAPIHadoopFile:19

sc.newapiHadoop文件(“mydata.txt”,…)
是一个
RDD[(LongWritable,Text)]
,其中元素的第一部分是起始字符索引,第二部分是python中由
“\u0001”
分隔的实际文本。这可以通过以下方法实现:

rdd = sc.newAPIHadoopFile(YOUR_FILE, "org.apache.hadoop.mapreduce.lib.input.TextInputFormat",
            "org.apache.hadoop.io.LongWritable", "org.apache.hadoop.io.Text",
            conf={"textinputformat.record.delimiter": YOUR_DELIMITER}).map(lambda l:l[1])

以下是适用于Scala用户的“s”和“s答案”的现成版本,可通过以下方式使用:

sc.textFile(“some/path.txt”,“u0001”)
下面的代码段使用
隐式类创建了一个附加的
textFile
方法,该方法隐式附加到
SparkContext
(以复制
SparkContext
的默认
textFile
方法):

package.com
导入org.apache.spark.SparkContext
导入org.apache.spark.rdd.rdd
导入org.apache.hadoop.conf.Configuration
导入org.apache.hadoop.io.{LongWritable,Text}
导入org.apache.hadoop.mapreduce.lib.input.TextInputFormat
物体火花{
隐式类contextensions(val sc:SparkContext)扩展了AnyVal{
def文本文件(
路径:字符串,
分隔符:字符串,
maxRecordLength:String=“1000000”
):RDD[String]={
val conf=新配置(sc.hadoopConfiguration)
//此配置设置记录分隔符:
conf.set(“textinputformat.record.delimiter”,delimiter)
//这一条限制了一条记录的大小:
conf.set(“mapreduce.input.linerecordreader.line.maxlength”,maxRecordLength)
sc.newapiHadoop文件(
路径
classOf[TextInputFormat],classOf[LongWritable],classOf[Text],
形态
)
.map{case({,text)=>text.toString}
}
}
}
可以这样使用:

import com.whatever.Spark.contextensions
sc.textFile(“some/path.txt”,“\u0001”)

请注意额外的设置
mapreduce.input.linerecordreader.line.maxlength
,它限制了记录的最大大小。当从损坏的文件中读取一条记录可能太长而无法放入内存时(使用记录分隔符时发生这种情况的可能性更大),这一点非常方便


使用此设置,当读取损坏的文件时,将抛出异常(
java.io.IOException
-因此可捕获),而不是从内存中取出一个乱七八糟的文件,从而停止SparkContext。

如果您使用的是spark上下文,下面的代码对我有帮助
sc.hadoopConfiguration.set(“textinputformat.record.delimiter”、“delimeter”)

当我在spark shell中运行上述代码时,我收到以下错误:scala>val job=new job(sc.hadoopConfiguration)警告:有1个弃用警告;使用-depredition重新运行java.lang.IllegalStateException:作业处于状态定义而不是运行在org.apache.hadoop.mapreduce.Job.EnsureRate(Job.java:283)如何修复此“java.lang.IllegalStateException:作业处于状态定义而不是运行”问题?能否将完整堆栈轨迹粘贴到某个位置并提供链接?
rdd = sc.newAPIHadoopFile(YOUR_FILE, "org.apache.hadoop.mapreduce.lib.input.TextInputFormat",
            "org.apache.hadoop.io.LongWritable", "org.apache.hadoop.io.Text",
            conf={"textinputformat.record.delimiter": YOUR_DELIMITER}).map(lambda l:l[1])