HiveServer2 does not return ResultSets in UTF-8 encoding 解决HiveServer2 JDBC显示UTF8乱码的问题

本文介绍如何通过配置Hive启动脚本中的环境变量来解决读取HDFS中非ASCII字符(如中文)时出现乱码的问题。重点在于确保HDFS文件编码与Hive启动时的环境变量一致。
add following env variables in Hive startup script ($HIVE_HOME/bin/hive):

export LANG=en_US.UTF-8
export HADOOP_OPTS="$HADOOP_OPTS -Dfile.encoding=UTF-8"

MapR cluster: /opt/mapr/hive/hive-0.11/bin/hive
Cloudera cluster: /opt/cloudera/parcels/CDH/lib/hive/bin/hive
other Hadoop distribution: /usr/lib/hive/bin/hive (maybe...)

make sure, your data in HDFS are encoded in UTF-8, if not, you should set LANG variable and file.encoding in HADOOP_OPTS as same as the encoding you used for the files in HDFS.

我们通过 Hive JDBC 读数据的时候,如果有非 ascii 字符,比如中文,CJK,之类的,默认情况下很可能是无法正确读取的,要么是乱码,要么是问号。。。

可以通过给hive的启动脚本添加上面两个环境变量解决,不同hadoop发行版的hive启动脚本位置有所不同,上面也列出了。

其实重点就是,你存入HDFS的文件编码要与启动hive,hiveserver2,sqoop之类的这些服务的环境变量相同,可以通过在启动脚本中设置LANG,和在HADOOP_OPTS中指定file.encoding解决。

如果你存入hdfs的文件是UTF8,那就这样设置,如果是GBK之类的,就

export LANG="zh_CN.GBK"
export HADOOP_OPTS="$HADOOP_OPTS -Dfile.encoding=GBK"
### Windows 控制台模式下处理非 UTF-8 字节序列的解决方案 在 Windows 系统中,标准输入输出流(stdio)默认使用代码页(Code Page)来处理字符编码。当尝试写入非 UTF-8 字节序列时,可能会遇到内部错误或不兼容问题[^1]。这是因为 Windows 的控制台子系统在处理非 Unicode 字符时依赖于当前活动的代码页设置。 为了解决这一问题,可以采用以下方法: #### 方法一:更改控制台代码页 通过命令行更改控制台的活动代码页以匹配所需的字符集。例如,如果需要支持简体中文的 GBK 编码,可以运行以下命令: ```cmd chcp 936 ``` 这将切换控制台的代码页到 GBK 编码(代码页 936)。需要注意的是,这种方法仅适用于当前会话,并且可能会影响其他程序的行为[^2]。 #### 方法二:使用宽字符流 为了确保兼容性,可以使用宽字符流(Wide Character Stream)来替代传统的窄字符流(Narrow Character Stream)。这样可以避免因代码页不匹配而导致的错误。以下是实现的一个示例: ```cpp #include <iostream> #include <io.h> #include <fcntl.h> int main() { // 设置控制台输出为宽字符模式 _setmode(_fileno(stdout), _O_U16TEXT); // 输出宽字符串 std::wcout << L"你好,世界!" << std::endl; return 0; } ``` 上述代码通过 `_setmode` 函数将标准输出流设置UTF-16LE 模式,从而支持多语言字符输出[^3]。 #### 方法三:手动转换字节序列 如果必须使用非 UTF-8 字节序列,可以通过手动转换字节序列来解决编码问题。例如,使用 `MultiByteToWideChar` 和 `WideCharToMultiByte` 函数进行编码转换。以下是一个示例: ```cpp #include <windows.h> #include <string> #include <iostream> std::string ConvertToAnsi(const std::wstring& wstr, UINT codePage) { int size = WideCharToMultiByte(codePage, 0, wstr.c_str(), -1, nullptr, 0, nullptr, nullptr); std::string str(size, 0); WideCharToMultiByte(codePage, 0, wstr.c_str(), -1, &str[0], size, nullptr, nullptr); return str; } int main() { std::wstring wstr = L"你好,世界!"; std::string ansiStr = ConvertToAnsi(wstr, CP_ACP); // 使用系统默认的 ANSI 代码页 std::cout << ansiStr << std::endl; return 0; } ``` 此代码片段展示了如何将宽字符串转换为 ANSI 字符串,并指定目标代码页[^4]。 ### 注意事项 - 在修改代码页或使用宽字符流时,需确保应用程序的其余部分能够正确处理这些更改。 - 如果涉及跨平台开发,建议优先使用 Unicode 编码(如 UTF-8UTF-16),以减少潜在的兼容性问题
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值