PIG UDF (Python) 字符集编码

PIG UDF (Python) Charset Encoding

我是编写 Python 和 Pig UDF 的初学者,并且正在努力使用 PIG 对输入文件进行字符集转换。

浏览了 Whosebug 和整个互联网几天,尝试了很多不同的东西,但我仍然无能为力。

希望有人能轻轻地把我推向正确的方向。


环境:真正的分布式 Hadoop 集群(无本地实例)/ Cloudera 配置 utf-8Apache Pig version 0.12.0

我的源文件使用 iso-8859-1 编码,目标是将其内容存储为 utf-8(在 pig 中的其他几个操作之后或之前)。

输入文件如下所示(几个 ASCII/iso-8859-1 个字符用于测试目的 - 每行一个字符):

ù
û
ü
ÿ
à
â
æ
ç
é
è
ê
ë
î
ô

这是我的 Pig 脚本:

RMF $output;

REGISTER 'charsetConversion.py' using org.apache.pig.scripting.jython.JythonScriptEngine AS pyudf;

data = LOAD '$input' USING PigStorage() AS (col1:chararray); --col1:bytearray

final = foreach data generate [=12=], pyudf.toUTF8(col1);

STORE final INTO '$output' USING PigStorage();

还有我的UDF(写在python):

#!/usr/bin/env python
# charsetConversion.py

@outputSchema("word:chararray")
def toUTF8(s):
    return unicode(s, 'iso-8859-1').encode('utf-8')

在 running/submitting 脚本之后我得到以下输出:

� �
� �
� �
� �
� �
� �
� �
� �
� �
� �
� �
� �
� �
� �
� �
� �
� �
� �
� �
� �
� �

在第二列中,我希望与输入文件中的可读值相同,而不是 �

这里发生了什么?

完全推荐我的方法吗?

还有哪些其他方法(没有 java Whosebug: Encoding in Pig - Java solution)?

在此先感谢您的建议。

我正在解决类似的问题。 是的,字符编码在 Java/Hadoop 世界中可能很棘手 :).

实际上,您已经很接近了 - 解决方案是:

data = LOAD '$input' USING PigStorage() AS (col1:bytearray);

问题是您将 col1 指定为字符数组。字符数组是 "a array (string) in Unicode UTF-8 format"。但是,对于 iso-8859-1 中的输入数据,情况并非如此。 pig 脚本将您的数据解释为 UTF-8 instead of iso-8859-1。您应该改为指定 bytearray。 Bytearray 不以任何方式解释数据 - 你必须这样做(例如在你的 UDF 函数中)。

接下来,我们需要处理每一行:

parsed = foreach a generate flatten(my.testparser([=11=]));

然后,在 UDF 函数 (my.testparser()) 中,我们将 iso-8859-1 编码更改为 utf-8:

  ....
  val line:String = input.get(0).asInstanceOf[DataByteArray].get(), "windows-1250")
  ....

代码在 scala 中(我不是 python 人 - 抱歉),它需要输入 DataByteArray (bytearray 在 PIG 中)并获取 Scala.Bytes 的数组。这些字节随后被解释为 windows-1250。

也就是说,您的 UDF 应该保持不变,但输入需要更改为 Pig 中的 bytearray 和 UDF 中的等效数据类型

希望对您有所帮助

下面是 Python 中定义的 UDF,它适用于那些不熟悉 Scala 的人:

#!/usr/bin/env python
# charsetConversion.py
import struct

@outputSchema("word:chararray")
def toUTF8(s):
        line = ‘.’join([struct.pack(‘B’, x).decode(‘iso-8859-1’) for x in s])
        return line

以下是 PIG 命令,用于注册 UDF、加载数据、将 UDF 应用于数据,并获取该数据的样本以检查解码是否按预期工作。

REGISTER 'charsetConversion.py' USING org.apache.pig.scripting.jython.JythonScriptEngine AS pyudf;
data = LOAD '$input' USING TextLoader AS (col1: bytearray);
final = FOREACH data GENERATE [=11=],pyudf.toUTF8(col1);
final_lim = LIMIT final 10;
DUMP final_lim;

正如xhudik在他的回答中提到的,这里的重要部分是将您的字段定义为字节数组。