使用JAVA api读取HDFS文件乱码踩坑

想写一个读取HFDS上的部分文件数据做预览的接口,根据网上的博客实现后,发现有时读取信息会出现乱码,例如读取一个csv时,字符串之间被逗号分割

  • 英文字符串aaa,能正常显示

  • 中文字符串“你好”,能正常显示

  • 中英混合字符串如“aaa你好”,出现乱码

查阅了众多博客,解决方案大概都是:使用xxx字符集解码。抱着不信的想法,我依次尝试,果然没用。

解决思路

因为HDFS支持6种字符集编码,每个本地文件编码方式又是极可能不一样的,我们上传本地文件的时候其实就是把文件编码成字节流上传到文件系统存储。那么在GET文件数据时,面对不同文件、不同字符集编码的字节流,肯定不是一种固定字符集解码就能正确解码的吧。

那么解决方案其实有两种

  • 固定HDFS的编解码字符集。比如我选用UTF-8,那么在上传文件时统一编码,即把不同文件的字节流都转化为UTF-8编码再进行存储。这样的话在获取文件数据的时候,采用UTF-8字符集解码就没什么问题了。但这样做的话仍然会在转码部分存在诸多问题,且不好实现。

  • 动态解码。根据文件的编码字符集选用对应的字符集对解码,这样的话并不会对文件的原生字符流进行改动,基本不会乱码。

我选用动态解码的思路后,其难点在于如何判断使用哪种字符集解码。

好在看到了一篇博客

https://blog.csdn.net/smallnetvisitor/article/details/84682867

Google提供了检测字节流编码方式的包。那么方案就很明了了,先读一些文件字节流,用工具检测编码方式,再对应进行解码即可。

具体代码

pom

<dependency>
<groupId>net.sourceforge.jchardet</groupId>
<artifactId>jchardet</artifactId>
<version>1.0</version>
</dependency>

从HDFS读取部分文件做预览的逻辑

    // 获取文件的部分数据做预览
public List<String> getFileDataWithLimitLines(String filePath, Integer limit) {
FSDataInputStream fileStream = openFile(filePath);
return readFileWithLimit(fileStream, limit);
} // 获取文件的数据流
private FSDataInputStream openFile(String filePath) {
FSDataInputStream fileStream = null;
try {
fileStream = fs.open(new Path(getHdfsPath(filePath)));
} catch (IOException e) {
logger.error("fail to open file:{}", filePath, e);
}
return fileStream;
} // 读取最多limit行文件数据
private List<String> readFileWithLimit(FSDataInputStream fileStream, Integer limit) {
byte[] bytes = readByteStream(fileStream);
String data = decodeByteStream(bytes);
if (data == null) {
return null;
} List<String> rows = Arrays.asList(data.split("\\r\\n"));
return rows.stream().filter(StringUtils::isNotEmpty)
.limit(limit)
.collect(Collectors.toList());
} // 从文件数据流中读取字节流
private byte[] readByteStream(FSDataInputStream fileStream) {
byte[] bytes = new byte[1024*30];
int len;
ByteArrayOutputStream stream = new ByteArrayOutputStream();
try {
while ((len = fileStream.read(bytes)) != -1) {
stream.write(bytes, 0, len);
}
} catch (IOException e) {
logger.error("read file bytes stream failed.", e);
return null;
}
return stream.toByteArray();
} // 解码字节流
private String decodeByteStream(byte[] bytes) {
if (bytes == null) {
return null;
} String encoding = guessEncoding(bytes);
String data = null;
try {
data = new String(bytes, encoding);
} catch (Exception e) {
logger.error("decode byte stream failed.", e);
}
return data;
} // 根据Google的工具判别编码
private String guessEncoding(byte[] bytes) {
UniversalDetector detector = new UniversalDetector(null);
detector.handleData(bytes, 0, bytes.length);
detector.dataEnd();
String encoding = detector.getDetectedCharset();
detector.reset(); if (StringUtils.isEmpty(encoding)) {
encoding = "UTF-8";
}
return encoding;
}

使用JAVA API读取HDFS的文件数据出现乱码的解决方案的更多相关文章

  1. Java API 读取HDFS的单文件

    HDFS上的单文件: -bash-3.2$ hadoop fs -ls /user/pms/ouyangyewei/data/input/combineorder/repeat_rec_categor ...

  2. java Api 读取HDFS文件内容

    package dao; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.*; import java ...

  3. Spark:java api读取hdfs目录下多个文件

    需求: 由于一个大文件,在spark中加载性能比较差.于是把一个大文件拆分为多个小文件后上传到hdfs,然而在spark2.2下如何加载某个目录下多个文件呢? public class SparkJo ...

  4. 用java api读取HDFS文件

    import java.io.IOException; import java.io.InputStream; import java.security.PrivilegedExceptionActi ...

  5. JAVA API 实现hdfs文件操作

    java api 实现hdfs 文件操作会出现错误提示: Permission denied: user=hp, access=WRITE, inode="/":hdfs:supe ...

  6. 分享非常有用的Java程序(关键代码)(八)---Java InputStream读取网络响应Response数据的方法!(重要)

    原文:分享非常有用的Java程序(关键代码)(八)---Java InputStream读取网络响应Response数据的方法!(重要) Java InputStream读取数据问题 ======== ...

  7. 使用Java API操作HDFS文件系统

    使用Junit封装HFDS import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.*; import org ...

  8. 使用Java Api 操作HDFS

    如题 我就是一个标题党  就是使用JavaApi操作HDFS,使用的是MAVEN,操作的环境是Linux 首先要配置好Maven环境,我使用的是已经有的仓库,如果你下载的jar包 速度慢,可以改变Ma ...

  9. C#选择多个文件并读取多个文件数据

    原文:C#选择多个文件并读取多个文件数据 版权声明:本文为博主原创文章,转载请附上链接地址. https://blog.csdn.net/ld15102891672/article/details/8 ...

随机推荐

  1. Jenkins从节点上构建自动化测试项目时报错:java.io.IOException: Unexpected termination of the channel

    在mac电脑上配置了Jenkins从节点,在该从节点上构建app UI 自动化测试项目,运行一些用例后报如下错误: java.io.EOFException at java.io.ObjectInpu ...

  2. 《Kafka笔记》1、Kafka初识

    目录 一.初识Kafka 1 apache kafka简介 2 消息中间件kafka的使用场景 2.1 订阅与发布队列 2.2 流处理 3 kafka对数据的管理形式 4 kafka基础架构 5 Ka ...

  3. python坐标获取经纬度或经纬度获取坐标免费模块--geopy

    一.官方文档 https://github.com/geopy/geopy 二.模块安装 pip3 install geopy 三.简单实用 from geopy.geocoders import N ...

  4. Cisco思科模拟器交换机划分VLAN 入门详解 - 精简归纳

    Cisco思科模拟器交换机划分VLAN 入门详解 - 精简归纳 JERRY_Z. ~ 2020 / 10 / 24 转载请注明出处!️ 附: 交流方式: ️ ️ ️ QQ: 1846334075 We ...

  5. 团体程序设计天梯赛-练习集 L1-007 念数字

    - - ->博主推荐,学生党.程序员必备,点击查看- - - >>>>> 热门文章推荐 以下50道算法编程题访问量较大,包含常用语法,数据结构,解题思路等等,作为C ...

  6. 【Flutter 面试】main入口函数会被调用几次

    老孟导读:这是一个读者面试时被问到的问题,这个问题前段时间我也在VIP交流群和大家一起探讨过. 这个问题涉及引擎的相关知识,如果不了解相关知识,很难回答正确,因为不管说调用几次都是错误的,下面来看一下 ...

  7. 记一次py交易

    讲一个故事 以下故事真实性不保证(你们懂的) 我没说这个是真的 所以不能当做以后别人挑我刺的证据 我只是讲个故事罢了 故事可以是fake 我不会承认这个故事是真的罢了 朋友是某c9高校工科专业 学校培 ...

  8. 脑桥Brain-Pons

    date: 2014-02-01 15:30:11 updated: 2014-02-01 15:30:11 [一] "2025.7.3.Brain-Pons?Expeiment?Under ...

  9. 必须掌握的分布式文件存储系统—HDFS

    HDFS(Hadoop Distributed File System)分布式文件存储系统,主要为各类分布式计算框架如Spark.MapReduce等提供海量数据存储服务,同时HBase.Hive底层 ...

  10. deconv的弊端

    https://chuansongme.com/n/2630693453218 学习到deconvlution会带来棋盘鬼影,比较重要的解决方法就是resize-deconvlution