如何将二进制字符串转换为spark scala中的scala字符串

时间:2017-08-02 22:08:43

标签: string scala apache-spark spark-dataframe

我正在读一个包含二进制字符串字段的avro文件,我需要将其转换为java.lang.string以将其传递给另一个库(spark-xml-util),如何将其转换为java .lang.string有效。这是我到目前为止的代码: -

    val df = sqlContext.read.format("com.databricks.spark.avro").load("filePath/fileName.avro")
    df.select("myField").collect().mkString

最后一行给出了以下例外: -

Exception in thread "main" java.lang.ClassCastException: [B cannot be cast to java.lang.String
    at org.apache.spark.sql.Row$class.getString(Row.scala:255)
    at org.apache.spark.sql.catalyst.expressions.GenericRow.getString(rows.scala:165)

df架构是: -

root
|-- id: string (nullable = true)
|-- myField: binary (nullable = true)

3 个答案:

答案 0 :(得分:3)

现在考虑API的状态(2.2.0),最好的方法是创建一个UDF来做这个并替换列:

import org.apache.spark.sql.functions.udf
val toString = udf((payload: Array[Byte]) => new String(payload))
df.withColumn("myField", toString(df("myField")))

或者如果您似乎暗示数据是使用GZIP压缩的,您可以:

import org.apache.spark.sql.functions.udf
val toString = udf((payload: Array[Byte]) => {
  val inputStream = new GZIPInputStream(new ByteArrayInputStream(payload))
  scala.io.Source.fromInputStream(inputStream).mkString
})
df.withColumn("myField", toString(df("myField")))

答案 1 :(得分:0)

在先前的解决方案中,代码new String(payload)对真正的二进制数据不起作用。

最终,解决方案要复杂得多,所需二进制数据的长度作为第二个参数。

def binToString(payload: Array[Byte], payload_length: Int): String = {
  val ac: Array[Char] = Range(0,payload_length).map(i => payload(i).toChar).toArray
  return ac.mkString 
}

val binToStringUDF = udf( binToString(_: Array[Byte], _: Int): String )

答案 2 :(得分:0)

在Spark 3.0中,您可以在BINARY和STRING数据之间进行转换。

scala> val df = sc.parallelize(Seq("ABC", "BCD", "CDE", "DEF")).toDF("value")
df: org.apache.spark.sql.DataFrame = [value: string]

scala> df.select($"value", $"value".cast("BINARY"), 
$"value".cast("BINARY").cast("STRING")).show()
+-----+----------+-----+
|value|     value|value|
+-----+----------+-----+
|  ABC|[41 42 43]|  ABC|
|  BCD|[42 43 44]|  BCD|
|  CDE|[43 44 45]|  CDE|
|  DEF|[44 45 46]|  DEF|
+-----+----------+-----+

我没有要测试的数据,但是您应该可以:

df.select($"myField".cast("STRING"))

这显然取决于实际数据(即,不要将JPEG转换为STRING),但假设它是UTF-8编码的,就可以了。