欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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

 更新時間:2020年11月16日 10:11:39   作者:BuptWade  
這篇文章主要介紹了JAVA讀取HDFS的文件數(shù)據(jù)出現(xiàn)亂碼的解決方案,幫助大家更好的理解和使用Java,感興趣的朋友可以了解下

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

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

  • 英文字符串a(chǎn)aa,能正常顯示
  • 中文字符串“你好”,能正常顯示
  • 中英混合字符串如“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)解碼的思路后,其難點在于如何判斷使用哪種字符集解碼。參考下面的內(nè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 implements
			nsICharsetDetectionObserver {
		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("\\r\\n"));
  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)亂碼的解決方案的詳細內(nèi)容,更多關于JAVA讀取HDFS的文件亂碼的資料請關注腳本之家其它相關文章!

相關文章

  • java中的動態(tài)代理與責任鏈模式詳解

    java中的動態(tài)代理與責任鏈模式詳解

    這篇文章主要介紹了java中的動態(tài)代理與責任鏈模式詳解,動態(tài)代理提供了一種靈活且非侵入式的方式,可以對對象的行為進行定制和擴展,它在代碼重用、解耦和業(yè)務邏輯分離、性能優(yōu)化以及系統(tǒng)架構中起到了重要的作用,需要的朋友可以參考下
    2023-08-08
  • @Validated和@Valid三種異常捕獲處理方式

    @Validated和@Valid三種異常捕獲處理方式

    這篇文章主要介紹了@Validated和@Valid三種異常捕獲處理方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-10-10
  • java利用htmlparser獲取html中想要的代碼具體實現(xiàn)

    java利用htmlparser獲取html中想要的代碼具體實現(xiàn)

    這篇文章主要介紹了java利用htmlparser獲取html中想要的代碼具體實現(xiàn),需要的朋友可以參考下
    2014-02-02
  • 在日志中記錄Java異常信息的正確姿勢分享

    在日志中記錄Java異常信息的正確姿勢分享

    這篇文章主要介紹了在日志中記錄Java異常信息的正確姿勢,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-09-09
  • Flutter瀑布流仿寫原生的復用機制詳解

    Flutter瀑布流仿寫原生的復用機制詳解

    這篇文章主要給大家介紹了關于Flutter瀑布流仿寫原生的復用機制的相關資料,文中通過示例代碼介紹的非常詳細,對大家學習或者使用flutter具有一定的參考學習價值,需要的朋友可以參考下
    2021-07-07
  • 解決spring boot網(wǎng)關gateway導致的坑,無法下載文件問題

    解決spring boot網(wǎng)關gateway導致的坑,無法下載文件問題

    這篇文章主要介紹了解決spring boot網(wǎng)關gateway導致的坑,無法下載文件的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-07-07
  • Java數(shù)組集合的深度復制代碼實例

    Java數(shù)組集合的深度復制代碼實例

    這篇文章主要介紹了Java數(shù)組集合的深度復制代碼實例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2019-11-11
  • Java中的繼承詳情

    Java中的繼承詳情

    這篇文章主要介紹了Java中的繼承詳情,繼承是面向對象三大特征之一,可以使得子類具有父類的屬性和方法,還可以在子類中重新定義,以及追加屬性和方法,下文介紹需要的朋友可以參考下
    2022-04-04
  • Javaweb請求轉發(fā)及重定向實現(xiàn)詳解

    Javaweb請求轉發(fā)及重定向實現(xiàn)詳解

    這篇文章主要介紹了Javaweb請求轉發(fā)及重定向實現(xiàn)詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-07-07
  • java Runtime如何執(zhí)行多條命令

    java Runtime如何執(zhí)行多條命令

    這篇文章主要介紹了java Runtime如何執(zhí)行多條命令,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-11-11

最新評論