PIG UDF (Python) 字符集编码
PIG UDF (Python) Charset Encoding
我是编写 Python 和 Pig UDF 的初学者,并且正在努力使用 PIG 对输入文件进行字符集转换。
浏览了 Whosebug 和整个互联网几天,尝试了很多不同的东西,但我仍然无能为力。
希望有人能轻轻地把我推向正确的方向。
环境:真正的分布式 Hadoop 集群(无本地实例)/ Cloudera 配置 utf-8
和 Apache 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在他的回答中提到的,这里的重要部分是将您的字段定义为字节数组。
我是编写 Python 和 Pig UDF 的初学者,并且正在努力使用 PIG 对输入文件进行字符集转换。
浏览了 Whosebug 和整个互联网几天,尝试了很多不同的东西,但我仍然无能为力。
希望有人能轻轻地把我推向正确的方向。
环境:真正的分布式 Hadoop 集群(无本地实例)/ Cloudera 配置 utf-8
和 Apache 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在他的回答中提到的,这里的重要部分是将您的字段定义为字节数组。