У меня есть случай, когда у меня есть фрейм данных ниже
`scala> res1.printSchema
root
|-- REC: binary (nullable = true)
scala> res1.show(1,false)
+----------------------+
|REC |
+----------------------+
|[75 00 01 00 4C 12 10]|
+----------------------+`
Теперь мое требование — получить строку «75 00 01 00 4C 12 10» из двоичного типа. Пожалуйста помоги.
Я попытался получить mkString(" "), но, похоже, он конвертируется в стандартный asci, но мне нужны буквально двоичные файлы в виде строки как "75 00 01 00 4C 12 10"
Возможно, вам просто нужен шестнадцатеричный код, но если вам действительно нужны пробелы, тогда:
val df = sparkSession.sql("select cast('i am text' as binary) bytes")
df.show
val castedToString = df.selectExpr("cast(bytes as string) casted")
castedToString.show
val hexed = df.selectExpr("hex(bytes) hexString")
hexed.show
val prettyString = hexed.selectExpr("rtrim(regexp_replace(hexString,'(.{2})', '$1 ')) perToPrettyString")
prettyString.show
дает:
+--------------------+
| bytes|
+--------------------+
|[69 20 61 6D 20 7...|
+--------------------+
+---------+
| casted|
+---------+
|i am text|
+---------+
+------------------+
| hexString|
+------------------+
|6920616D2074657874|
+------------------+
+--------------------+
| perToPrettyString|
+--------------------+
|69 20 61 6D 20 74...|
+--------------------+
Последнее выражение заменяет каждые два символа сами по себе и дополнительный пробел, а затем удаляет последний конечный пробел.
Подробности:
Когда Spark выполняет «.show», каждый столбец принудительно обрабатывается новым внутренним выражением ToPrettyString, которое по умолчанию, унаследованное от ToStringBase, преобразует двоичный код в шестнадцатеричный (через SparkStringUtils.getHexString), заключая его в квадратные скобки.
bytes.map("%02X".format(_)).mkString("[", " ", "]")
Cast переопределяет это значение по умолчанию:
override protected def useHexFormatForBinary: Boolean = false
Функция hex sql вызывает Hex.hex:
def hex(bytes: Array[Byte]): UTF8String = {
val length = bytes.length
val value = new Array[Byte](length * 2)
var i = 0
while (i < length) {
value(i * 2) = Hex.hexDigits((bytes(i) & 0xF0) >> 4)
value(i * 2 + 1) = Hex.hexDigits(bytes(i) & 0x0F)
i += 1
}
UTF8String.fromBytes(value)
}
Вы также можете вызвать эту функцию с помощью udf и, вероятно, должны это сделать, если важна производительность вместо использования регулярного выражения.
Пробовали ли вы использовать функцию
cast
в столбцеREC
[.withColumn("result", $"REC".cast("string"))
]?