国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 開發 > 綜合 > 正文

[C#]解決讀寫包含漢字的txt文件時亂碼的問題

2024-07-21 02:17:28
字體:
來源:轉載
供稿:網友
,歡迎訪問網頁設計愛好者web開發。作者:袁曉輝(版權所有)時間:2005-8-8   當我們用system.io.streamreader讀取包含漢字的txt文件時,經常會讀出亂碼(streamwriater寫文本文件也有類似的問題),原因很簡單,就是文件的編碼(encoding)和streamreader/writer的encoding不對應。    為了解決這個問題,我寫了一個類,來取得一個文本文件的encoding,這樣我們就可以創建對應的streamreader和streamwriter來讀寫,保證不會出現亂碼現象。其實原理很簡單,文本編輯器(比如xp自帶的記事本)在生成文本文件時,如果編碼格式和系統默認的編碼(中文系統下默認為gb2312)不一致時,會在txt文件開頭部分添加特定的“編碼字節序標識(encoding bit order madk,簡寫為bom)”,類似pe格式的"mz"文件頭。這樣它在讀取時就可以根據這個bom來確定該文本文件生成時所使用的encoding。這個bom我們用記事本等程序打開默認是看不到的,但是用stream按字節讀取時是可以讀到的。我的這個txtfileencoding類就是根據這個bom“文件頭”來確定txt文件生成時用到的編碼的。

//  作者:袁曉輝

//  2005-8-8

// // // // // //

using system;

using system.text;

using system.io;

namespace farproc.text

{

    /// <summary>

    /// 用于取得一個文本文件的編碼方式(encoding)。

    /// </summary>

    public class txtfileencoding

    {

        public txtfileencoding()

        {

            //

            // todo: 在此處添加構造函數邏輯

            //

        }

        /// <summary>

        /// 取得一個文本文件的編碼方式。如果無法在文件頭部找到有效的前導符,encoding.default將被返回。

        /// </summary>

        /// <param name="filename">文件名。</param>

        /// <returns></returns>

        public static encoding getencoding(string filename)

        {

            return getencoding(filename, encoding.default);

        }

        /// <summary>

        /// 取得一個文本文件流的編碼方式。

        /// </summary>

        /// <param name="stream">文本文件流。</param>

        /// <returns></returns>

        public static encoding getencoding(filestream stream)

        {

            return getencoding(stream, encoding.default);

        }

        /// <summary>

        /// 取得一個文本文件的編碼方式。

        /// </summary>

        /// <param name="filename">文件名。</param>

        /// <param name="defaultencoding">默認編碼方式。當該方法無法從文件的頭部取得有效的前導符時,將返回該編碼方式。</param>

        /// <returns></returns>

        public static encoding getencoding(string filename, encoding defaultencoding)

        {

            filestream fs = new filestream(filename, filemode.open);

            encoding targetencoding = getencoding(fs, defaultencoding);

            fs.close();

            return targetencoding;

        }

        /// <summary>

        /// 取得一個文本文件流的編碼方式。

        /// </summary>

        /// <param name="stream">文本文件流。</param>

        /// <param name="defaultencoding">默認編碼方式。當該方法無法從文件的頭部取得有效的前導符時,將返回該編碼方式。</param>

        /// <returns></returns>

        public static encoding getencoding(filestream stream, encoding defaultencoding)

        {

            encoding targetencoding = defaultencoding;

            if(stream != null && stream.length >= 2)

            {

                //保存文件流的前4個字節

                byte byte1 = 0;

                byte byte2 = 0;

                byte byte3 = 0;

                byte byte4 = 0;

                //保存當前seek位置

                long origpos = stream.seek(0, seekorigin.begin);

                stream.seek(0, seekorigin.begin);

               

                int nbyte = stream.readbyte();

                byte1 = convert.tobyte(nbyte);

                byte2 = convert.tobyte(stream.readbyte());

                if(stream.length >= 3)

                {

                    byte3 = convert.tobyte(stream.readbyte());

                }

                if(stream.length >= 4)

                {

                    byte4 = convert.tobyte(stream.readbyte());

                }

                //根據文件流的前4個字節判斷encoding

                //unicode {0xff, 0xfe};

                //be-unicode {0xfe, 0xff};

                //utf8 = {0xef, 0xbb, 0xbf};

                if(byte1 == 0xfe && byte2 == 0xff)//unicodebe

                {

                    targetencoding = encoding.bigendianunicode;

                }

                if(byte1 == 0xff && byte2 == 0xfe && byte3 != 0xff)//unicode

                {

                    targetencoding = encoding.unicode;

                }

                if(byte1 == 0xef && byte2 == 0xbb && byte3 == 0xbf)//utf8

                {

                    targetencoding = encoding.utf8;

                }

                //恢復seek位置      

                stream.seek(origpos, seekorigin.begin);

            }

            return targetencoding;

        }

    }

}

       由于在gb2312和utf7編碼都沒有bom,所以需要指定一個默認的encoding,在找不到合法的bom時,將返回這個encoding。有誰知道如何區分gb2312和utf7編碼txt文件的方法,也請告訴我。    由于只是static方法,所以不用new,直接通過類名調用方法,使用起來也很簡單。

using system;

using farproc.text;

using system.text;

using system.io;

namespace consoleapplication1

{

    /// <summary>

    /// class1 的摘要說明。

    /// </summary>

    class class1

    {

        /// <summary>

        /// 應用程序的主入口點。

        /// </summary>

        [stathread]

        static void main(string[] args)

        {

            //

            // todo: 在此處添加代碼以啟動應用程序

            //

            string filename = @"e:/a.txt";

            //生成一個big endian unicode編碼格式的文本文件

            streamwriter sw = new streamwriter(filename, false, encoding.bigendianunicode);//你可以試試其他編碼,比如encoding.getencoding("gb2312")或utf8

            sw.write("這是一個string");

            sw.close();

   

            //讀取

            encoding fileencoding = txtfileencoding.getencoding(filename, encoding.getencoding("gb2312"));//取得這txt文件的編碼

            console.writeline("這個文本文件的編碼為:" + fileencoding.encodingname);

            streamreader sr = new streamreader(filename, fileencoding);//用該編碼創建streamreader

   

            //用下面的方法雖然可以讓系統自動判斷文本文件的編碼格式,但是我們無法取得該文本文件的編碼

            //sr.currentencoding永遠為 unicode(utf-8)

            //streamreader sr = new streamreader(filename, true);

            //console.writeline("這個文本文件的編碼為:" + sr.currentencoding.encodingname);

            console.writeline("這個文本文件的內容為:" + sr.readtoend());

            sr.close();

            console.readline();

        }

    }

}

       .net下的string永遠是unicode的,所以只能判斷txt文件的encoding。對于byte[],只有自己知道它的encoding才能轉換為string 轉換為其他編碼的byte[],一個例外是把整個txt文件通過stream讀入byte[]后也可以根據它的前幾個字節判斷encoding,對于片斷,我們就無能為力了:)

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 永年县| 原平市| 黔西| 页游| 古交市| 太和县| 新源县| 泰安市| 阳谷县| 邓州市| 松阳县| 都昌县| 安吉县| 白山市| 乌兰察布市| 江北区| 黔西县| 旌德县| 绥江县| 石台县| 开江县| 平山县| 临海市| 宜宾县| 宁陕县| 潞城市| 寻甸| 长顺县| 益阳市| 凭祥市| 南丹县| 全南县| 崇礼县| 资兴市| 博湖县| 泊头市| 西青区| 谢通门县| 姜堰市| 淮阳县| 太湖县|