zoukankan      html  css  js  c++  java
  • 中文系统下,UTF-8编码文本文件读取导致的错误

    一、UTF-8编码文件读取导致的错误

    有个txt文件,里面内容为:

    aaa
    bbb
    ccc

    以UTF-8编码方式打开txt文件,顺序读取,将里面的值放到一个hashset中,并判断aaa是否在在hashset中

    class  
    {
        public static void main(String[] args) 
        {
            try
            {
               HashSet<String> specialCateSet= new HashSet<String>();
               FileInputStream a = new FileInputStream("d://test.txt");
               String encoding = "UTF-8";
               InputStreamReader b = new InputStreamReader(a,encoding);
               BufferedReader br = new BufferedReader(b);
    
               String message = br.readLine();
               while (message != null) 
               {
                specialCateSet.add(message);
                message = br.readLine();
               }
            }
            catch(Exception e)
            {
                e.printStackTrace();
            }
    
            if(specialCateSet.contains("aaa"))
            {
                System.out.println("SpecialCate包含aaa");
            }
            else
            {
                System.out.println("SpecialCate不包含aaa");
            }
        }
    }

    结果输出:SpecialCateSet不包含aaa

    断点跟踪SpecialCateSet中的值,里面确实包含值"aaa",但是为什么specialCateSet.contains("aaa")验证为false呢?

    二、错误原因

    中文操作系统下,对于UTF-8编码格式的文本文件,其前3个字节的值就是-17、-69、-65(这三个字节说明了编码方式,详情参考Java如何获取文件编码格式) 

    修改程序如下,就直观了:

    class  
    {
        public static void main(String[] args) 
        {
            try
            {
               HashSet<String> specialCateSet= new HashSet<String>();
               FileInputStream a = new FileInputStream("d://test.txt");
               String encoding = "UTF-8";
               InputStreamReader b = new InputStreamReader(a,encoding);
               BufferedReader br = new BufferedReader(b);
    
               String message = br.readLine();
               while (message != null) 
               {
                    //打印输出message的byte值
                       byte[] a1=message.getBytes();
                    for(byte b1 :a1){
                    System.out.print(b1+ " "); 
                    }
    System.out.println(); specialCateSet.add(message); message
    = br.readLine(); } } catch(Exception e) { e.printStackTrace(); } } }

    结果输出如下,其中a的ascll为97,b:98,c:99
    -17 69 65 97 97 97

    98 98 98

    99 99 99

     因此specialCateSet中存放三个字符串值aaa(byte字节为:-17 69 65 97 97 97),bbb(byte字节为:-98 98 98),ccc(byte字节为:-99 99 99),其中虽然在java中显示specialCateSet包含字符串aaa,但是这个字符串aaa的byte字节为(-17 69 65 97 97 97),而在后面判断中specialCateSet.contains("aaa"),在java中定义的aaa byte字节为(97 97 97),因此验证不通过。

         通俗来讲,文本文件中读取的aaa的byte字节为(-17 69 65 97 97 97),其中包含有3个byte的编码值,但是在java中显示时将头三位的编码值忽略了,因此在java中显示的值为aaa,而直接在java中定义的字符串aaa的byte字节为(97 97 97),两者虽然显示一致,但是对应的字节值不同,以及各自的hashcode值也不同,因此java判断此aaa不同于彼aaa

    三、解决办法

    1、最简单的,在txt中空出第一行不用即可,因为就头三位是编码信息

    2、读取第一行时,将编码信息去除即可

  • 相关阅读:
    VGG卷积神经网络模型解析
    利用Azure内容审查器审查违规内容(上)
    Kotlin + 协程 + Retrofit + MVVM优雅的实现网络请求
    OpenCV 实现图片的水平投影与垂直投影,并进行行分割
    C#自定义ip控件
    C#、Java中的一些小知识点总结(持续更新......)
    WinForm程序,实现只启动一个实例
    将DLL文件直接封装进exe执行文件中(C#)
    WinForm下的loading框的实现
    获取串口映射的COM端口号
  • 原文地址:https://www.cnblogs.com/king1302217/p/4003274.html
Copyright © 2011-2022 走看看