色综合图-色综合图片-色综合图片二区150p-色综合图区-玖玖国产精品视频-玖玖香蕉视频

您的位置:首頁技術文章
文章詳情頁

JAVA讀取HDFS的文件數(shù)據(jù)出現(xiàn)亂碼的解決方案

瀏覽:3日期:2022-08-21 09:51:08

使用JAVA api讀取HDFS文件亂碼踩坑

想寫一個讀取HFDS上的部分文件數(shù)據(jù)做預覽的接口,根據(jù)網(wǎng)上的博客實現(xiàn)后,發(fā)現(xiàn)有時讀取信息會出現(xiàn)亂碼,例如讀取一個csv時,字符串之間被逗號分割

英文字符串aaa,能正常顯示 中文字符串“你好”,能正常顯示 中英混合字符串如“aaa你好”,出現(xiàn)亂碼

查閱了眾多博客,解決方案大概都是:使用xxx字符集解碼。抱著不信的想法,我依次嘗試,果然沒用。

解決思路

因為HDFS支持6種字符集編碼,每個本地文件編碼方式又是極可能不一樣的,我們上傳本地文件的時候其實就是把文件編碼成字節(jié)流上傳到文件系統(tǒng)存儲。那么在GET文件數(shù)據(jù)時,面對不同文件、不同字符集編碼的字節(jié)流,肯定不是一種固定字符集解碼就能正確解碼的吧。

那么解決方案其實有兩種

固定HDFS的編解碼字符集。比如我選用UTF-8,那么在上傳文件時統(tǒng)一編碼,即把不同文件的字節(jié)流都轉化為UTF-8編碼再進行存儲。這樣的話在獲取文件數(shù)據(jù)的時候,采用UTF-8字符集解碼就沒什么問題了。但這樣做的話仍然會在轉碼部分存在諸多問題,且不好實現(xiàn)。 動態(tài)解碼。根據(jù)文件的編碼字符集選用對應的字符集對解碼,這樣的話并不會對文件的原生字符流進行改動,基本不會亂碼。

我選用動態(tài)解碼的思路后,其難點在于如何判斷使用哪種字符集解碼。參考下面的內容,獲得了解決方案

java檢測文本(字節(jié)流)的編碼方式

需求:

某文件或者某字節(jié)流要檢測他的編碼格式。

實現(xiàn):

基于jchardet

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

代碼如下:

public class DetectorUtils {private DetectorUtils() {} static class ChineseCharsetDetectionObserver implementsnsICharsetDetectionObserver {private boolean found = false;private String result; public void Notify(String charset) {found = true;result = charset;} public ChineseCharsetDetectionObserver(boolean found, String result) {super();this.found = found;this.result = result;} public boolean isFound() {return found;} public String getResult() {return result;} } public static String[] detectChineseCharset(InputStream in)throws Exception {String[] prob=null;BufferedInputStream imp = null;try {boolean found = false;String result = Charsets.UTF_8.toString();int lang = nsPSMDetector.CHINESE;nsDetector det = new nsDetector(lang);ChineseCharsetDetectionObserver detectionObserver = new ChineseCharsetDetectionObserver(found, result);det.Init(detectionObserver);imp = new BufferedInputStream(in);byte[] buf = new byte[1024];int len;boolean isAscii = true;while ((len = imp.read(buf, 0, buf.length)) != -1) {if (isAscii)isAscii = det.isAscii(buf, len);if (!isAscii) {if (det.DoIt(buf, len, false))break;}} det.DataEnd();boolean isFound = detectionObserver.isFound();if (isAscii) {isFound = true;prob = new String[] { 'ASCII' };} else if (isFound) {prob = new String[] { detectionObserver.getResult() };} else {prob = det.getProbableCharsets();}return prob;} finally {IOUtils.closeQuietly(imp);IOUtils.closeQuietly(in);}}}

測試:

String file = 'C:/3737001.xml';String[] probableSet = DetectorUtils.detectChineseCharset(new FileInputStream(file));for (String charset : probableSet) {System.out.println(charset);}

Google提供了檢測字節(jié)流編碼方式的包。那么方案就很明了了,先讀一些文件字節(jié)流,用工具檢測編碼方式,再對應進行解碼即可。

具體解決代碼

pom

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

從HDFS讀取部分文件做預覽的邏輯

// 獲取文件的部分數(shù)據(jù)做預覽 public List<String> getFileDataWithLimitLines(String filePath, Integer limit) { FSDataInputStream fileStream = openFile(filePath); return readFileWithLimit(fileStream, limit); } // 獲取文件的數(shù)據(jù)流 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; } // 讀取最多l(xiāng)imit行文件數(shù)據(jù) 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('rn')); return rows.stream().filter(StringUtils::isNotEmpty) .limit(limit) .collect(Collectors.toList()); } // 從文件數(shù)據(jù)流中讀取字節(jié)流 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(); } // 解碼字節(jié)流 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; } // 根據(jù)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讀取HDFS的文件數(shù)據(jù)出現(xiàn)亂碼的解決方案的詳細內容,更多關于JAVA讀取HDFS的文件亂碼的資料請關注好吧啦網(wǎng)其它相關文章!

標簽: Java
相關文章:
主站蜘蛛池模板: 国产成人综合一区精品 | 欧美成a人免费观看久久 | 国外精品视频在线观看免费 | 美女视频永久黄网站在线观看 | 三级视频中文字幕 | 国产美女自拍视频 | 国产成人精品日本亚洲专一区 | 午夜国产理论 | 亚洲经典在线中文字幕 | 国产高清在线看免费视频观 | 一本色道久久综合亚洲精品加 | 毛片免费视频 | 久久午夜视频 | 日本免费一区二区三区视频 | 在线免费视频国产 | 久草草视频在线观看免费高清 | 男女一级 | 三级国产三级在线 | 永久免费观看午夜视频在线 | 成人亚洲精品7777 | 玖玖爱zh综合伊人久久 | 99在线观看视频免费精品9 | 4tube高清性欧美 | 亚洲a网 | 久久久久国产 | 国产成人综合亚洲一区 | 亚洲成人www | 日本高清毛片视频在线看 | 一本伊大人香蕉高清在线观看 | 亚洲性久久久影院 | a毛片免费观看完整 | 日本精品一区二区三区在线视频 | 日韩亚洲欧美一区二区三区 | 成人做爰视频www在线观看 | 91精品国产91热久久p | 最新国产区 | 91精品国产综合久久欧美 | 欧美精品国产一区二区三区 | 国产亚洲精品久久久久久午夜 | 怡红院免费全部视频在线 | 精品视频一区二区三区四区 |