Silverlight读取包含中文的txt(解决乱码问题)

虽然Silverlight已经是被抛弃的孩子了,但此前做的一些项目还是用到Silverlight。今天用Silverlight导入客户端本地的一个txt文件,然后读取需要的信息。随手记录一下,留作以后备忘。

网上也有不少的相关资料,但好像要么是单纯的Ctrl+C、Ctrl+V,要么是不够齐全。闲话少说,直接上代码。

我用的是MVVM模式,所以用RelayCommand命令打开了。其它的,直接在类似Button_Click事件里调用OpenFile(),同理。

 1         /// <summary>
 2         /// 打开文件
 3         /// </summary>
 4         private void OpenFile()
 5         {
 6             try
 7             {
 8                 //检查是否是在OOB模式下运行
 9                 OOBChecker.CheckInstallState(() =>
10                 {
11                     //弹出选择文件对话框
12                     OpenFileDialog fileDialog = new OpenFileDialog()
13                     {
14                         Filter = "Txt Files (*.txt)|*.txt|All Files (*.*)|*.*",
15                     };
16 
17                     if (fileDialog.ShowDialog() == true)
18                     {
19                         //读取文件流
20                         using (Stream fs = fileDialog.File.OpenRead())
21                         {
22                             ReadTxtFile(fs);
23                             fs.Close();
24                         }
25                     }
26                 });
27             }
28             catch (Exception e)
29             {
30 
31                 //错误处理
32             }
33         }

注: OOBChecker.CheckInstallState,是为公司项目需要写的一个检查Silverlight程序是否在浏览器外运行的方法。众所周知,Silverlight是可以安装在本机脱离浏览器运行的,这样便可获得更高的执行权限。有时对本地文件(夹)进行操作时,程序需要获得信任权限。不知是否我浏览器设置问题,我直接在IE上运行,貌似也有权限。

附上OOBChecker的代码。

   public class OOBChecker
        {
            /// <summary>
            /// 当前程序是否安装在本地
            /// </summary>
            private static bool IsInstall { get; set; }

            /// <summary>
            /// 检查当前程序有没有安装在本地,callback是回调
            /// </summary>
            public static void CheckInstallState(Action callback)
            {
                try
                {
                    if (App.Current.HasElevatedPermissions)
                    {
                        //跳过OOB验证,直接在网页打开
                        if (callback != null)
                        {
                            callback();
                            return;
                        }
                    }

                    if (App.Current.InstallState == InstallState.Installed)
                    {
                        if (App.Current.IsRunningOutOfBrowser)
                        {
                            IsInstall = true;

                            //项目中操作Office COM需要
                            if (AutomationFactory.IsAvailable)
                            {
                                if (callback != null)
                                {
                                    callback();
                                }
                            }
                            else
                            {
                                MessageWindow.CreateNew("您好,AutomationFactory IsAvailable Is False",
                                                    resTipInformation.strApplicationTitle);
                            }

                            //App.Current.MainWindow.TopMost = true;
                        }
                        else
                        {
                            MessageWindow.CreateNew("您好,您已在本机安装了模块程序,请保存本页面数据后双击运行桌面的图标。",
                                                    resTipInformation.strApplicationTitle);
                        }
                    }
                    else
                    {
                        MessageWindow.CreateNewConfirm("打开文档之前需要安装本程序在您电脑上,确定帮您安装吗?为避免数据丢失,请确认前先保存数据。",
                            resTipInformation.strApplicationTitle, () =>
                            {
                                App.Current.InstallStateChanged += Current_InstallStateChanged;
                                App.Current.Install();
                            });
                    }
                }
                catch (Exception ex)
                {
                    ErrorWindow.CreateNew(ex);
                    Debug.WriteLine(string.Format("{0} at {1}", ex.Message, "OOBChecker"));
                }
            }

            /// <summary>
            /// 安装完成后
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private static void Current_InstallStateChanged(object sender, System.EventArgs e)
            {
                if (App.Current.InstallState == InstallState.Installed)
                {
                    IsInstall = true;
                }
            }
        }
View Code

OpenFile方法中,调用了一个读取文件内容的方法:ReadTxtFile

 1         /// <summary>
 2         /// 一行行地循环读取
 3         /// </summary>
 4         private void ReadTxtFile(Stream fs)
 5         {
 6             var myTable = new List<string>();
 7             using (StreamReader reader = new StreamReader(fs, new Gb2312Encoding()))
 8             {
 9                 /*
10                  * 一次性读出所有文件信息
11                  * var fileText = string.Empty;
12                 fileText = reader.ReadToEnd();
13                  */
14 
15                 reader.BaseStream.Seek(0, SeekOrigin.Begin);
16                 string strLine = reader.ReadLine();
17                 var tableIndex = 0;
18                 while (strLine != null)
19                 {
20                     /*
21                      * do your things here
22                     if (strLine.Contains("[Your message is here]"))
23                     {
24                         //找到表头了
25                         tableIndex++;
26                     }
27 
28                     if (tableIndex > 6)
29                     {
30                         //读完需要的表信息了,跳出
31                         break;
32                     }
33 
34                     if (tableIndex >= 4)
35                     {
36                         //开始获取需要的信息
37                         myTable.Add(strLine);
38                     }
39                     if (tableIndex > 0)
40                     {
41                         tableIndex++;
42                     }
43                     */
44                     strLine = reader.ReadLine();
45                 }
46                 reader.Close();
47             }
48 
49             if (myTable.Any())
50             {
51                 foreach (var strItem in myTable)
52                 {
53                     var view = strItem.TrimEnd('\t').Split('\t');
54                     //do something here
55                 }
56             }
57 
58         }

注:Silverlight不支持GB2312编码,所以打开中文时会乱码。为此,我们可以继承Encoding,自己为程序添加GB2312编码。然后像下面那样调用。

StreamReader reader = new StreamReader(fs, new Gb2312Encoding())
Gb2312Encoding的代码,里面包含了个Gb2312toUnicodeDictinary(这个是网上找的,很多网上资料只有Gb2312Encoding,却没有附上Gb2312toUnicodeDictinary)。
只上Gb2312Encoding的代码吧,Gb2312toUnicodeDictinary有7000多行的说……,这两个文件以附件形式放在后面,有需要的童鞋自行下载。
 1  public class Gb2312Encoding : Encoding
 2     {
 3         public override string WebName
 4         {
 5             get
 6             {
 7                 return "gb2312";
 8             }
 9         }
10 
11         public Gb2312Encoding()
12         {
13 
14         }
15         public override int GetBytes(char[] chars, int charIndex, int charCount, byte[] bytes, int byteIndex)
16         {
17             throw new NotImplementedException();
18         }
19 
20         public override int GetChars(byte[] bytes, int byteIndex, int byteCount, char[] chars, int charIndex)
21         {
22             int j = 0;
23             char c;
24             for (int i = 0; i < byteCount; i += 2)
25             {
26                 if (i + 1 >= bytes.Length)
27                 {
28                     char[] last = Encoding.UTF8.GetChars(new byte[] { bytes[i] });
29                     chars[j] = last[0];
30                 }
31                 else
32                 {
33                     byte[] bb = new byte[] { bytes[i], bytes[i + 1] };
34                     if (Gb2312toUnicodeDictinary.TryGetChar(bb, out c))
35                     {
36                         chars[j] = c;
37                         j++;
38                     }
39                     else
40                     {
41                         char[] tt = Encoding.UTF8.GetChars(new byte[] { bb[1] });
42                         chars[j] = tt[0];
43                         j++;
44                         //测试下一个
45                         if (i + 2 >= bytes.Length)
46                         {
47                             char[] tttt = Encoding.UTF8.GetChars(new byte[] { bb[0] });
48                             chars[j] = tttt[0];
49                             j++;
50                         }
51                         else
52                         {
53                             byte[] test = new byte[] { bb[0], bytes[i + 2] };
54                             if (Gb2312toUnicodeDictinary.TryGetChar(test, out c))
55                             {
56                                 chars[j] = c;
57                                 j++;
58                                 i++;
59                             }
60                             else
61                             {
62                                 char[] ttt = Encoding.UTF8.GetChars(new byte[] { bb[0] });
63                                 chars[j] = ttt[0];
64                                 j++;
65                             }
66 
67                         }
68                     }
69                 }
70             }
71 
72             return chars.Length;
73         }
74 
75         public override int GetByteCount(char[] chars, int index, int count)
76         {
77             return count;
78         }
79         public override int GetCharCount(byte[] bytes, int index, int count)
80         {
81             return count;
82         }
83 
84         public override int GetMaxByteCount(int charCount)
85         {
86             return charCount;
87         }
88         public override int GetMaxCharCount(int byteCount)
89         {
90             return byteCount;
91         }
92         public static int CharacterCount
93         {
94             get { return 7426; }
95         }
96     }
View Code

 附件(GB2312Encoding+GB2312toUnicodeDictinary)下载

作者:Ivan
个人网站:http://www.IvanBy.com
原文地址:https://www.cnblogs.com/oneivan/p/3089503.html