java 使用readLine() 乱码的解决

 更新时间:2021年12月09日 11:46:06   作者:学习笔记cmj  
这篇文章主要介绍了java使用readLine()乱码的解决,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

使用readLine() 乱码的解决

本人在公司开发程序遇到了读取一行乱码

eclipse 默认为utf-8

FileInputStream f4 = new FileInputStream(new File("F:\\bb.txt"));
BufferedReader bufferedReader2 = new BufferedReader(new InputStreamReader(f4));
String readLine = bufferedReader2.readLine(); //会输出乱码

测试文件有两个文本文件分别为,aa.txt (UTF-8编码),bb.txt(GB2312编码)两个文件中的内容都为一个字符 中:

前提知识: utf-8中文占三个字节,GB2312中文占两个字节

测试 代码:

public class EncodeTest {
    @Test
    public void test1() throws Exception{
        FileInputStream f1 = new FileInputStream(new File("F:\\aa.txt"));
        byte[] b1  =  new byte[f1.available()];
        f1.read(b1);
        for(byte b : b1){
            System.out.println(b);
        }
        System.out.println(new String(b1));
        System.out.println("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
        FileInputStream f2 = new FileInputStream(new File("F:\\bb.txt"));
        byte[] b2  =  new byte[f2.available()];
        f2.read(b2);
        for(byte b : b2){
            System.out.println(b);
            byte[] tb = new byte[]{b};
            String lm = new String(tb);
            System.out.println("当前乱码"+lm);
            byte[] lm_b = lm.getBytes();
            System.out.println("-----------乱码 start--------");
            for(byte bn: lm_b){
                System.out.println(bn);
            }
            System.out.println("-----------乱码 end--------");
        }
        System.out.println(new String(b2,"gb2312"));
        System.out.println("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
        FileInputStream f3 = new FileInputStream(new File("F:\\bb.txt"));
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(f3));
        String readLine2 = bufferedReader.readLine();
        byte[] b3 = readLine2.getBytes("UTF-8");
        for(byte b : b3){
            System.out.println(b);
        }
        System.out.println(new String(b3));
        System.out.println("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
        
        FileInputStream f4 = new FileInputStream(new File("F:\\bb.txt"));
        BufferedReader bufferedReader2 = new BufferedReader(new InputStreamReader(f4,"GB2312"));
        String readLine = bufferedReader2.readLine();
        byte[] b4 =readLine.getBytes("UTF-8");
        for(byte b : b4){
            System.out.println(b);
        }
        System.out.println(new String(b4));
        System.out.println("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
    }
}

通过分析打印结果:

-28 #字节1
-72 #字节2
-83 #字节3
中 #utf-8 解码后字符为:中,没有出现乱码
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-42 #字节1
当前乱码� #将 -42 按照utf-8 解码后的字符是乱码,然后再将乱码按照utf-8编码得到的字节如下
-----------乱码 start--------
-17
-65
-67
-----------乱码 end--------
-48 #字节2
当前乱码� ##将 -48 按照utf-8 解码后的字符是乱码,然后再将乱码按照utf-8编码得到的字节如下
-----------乱码 start--------
-17
-65
-67
-----------乱码 end--------
中 # 将 字节1: -42和字节2:-48 按照 gb2312 解码 后为字符 中
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-17 # 这里为readline()方法没有设置使用eclipse默认编码 默认使用utf-8 (读取bb.txt)
-65
-67
-17
-65
-67
�� # 输出的中文为乱码
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-28 #这里为readline()方法设置了编码为GB2312 读取一行文字为中 (读取bb.txt)
-72
-83

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

小结一下

new BufferedReader(new InputStreamReader(f4)); 默认用utf-8去解码字节,而bb.txt文件内容的字符是gb2312 所以该 中 字符在磁盘中占两个字节,而utf-8编码集中的中文占3个字节,而readline()的时候发现是两个字节,当前使用的又是utf-8,所以java底层就将这两个字节单独使用utf-8进行了解码, 每一个字节 使用utf-8编码一次为 一个char字符,所以经过utf-8将两个字节分别解码后的最终数据为两个乱码字符,

读者可以看上面的代码和打印的信息,两字符个乱码编码后的字节分别为-17 -65 -67(红色),和上面单独将一个字节用utf-8 接码后的字符再按照utf-8编码后得到的字节 -17 -65 -67(蓝色)一样,也就是说 当字节按照utf-8 解码时在utf-8编码集中找不到对应的正确的字符时就会默认作为� 输出,而� 对应的utf-8 字节 -17 -65 -67。所以当找不到对应正确的编码字符时都会按照 -17 -65 -67 对应的 字符 � 输出。

常识: 当使用 new BufferedReader(new InputStreamReader(f4),"文本源的编码") 文本源的编码一定要写。这样就不会有乱码。

调用readLine的乱码问题

readLine是一个很好用的方法,但是作为字符流的方法,确实会遇到各种关于编码方面的问题。但是用字节流来处理数据,比如说一个文本文件,要作按行处理的话,又会显得很不灵活。

下面提供的是readLine字符流指定编码方式的方法

//定义一个File对象
File someFile = new File("somefile.txt");
//输入流
FileInputStream fis = new FileInputStream(someFile);
InputStreamReader isr = new InputStreamReader(fis,"UTF-8"); //指定以UTF-8编码读入
BufferedReader br = new BufferedReader(isr);
//输出流
FileOutputStream fos = new FileOutputStream(someFile + ".生成的文件.txt");
OutputStreamWriter osw = new OutputStreamWriter(fos, "UTF-8"); //指定以UTF-8编码输出
while ((line = br.readLine()) != null) {
//osw.write("write something");
osw.write(line);
}
//关闭IO流
br.close();
osw.close();

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • Spring @Component自定义注解实现详解

    Spring @Component自定义注解实现详解

    @Component是一个元注解,意思是可以注解其他类注解,如@Controller @Service @Repository @Aspect。官方的原话是:带此注解的类看为组件,当使用基于注解的配置和类路径扫描的时候,这些类就会被实例化
    2022-09-09
  • Java设计模式之外观模式示例详解

    Java设计模式之外观模式示例详解

    外观模式为多个复杂的子系统,提供了一个一致的界面,使得调用端只和这个接口发生调用,而无须关系这个子系统内部的细节。本文将通过示例详细为大家讲解一下外观模式,需要的可以参考一下
    2022-03-03
  • Mac系统搭建JDK及JMETER过程解析

    Mac系统搭建JDK及JMETER过程解析

    这篇文章主要介绍了Mac系统搭建JDK及JMETER过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-08-08
  • 启用Spring事务管理@EnableTransactionManagement示例解析

    启用Spring事务管理@EnableTransactionManagement示例解析

    这篇文章主要为大家介绍了启用Spring事务管理@EnableTransactionManagement示例解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-09-09
  • Java 策略模式 if-else用法实例详解

    Java 策略模式 if-else用法实例详解

    这篇文章主要介绍了Java 策略模式 if-else用法详解,文章围绕主题展开详细的内容介绍,具有一定的参考价值,需要的朋友可以参考一下
    2022-07-07
  • 线程池之jdk1.8 Executors创建线程池的几种方式

    线程池之jdk1.8 Executors创建线程池的几种方式

    这篇文章主要介绍了线程池之jdk1.8 Executors创建线程池的几种方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-08-08
  • 使用spring容器在初始化Bean时前和后的操作

    使用spring容器在初始化Bean时前和后的操作

    这篇文章主要介绍了使用spring容器在初始化Bean时前和后的操作,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-09-09
  • 对Netty组件的基本介绍

    对Netty组件的基本介绍

    这篇文章主要介绍了对Netty组件的基本介绍,Netty是基于Java NIO client-server的网络应用框架,使用Netty可以快速开发网络应用,本文涵盖了netty开发中主要的组件的介绍,需要的朋友可以参考下
    2021-06-06
  • spring boot 常见http请求url参数获取方法

    spring boot 常见http请求url参数获取方法

    这篇文章主要介绍了spring boot 常见http请求url参数获取,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-03-03
  • 解决logback的日志文件路径问题

    解决logback的日志文件路径问题

    这篇文章主要介绍了解决logback的日志文件路径问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-02-02

最新评论