在我们的用例中,我们得到的UTF-8文本数据的格式如下:
Data1§Data2
Data3§Data4现在,我们希望将Data1和Data3放在一列中,Data2和Data4放在Apache的一列中。听起来很简单。
但是,我们不能将§字符(即unicode U+00A7“区段符号”(参见这里) )指定为字段分隔符。
我们尝试了以下方法,但没有取得可接受的结果。
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表示)
选择的结果总是相同的:
+--------------------+--------------------+--+
| test.column1 | test.column2 |
+--------------------+--------------------+--+
| NULL | NULL |
| NULL | NULL |
+--------------------+--------------------+--+到目前为止,我的研究表明:
1) Hive不能使用非打印的ASCII字符,这些字符的八进制数高于177。在github上的其他代码这里中,指向这一点的指针让我感到惊讶,因为github是这样写的:
胞可以在窗体'\ ooo‘中指定分隔符字符,其中ooo是介于000到177之间的三位八进制数字。
2)此外,我还发现证据表明,在这里的文档中(但在正式文档中),只有一个字节的字符可以用作字段标记,其中写道:
分隔符必须是单字节字符。
就我的研究而言,§(unicode U+00A7)是一个2字节字符(11000010:10100111)。
,这是否意味着我不能使用这个分隔符,或者有没有其他方法来使用它?
小更新,如果这个问题仍未解决,并且有人需要它:
我尝试了以下方法:将数据作为一列表进行暂存,然后将§转换为(逗号),然后再用逗号将其拆分。这适用于小样本数据,但对于我的大型生产表(包含有错误的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 : org.apache.hadoop.hive.ql.metadata.HiveException:错误计算翻译(stagingstring,'§',';‘’) java.io.IOException: org.apache.hadoop.hive.ql.metadata.HiveException:错误计算翻译(stagingstring,'§',‘;’java.io.IOException: org.apache.hadoop.hive.ql.metadata.HiveException:错误计算翻译(stagingstring,'§',‘§’,‘§’,‘§’,‘§’,‘§’);') org.apache.hadoop.hive.ql.metadata.HiveException:错误求值转换(stagingstring,'§',';') org.apache.hadoop.hive.ql.metadata.HiveException:Error计算转换(stagingstring,'§',';') java.lang.IllegalArgumentException: null
更新2:
上述方法有效,但如果源数据不干净(有其他UTF-8问题),则会抛出上述错误。
发布于 2016-11-11 07:55:53
答案在我对上述问题的更新中。但是,如果数据不干净,或者包含我找到的其他有问题的字符,这将引发错误。
发布于 2017-07-21 20:38:37
您需要用
Fields Terminated by '-89'
“分段符号”的十进制代码是167。
167 - 256 = -89这个-89应该是你的分隔符。蜂巢允许分隔符在-127到127之间。
有关进一步阅读以下片段从Cloudera。
注意: CREATE子句字段终止于,转义为,行结束时具有用于其参数的字符串文字的特殊规则,因为它们都需要一个字符。您可以使用由单引号或双引号包围的常规字符、八进制序列(如'\054‘(表示逗号))或范围'-127'..'128’(带有引号但没有反斜杠)的整数,它被解释为单字节ASCII字符。从256中减去负值;例如,以'-2‘结尾的字段将字段分隔符设置为ASCII代码254,这是一些数据格式用作分隔符的“冰岛Thorn”字符。
发布于 2017-12-11 09:17:49
我知道这有点冷,但是这个问题可以用MultiDelimitSerDe来解决。
实际上,Hive默认SerDe (称为LazySimpleSerDe)只支持单字节分隔符。正如声码器所说,这还没有记录在案。您需要阅读源代码才能理解它。
MultiDelimitSerDe被设计为支持多字符分隔符.幸运的是,它支持任何多字节字符.
https://stackoverflow.com/questions/40461000
复制相似问题