解析StreamReader与文件乱码问题的解决方法

 更新时间:2013年05月13日 12:14:14   作者:  
本篇文章是对StreamReader与文件乱码问题的解决方法进行了详细的分析介绍,需要的朋友参考下

相信很多人在读取文件的时候都会碰到乱码的情况,所谓乱码就是错乱的编码的意思,造成乱码的是由于编码不一致导致的。

演示程序:

新建3个文本文件:

clip_image002

编码和名字一样,分别是ansi,Unicode,utf8

里面的内容都是:

~@#%……&*()

abcdefg

123456789

测试数据

clip_image004

clip_image006

clip_image008

 

读取这些文件的代码如下:

public static void Main()

{

    List<string> lstFilePath = new List<string>()

    {

        "H:\\TestText\\ansi.txt",

        "H:\\TestText\\unicode.txt",

        "H:\\TestText\\utf8.txt"

    };

    foreach (string filePath in lstFilePath)

    {

        using (StreamReader reader = new StreamReader(filePath))

        {

            Console.WriteLine("读取文件" + filePath);

            Console.WriteLine(reader.ReadToEnd());

            Console.WriteLine("************************************************************");

        }

    }

}

输出入下:

clip_image010

 

由于第一个文件使用ansi编码,但是StreamReader 的默认构造函数使用的是utf8编码,所以乱码了。

StreamReader 旨在以一种特定的编码输入字符,而 Stream 类用于字节的输入和输出。 使用 StreamReader 读取标准文本文件的各行信息。

除非另外指定, StreamReader 的默认编码为 UTF-8,而不是当前系统的 ANSI 代码页 UTF-8 可以正确处理 Unicode 字符并在操作系统的本地化版本上提供一致的结果。

所以解决上面的编码问题的解决方案是使用StreamReader,并且传递Encoding.Default作为编码,一般在中文操作系统中,Encoding.Default是Gb2312编码。

public static void Main()

{

    List<string> lstFilePath = new List<string>()

    {

        "H:\\TestText\\ansi.txt",

        "H:\\TestText\\unicode.txt",

        "H:\\TestText\\utf8.txt"

    };

    foreach (string filePath in lstFilePath)

    {

        using (StreamReader reader = new StreamReader(filePath,Encoding.Default))

        {

            Console.WriteLine("读取文件" + filePath);

            Console.WriteLine(reader.ReadToEnd());

            Console.WriteLine("************************************************************");

        }

    }

}

输出如下:

clip_image012

从这里得到一个结论:使用StreamReader,并且使用Encoding.Default 作为编码。

很可惜,上面的这个结论在某些情况下页会存在问题,例如在你的操作系统中Encoding.Default Encoding.UTF8的时候。

最完美的解决方案是:文件使用什么编码保存的,就用什么编码来读取。

那如何得到文件的编码呢?

使用下面的代码就可以了:

复制代码 代码如下:

public static Encoding GetEncoding(string filePath)
        {
            if (filePath == null)
            {
                throw new ArgumentNullException("filePath");
            }
            Encoding encoding1 = Encoding.Default;
            if (File.Exists(filePath))
            {
                try
                {
                    using (FileStream stream1 = new FileStream(filePath, FileMode.Open, FileAccess.Read))
                    {
                        if (stream1.Length > 0)
                        {
                            using (StreamReader reader1 = new StreamReader(stream1, true))
                            {
                                char[] chArray1 = new char[1];
                                reader1.Read(chArray1, 0, 1);
                                encoding1 = reader1.CurrentEncoding;
                                reader1.BaseStream.Position = 0;
                                if (encoding1 == Encoding.UTF8)
                                {
                                    byte[] buffer1 = encoding1.GetPreamble();
                                    if (stream1.Length >= buffer1.Length)
                                    {
                                        byte[] buffer2 = new byte[buffer1.Length];
                                        stream1.Read(buffer2, 0, buffer2.Length);
                                        for (int num1 = 0; num1 < buffer2.Length; num1++)
                                        {
                                            if (buffer2[num1] != buffer1[num1])
                                            {
                                                encoding1 = Encoding.Default;
                                                break;
                                            }
                                        }
                                    }
                                    else
                                    {
                                        encoding1 = Encoding.Default;
                                    }
                                }
                            }
                        }
                    }
                }
                catch (Exception exception1)
                {
                    throw;
                }
                if (encoding1 == null)
                {
                    encoding1 = Encoding.UTF8;
                }
            }
            return encoding1;
        }

这段代码使用encoding1.GetPreamble()方法来得到编码的字节序列,然后重新读取数据,比较数据,如果不相同则说明是Encoding.Default.

否则是Encoding.Utf8.

有了GetEncoding(filename)方法后,可以将上面的读取代码修改如下:

public static void Main()

{

    List<string> lstFilePath = new List<string>()

    {

        "H:\\TestText\\ansi.txt",

        "H:\\TestText\\unicode.txt",

        "H:\\TestText\\utf8.txt"

    };

    foreach (string filePath in lstFilePath)

    {

        using (StreamReader reader = new StreamReader(filePath, GetEncoding(filePath)))

        {

            Console.WriteLine("读取文件" + filePath);

            Console.WriteLine(reader.ReadToEnd());

            Console.WriteLine("当前编码:" + reader.CurrentEncoding.EncodingName);

            Console.WriteLine("************************************************************");

        }

    }

}

输出如下:

clip_image002

从这里可以看到ansi 编码,Encoding.Default 就是简体中文(GB2312)

相关文章

  • C#使用第三方组件生成二维码汇总

    C#使用第三方组件生成二维码汇总

    本文给大家汇总了几种C#使用第三方组件生成二维码的方法以及示例,非常的简单实用,都是项目中经常需要用到的,希望大家能够喜欢
    2016-12-12
  • C#难点逐个击破(8):可空类型System.Nullable

    C#难点逐个击破(8):可空类型System.Nullable

    null值用来表示数据类型未被赋予任何值,它是一种引用类型;void表示没有类型,或者说是没有任何值。null与void的区别可以认为void是根本没有,而null是一个空箱子,里面什么都没有。
    2010-02-02
  • C#图片处理3种高级应用

    C#图片处理3种高级应用

    本文介绍C#图片处理高级应用,这些功能并无多大技术含量。全部基于.Net Framework类库完成,代码中包含了C#图片处理的一些基础知识,与大家分享,个人能力有限,不足之处还请及时指正。
    2015-10-10
  • C# 7.0 使用下划线忽略使用的变量的原因分析

    C# 7.0 使用下划线忽略使用的变量的原因分析

    这篇文章主要介绍了C# 7.0 使用下划线忽略使用的变量的原因浅析,本文通过实例代码给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
    2018-10-10
  • webBrowser执行js的方法,并返回值,c#后台取值的实现

    webBrowser执行js的方法,并返回值,c#后台取值的实现

    下面小编就为大家带来一篇webBrowser执行js的方法,并返回值,c#后台取值的实现。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-12-12
  • C#入门教程之集合ArrayList用法详解

    C#入门教程之集合ArrayList用法详解

    这篇文章主要介绍了C#入门教程之集合ArrayList用法,结合具体实例分析了C#中集合的概念、功能、创建与使用方法,需要的朋友可以参考下
    2017-06-06
  • C#以太网Sockets客户端设计实现

    C#以太网Sockets客户端设计实现

    本文主要介绍了C#以太网Sockets客户端设计实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-02-02
  • 基于C#实现图片合成功能

    基于C#实现图片合成功能

    这篇文章主要为大家详细介绍了如何利用C#实现图片合成的功能,文中的示例代码讲解详细,对我们学习C#有一定的帮助,感兴趣的小伙伴可以跟随小编一起了解一下
    2022-12-12
  • C#语言主要特性总结

    C#语言主要特性总结

    这篇文章主要介绍了C#语言主要特性总结,本文总结了C#语言的简单、现代、面向对象、类型安全、相互兼容性、可伸缩性和可升级性等几个主要特点,需要的朋友可以参考下
    2015-02-02
  • Unity3D实现物体旋转缩放移动效果

    Unity3D实现物体旋转缩放移动效果

    这篇文章主要为大家详细介绍了Unity3D实现物体旋转缩放移动效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-02-02

最新评论