首页 文章

Apache Hive:如何使用Unicode字符(八进制高于177)作为字段分隔

提问于
浏览
2

在我们的用例中,我们得到的UTF-8文本数据格式如下:

Data1§Data2
Data3§Data4

现在我们希望将Data1和Data3放在一个列中,Data2和Data4放在Apache Hive的一列中 . 听起来很简单 .

但是,我们无法将§字符(即unicode U 00A7 "Section Sign"参见here)指定为字段分隔符 .

我们尝试了以下方法,没有任何结果可以达到 .

1)使用通过接近终止的正常字段

ROW FORMAT DELIMITED FIELDS TERMINATED BY '§'

返回(注意附加到每个单元格的?,在其他客户端中注明未识别标志的unicode标志)

+--------------------+--------------------+--+
| test.column1       | test.column2          |
+--------------------+--------------------+--+
| Data1?             | Data2?                |
| Data3?             | Data4?                |
+--------------------+--------------------+-

或八进制表示

ROW FORMAT DELIMITED FIELDS TERMINATED BY '\247'

要么

ROW FORMAT DELIMITED FIELDS TERMINATED BY '\304\247'

返回:

+--------------------+--------------------+--+
| test.column1       | test.column2          |
+--------------------+--------------------+--+
| Data1?Data2        | NULL                  |
| Data3?Data4        | NULL                  |
+--------------------+--------------------+--+

2)使用RegexSerDe

ROW FORMAT SERDE 'org.apache.hadoop.hive.contrib.serde2.RegexSerDe'
WITH SERDEPROPERTIES (
"input.regex" = "^([^\\]]+)\\\247([^\\]]+)$")

(将字段分隔符更改为/在某些测试源数据中并使用\ 057(八进制为/)会产生正确的结果,但更改源数据对我们来说是不可行的 . )

要么

ROW FORMAT SERDE 'org.apache.hadoop.hive.contrib.serde2.RegexSerDe'
WITH SERDEPROPERTIES (
"input.regex" = "^([^\\]]+)\\$([^\\]]+)$")

(在描述格式化的表语句中,这会产生:

input.regex  ^([^\\]]+)\\\uFFFD\uFFFD([^\\]]+)$

其中\ uFFFD是未识别标志的unicode表示)

SELECT的结果总是一样的:

+--------------------+--------------------+--+
| test.column1       | test.column2          |
+--------------------+--------------------+--+
| NULL               | NULL                  |
| NULL               | NULL                  |
+--------------------+--------------------+--+

My research so far indicates the following:

1)Hive无法使用不可打印的ASCII字符,其中的八进制数高于177.在github上的其他一些代码here中,我的意外指向令我惊讶的是:

Hive可以在'\ ooo'形式中指定分隔符,其中ooo是介于000和177之间的三位八进制数 .

2)此外,我发现证据表明只有一个字节的字符可以用作BigSQL文档中的字段分隔here(但不在官方文档中),它说:

分隔符必须是单字节字符

至于我的研究§(unicode U 00A7)是一个2字节的字符(11000010:10100111)

Does this mean I can not use this delimiter or is there any other ways to use it?

小更新,如果这仍然没有解决,有人需要它:

我尝试了以下方法将数据暂存为单列表,然后将§转换为(逗号),然后用逗号分隔 . 这适用于小样本数据,但对于具有错误的200列的较大 生产环境 表失败 .

select
split(a.textcolumn, '\\,')[0] as column1
,split(a.textcolumn, '\\,')[1] as column2
from
(select translate(textcolumn, '§', ',') as textcolumn from database.stage) a;

这是错误:

SQL错误:java.io.IOException:org.apache.hadoop.hive.ql.metadata.HiveException:错误评估translate(stagingstring,'§',';')java.io.IOException:org.apache.hadoop.hive .ql.metadata.HiveException:错误评估translate(stagingstring,'§',';')java.io.IOException:org.apache.hadoop.hive.ql.metadata.HiveException:错误评估translate(stagingstring,'§' ,';')org.apache.hadoop.hive.ql.metadata.HiveException:错误评估translate(stagingstring,'§',';')org.apache.hadoop.hive.ql.metadata.HiveException:错误评估翻译(stagingstring,'§',';')java.lang.IllegalArgumentException:null

更新2:

上面的方法有效,但如果源数据不干净(有其他UTF-8问题),它将抛出上述错误 .

3 回答

  • 1

    你需要创建你的表

    Fields Terminated by '-89'

    'section sign'的DECIMAL代码是167 .

    167 - 256 = -89
    

    这个-89应该是你的分隔符 . Hive允许分隔符在-127到127之间 .

    有关Cloudera的以下片段的进一步阅读 .

    https://www.cloudera.com/documentation/enterprise/5-8-x/topics/impala_create_table.html

    注意:CREATE TABLE子句FIELDS TERMINATED BY,ESCAPED BY和LINES TERMINATED BY对用于其参数的字符串文字具有特殊规则,因为它们都需要单个字符 . 您可以使用由单引号或双引号括起来的常规字符,八进制序列(如'\054'(表示逗号))或'-127' .. '128'范围内的整数(带引号但没有反斜杠),这被解释为单字节ASCII字符 . 从256减去负值;例如,FIELDS TERMINATED BY '-2'将字段分隔符设置为ASCII代码254,"Icelandic Thorn"字符用作某些数据格式的分隔符 .

  • 0

    答案是我对上述问题的更新 . 但是,如果数据不干净或包含我发现的其他有问题的字符,这将抛出错误 .

  • 1

    我知道这是一个很冷的案例,但是这个问题可以用MultiDelimitSerDe来解决 .

    实际上,Hive默认SerDe(称为LazySimpleSerDe)仅支持单字节分隔符 . 正如alpcoder所说,这没有记录 . 你需要阅读源代码来计算它 .

    MultiDelimitSerDe旨在支持多字符分隔符 . 幸运的是,它支持任何多字节字符 .

相关问题