java 字节乱码_java用字节流读取中文乱码怎么解决?

本文探讨了在处理不确定编码的文本文件时,如何使用CodepageDetectorProxy进行编码猜测,以及Java字符流如何处理编码转换以避免乱码。重点介绍了如何初始化编码判别器,检测输入流和文件编码,并提到了编码不一致可能导致的问题及解决方案。
摘要由CSDN通过智能技术生成

首先,如果你明确的知道使用的编码,那么你可以在读取完毕生成字符串的时候直接指定编码。

例如:

FileInputStream in = new FileInputStream("aaa.txt");

byte[] data = new byte[1024 * 4];

StringBuilder sb = new StringBuilder();

while(in.read(data) > 0) {

sb.append(new String(data,"utf8"); // 指定编码格式,避免乱码}

System.out.println(sb.toString());

这里FileInputStream就是很标准的字节流了,只需要在最终形成字符串的时候指定正确的编码,那么就可以避免乱码。

或者利用新的NIO的API读取:

Path path = Paths.get("D:/aaa.txt");

byte[] data = Files.readAllBytes(path);

String result = new String(data,"utf8"); // 指定编码,可以避免乱码。System.out.println(result);

那么,当我们不确定他的编码的时候,该怎么办呢,这就需要使用类库去猜解他的编码,我用的是这个:cpdetector,他的maven依赖如下:

net.sourceforge.cpdetector

cpdetector

1.0.7

具体用法是这样的:

/*** 初始化一个编码判别器,用于判断文件编码。*/

public static CodepageDetectorProxy getCodePageDetector() {

CodepageDetectorProxy detector = CodepageDetectorProxy.getInstance();

// 这个用于处理文本文件或者有明确编码的文件 detector.add(new ParsingDetector(false));

// 用于检测Unicode的编码 detector.add(UnicodeDetector.getInstance());

// 用于检测各类型的编码 detector.add(JChardetFacade.getInstance());

// 用于检测ASCII类型编码 detector.add(ASCIIDetector.getInstance());

return detector;

}

然后通过这种做法获取具体的编码:

/*** 获取输入流的编码格式,但是似乎这种方法有点问题。*/

public static Charset getCharset(InputStream in) {

CodepageDetectorProxy detectorProxy = getCodePageDetector();

try(BufferedInputStream bufferedInputStream = new BufferedInputStream(in)) {

return detectorProxy.detectCodepage(bufferedInputStream, 128);

} catch (Exception e) {

e.printStackTrace();

return Charset.defaultCharset();

}

}

/*** 获取文件的编码格式,一般用到的就是他了。*/

public static Charset getCharset(File file) {

CodepageDetectorProxy detectorProxy = getCodePageDetector();

try {

return detectorProxy.detectCodepage(file.toURI().toURL());

} catch (Exception e) {

return Charset.defaultCharset();

}

}

那么经过上面两个步骤,我们就能够得到一个charset对象,用他创建string,如果猜测的编码是正确的,就不会出现乱码,当然猜测代码比较耗费时间的,这个在使用的时候要注意一下。

说到乱码,我们得知道输入流是怎么处理字符的。

InputStream是一个读取字节的东西,因为无论是什么文本数据,存到系统的时候都是二进制的字节,为了能正确显示字符,需要有一个东西把字符表示为二进制字节,这个东西就是编码表。

不同的码表的字符和他对应的二进制字节的对应关系是不一致的,那么如果一个字符通过编码格式A编码,但是读取的时候通过编码格式B读取,那么就有一定几率出现乱码,为什么是有一定几率呢,是因为字符集有的是可以相互兼容的,尤其是英文字符部分,不兼容的部分就会出现乱码。

那么java是怎么处理字符流的呢?

Java的字符流从本质上来说,是字节流的衍生,他通过StreamDecoder和StreamEncoder进行处理,StreamEncoder的作用是将字符按照某种编码输出为字节,StreamDecoder作用是将某些字节按照某个编码方式解码成字符,你可以自己指定使用的编码类型,当然你不指定,他也会有一个默认的编码类型,而一旦你的文件编码和默认编码不一致,而你又没有指定字符集,那么出现乱码几乎是必然的。

因此我不赞同你认为字符流能够解决乱码问题,在这个问题上没有一劳永逸的办法,如果阁下知道更合理的解决方案欢迎补充,或者指出回答中不正确的部分。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值