`
cindylu520
  • 浏览: 148171 次
  • 性别: Icon_minigender_2
  • 来自: 大连
社区版块
存档分类
最新评论

.Net 的区域性信息对程序移植性的影响

    博客分类:
  • .NET
阅读更多

如果你的程序希望在不同语言的操作系统上平滑移植,你必须要正确理解和设置区域性信息(CultureInfo),这个问题对于习惯了中文windows 操作系统的我们来说,往往非常容易忽略。一旦忽略这个问题,我们在中文windows操作系统下运行正常的程序跑在英文或者其他语言的操作系统上,比如台湾或香港版本的windows下,轻则显示不对,重则逻辑错误。下面就谈谈这个区域性信息对程序移植性的影响

一、对字符串排序的影响

在.net 下,字符串的大小比较并不是如C++那样按照字符串字符内码大小顺序从头到尾来比较的。由于我是从C/C++转过来的,我一直以来都以为.net 下字符串的比较规则和C++是一样的,直到有一天我的程序在英文操作系统下出错。

.net 下,字符串的排序受 System.Threading.Thread.CurrentThread.CurrentCulture 这个当前区域性信息影响,不同的区域性信息,字符串的排序结果会完全不同。

比如简体中文操作系统的默认当前区域性信息为 zh-CN 而英文操作系统(美国销售的)默认为 en-US ,我们就来看看这两者对中文字符串的排序有什么不同

先看 zh-CN

 

string[] stringList = { "不", "啊", "从", "的","一" };
 
System.Threading.Thread.CurrentThread.CurrentCulture = 
new System.Globalization.CultureInfo("zh-CN");
 
Array.Sort(stringList);
 
foreach (string str in stringList)
{
       Console.WriteLine(str);
 }

 

 

 

输出结果为:




我们再看 en-US

 

string[] stringList = { "不", "啊", "从", "的","一" };
 
System.Threading.Thread.CurrentThread.CurrentCulture = 
new System.Globalization.CultureInfo("en-US");
 
Array.Sort(stringList);
 
foreach (string str in stringList)
{
    Console.WriteLine(str);
}

 

输出结果为:




我们可以看出,不同的区域性信息,上述字符串的排序结果完全不同,简体中文下,排序按照汉字的拼音顺序来排序,而en-US 下则是按汉字的unicode 内码顺序排序。

其实就是简体中文下,排序顺序也有两种,一种是拼音顺序,一种是笔画顺序,下面我们看看按笔画顺序排序的结果

 

string[] stringList = { "不", "啊", "从", "的","一" };
 
System.Threading.Thread.CurrentThread.CurrentCulture = 
new System.Globalization.CultureInfo("zh-CN_stroke");
 
Array.Sort(stringList);
 
foreach (string str in stringList)
{
     Console.WriteLine(str);
}

 

输出结果为:





排序顺序对程序移植性的影响

显而易见,如果不注意这个问题,当程序从中文操作系统移植到英文操作系统上运行时,中文字符串的排序结果会完全不同,如果这个排序结果仅仅用于显示,则显示结果会不同,如果排序结果被作为一种类似主键的方式存储在文件,那么在中文操作系统下排序的文档,到了英文操作系统下就变成了不排序的文档,整个程序逻辑都会发生错误。

为了防止这种情况发生,我们必须在排序时指定一个固定的区域性信息,而不是使用操作系统默认的区域性信息。

 

二、对字符串查找的影响

           List<string> list = new List<string>(stringList);

            Console.WriteLine(list.BinarySearch("啊"));

 

上面代码,如果stringList 是从文件中读出,而这个文件是在中文操作系统下生成,如果当前是英文操作系统,则这里二分法查找字符串的结果就不确定,因为输入的字符串在英文操作系统下被认为不是排序的。

 

三、对Indexof的影响

这一节直接转载 MSDN 上的原文 http://msdn.microsoft.com/zh-cn/library/a7zyyk0c%28v=VS.80%29.aspx

 

您可以使用重载的 CompareInfo.IndexOf 方法返回指定字符串中某个字符或子字符串的从零开始的索引。如果在指定字符串中未找到该字符或子字符串,此方法将返回一个负整数。在使用 CompareInfo.IndexOf 搜索指定字符时,注意接受 CompareOptions 参数的方法重载执行比较的方式与不接受 CompareOptions 参数的方法重载不同。搜索 char(在 Visual Basic 中为 Char)并且不使用 CompareOptions 类型的参数的 CompareInfo.IndexOf 重载执行区分区域性的搜索。这就是说,如果 char 是一个表示预先撰写的字符的 Unicode 值,如连字“Æ”(\u00C6),则根据区域性的不同,它可能被视为等效于它的以正确顺序排列的任何组成部分,如“AE”(\u0041 \u0045)。若要执行序号(不区分区域性)搜索(即两个 char 只有 Unicode 值相同时才被视为相等),请使用带 CompareOptions 参数的 CompareInfo.IndexOf 重载之一。CompareOptions 参数设置为 CompareOptions.Ordinal 值。

您也可以使用搜索 charString.IndexOf 方法重载来执行序号搜索。请注意,搜索字符串的 String.IndexOf 方法重载执行区分区域性的搜索。

下面的代码示例阐释了根据区域性的不同,CompareInfo.IndexOf(string, char) 方法返回的结果的差异。针对“da-DK”(丹麦的丹麦语)创建 CultureInfo。接下来,使用 CompareInfo.IndexOf 方法的重载在字符串“Æble”和“aeble”中搜索字符“Æ”。请注意,对于“da-DK”区域性,带 CompareOptions.Ordinal 参数的 CompareInfo.IndexOf 方法与不带 CompareOptions.Ordinal 参数的 CompareInfo.Index 方法将返回相同的结果。字符“Æ”仅被视为等效于 Unicode 代码值 \u00E6。

 

using System;
using System.Globalization;
using System.Threading;
 
public class CompareClass
{
 
   public static void Main()
   {
      string str1 = "Æble";
      string str2 = "aeble"; 
      char find = 'Æ';
 
      // Creates a CultureInfo for Danish in Denmark.
      CultureInfo ci= new CultureInfo("da-DK");
 
      int result1 = ci.CompareInfo.IndexOf(str1, find);
      int result2 = ci.CompareInfo.IndexOf(str2, find);
      int result3 = ci.CompareInfo.IndexOf(str1, find,   
         CompareOptions.Ordinal);
      int result4 = ci.CompareInfo.IndexOf(str2, find, 
         CompareOptions.Ordinal);
 
      Console.WriteLine("\nCultureInfo is set to {0} ", ci.DisplayName);
      Console.WriteLine("\nUsing CompareInfo.IndexOf(string, char) , find, str1, result1);
         method\nthe result of searching for {0} in the string {1} is: 
         {2}"
      Console.WriteLine("\nUsing CompareInfo.IndexOf(string, char) , find, str2, result2);
         method\nthe result of searching for {0} in the string {1} is: 
         {2}"
      Console.WriteLine("\nUsing CompareInfo.IndexOf(string, char, , find, str1, result3);
         CompareOptions) method\nthe result of searching for {0} in the 
         string {1} is: {2}"
      Console.WriteLine("\nUsing CompareInfo.IndexOf(string, char, , find, str2, result4);
         CompareOptions) method\nthe result of searching for {0} in the 
         string {1} is: {2}"
   }
}

 

此代码产生下列输出:

CultureInfo is set to Danish (Denmark)

Using CompareInfo.IndexOf(string, char) method
the result of searching for Æ in the string Æble is: 0

Using CompareInfo.IndexOf(string, char) method
the result of searching for Æ in the string aeble is: -1

Using CompareInfo.IndexOf(string, char, CompareOptions) method
the result of searching for Æ in the string Æble is: 0

Using CompareInfo.IndexOf(string, char, CompareOptions) method
the result of searching for Æ in the string aeble is: -1

如果用 CultureInfo ci = new CultureInfo ("en-US") 替换 CultureInfo ci = new CultureInfo ("da-DK");,则带 CompareOptions.Ordinal 参数的 CompareInfo.Index 方法与不带 CompareOptions.Ordinal 参数的 CompareInfo.Index 方法将返回不同的结果。由 CompareInfo.IndexOf(string, char) 执行的区分区域性的比较认为字符“Æ”与其组成部分“ae”等效。由 CompareInfo.IndexOf(string, char, CompareOptions.Ordinal) 方法执行的序号(不区分区域性)比较则不返回与“ae”等效的字符“Æ”,因为它们的 Unicode 代码值不匹配。

当针对“en-US”区域性重新编译并执行这些代码时,将产生以下输出:

 

The CurrentCulture property is set to English (United States) 

Using CompareInfo.IndexOf(string, char) method
the result of searching for Æ in the string Æble is: 0

Using CompareInfo.IndexOf(string, char) method
the result of searching for Æ in the string aeble is: 0

Using CompareInfo.IndexOf(string, char, CompareOptions) method
the result of searching for Æ in the string Æble is: 0

Using CompareInfo.IndexOf(string, char, CompareOptions) method
the result of searching for Æ in the string aeble is: -1

 

四、如何指定当前默认的区域性信息

 

 

当前区域性信息在控制面板的 区域和语言选项中指定,修改第一个tab 中这两个参数将会影响操作系统当前默认的区域性信息。

分享到:
评论

相关推荐

    微软ASP.NET入门教程

    设置区域性和编码 本地化 ASP.NET 应用程序 使用资源文件 跟踪 跟踪概述 跟踪记录到页输出 应用程序级跟踪记录 调试 SDK 调试器 性能 性能概述 性能优化提示 测量性能 ASP 到 ASP.NET 的移植 移植概述...

    zxing.net 最新源码 ZXing.Net-master

    该项目源自于ZXing(Zebra Crossing),最初是Java平台上的一个条码识别库,而ZXing.Net则是其在.NET平台上的移植版本。 在“ZXing.Net-master”这个压缩包中,包含的是ZXing.Net项目的最新源码,时间戳为2017年。...

    ASP.NET Core.pdf

    - .NET Core 提供了更好的性能和更高的可移植性,适合现代云原生应用的开发。 #### 入门 - 开始学习 ASP.NET Core 的最佳方式是通过官方文档或教程。 - 可以从简单的 Web 应用程序开始,逐步深入到更复杂的项目。 ...

    BCGControlBar for .NET 3.1.1.0

    "BCGControlBar for .NET 3.1.1.0" 是一个专门针对...使用BCGControlBar for .NET 3.1.1.0时,开发者可以通过查阅文档、示例代码和在线资源来学习如何集成和利用这些功能,提升他们的.NET应用程序的专业性和用户体验。

    VB.Net 移动无标题栏的窗体(VB6.0方法移植版)

    这个项目展示了如何将VB6.0中的技术迁移到VB.NET中,同时保持了与操作系统的兼容性和用户体验的一致性。 总的来说,这个知识点涉及到Windows API的使用、窗体样式控制、鼠标事件处理以及自定义窗体行为。在实际开发...

    微软文档:.NET文档-5673页

    总之,.NET 文档提供了全面的资源,无论你是初学者还是经验丰富的开发者,都能从中找到所需信息,助力你的 .NET 开发之旅。不断更新的新特性、丰富的社区资源和工具,使得 .NET 成为了构建现代应用程序的强大平台。

    .NET中反射机制的使用与分析

    传递的路径不包含版本号、区域性或公钥信息,如果找不到程序集也会抛出异常。 3. **LoadWithPartialName**:这是一个应避免使用的方法,因为它不能确保加载程序集的版本。此方法仅用于.NET框架的测试环境中,将来很...

    界面开发(c++ 、.net)

    SkinSE只用到了windows几个底层的核心库,没有用到(MFC/ATL等第三方库),采用纯API编写,采用C语言导出方式,增强可移植性,可以用于多种计算机语言。 1.SKINSE界面库内部没有完全采用HOOK拦截窗口的机制,主要采用...

    .net平台开发的一个简单的Ajax登录界面

    7. **可移植模板**:为了增强代码的复用性和可维护性,开发者可能会使用模板引擎,如ASP.NET MVC的Razor视图或第三方库(如Handlebars、Nunjucks),来创建可重用的HTML模板。这样可以将视图逻辑与呈现逻辑分离,...

    仿微博头像上传.net版本

    - `web.config`:这是ASP.NET应用程序的核心配置文件,包含了应用程序的设置,如数据库连接字符串、身份验证和授权规则,以及错误处理。在这个项目中,可能有关于文件上传路径、权限设置或者MIME类型映射的配置。 ...

    WINCE.NET体系结构

    此外,它还支持一部分Win32 API,便于移植基于Windows的应用程序。 #### 二、特点与设计目标 1. **小尺寸映像**:WinCE.NET的设计重点之一在于其能够运行在资源极其有限的硬件平台上。通过高度组件化的设计,开发者...

    asp.net专家疑难解答200问

    12. ASP.NET Core:作为ASP.NET的最新版本,ASP.NET Core支持跨平台,结合了Web Forms和MVC的优势,提供了更高的性能和可移植性。 13. Razor视图引擎:Razor语法简洁,用于创建视图模板,结合C#语言特性,提高了视...

    ASP.NET Core 2.2 官方教程,netcore入门教程,C#源码.zip

    8. **全球化和本地化**:2.2版本提供了更好的全球化支持,包括区域性和文化敏感性处理,使得应用程序可以更好地适应全球用户。 9. **测试和调试**:加强了对单元测试和集成测试的支持,同时提供了更丰富的调试工具...

    libgeotiff.net:.net libgeotiff的端口

    而libgeotiff.net是这个C库在.NET平台上的一个移植版本,专门为C#开发者提供了访问Geotiff功能的接口。 libgeotiff.net的核心目标是为.NET Framework提供与libgeotiff相同的API,使得C#开发者能够方便地处理具有...

    VC程序设计大作业

    【VC程序设计大作业】是基于Visual C++ (VC) 的一项编程任务,它要求学生在VS2015编译环境下,模仿MATLAB的图形用户...在实际开发中,还可以考虑引入更现代的图形库,如Qt或wxWidgets,以提高代码的可移植性和效率。

    ASPNETCORERoleManagement

    ASP.NET Core是微软开发的一个开源、跨平台的Web应用程序框架,它在设计上注重性能、模块化和可移植性。本示例“ASPNETCORERoleManagement”关注的是在ASP.NET Core 2.0中实现基于角色的权限管理,这是一种常见的...

    ASP.NET基于Ajax+Lucene构建搜索引擎的设计和实现(源代码+论文).zip

    ASP.NET是一种微软开发的Web应用程序框架,用于构建交互性强、响应迅速的Web应用。结合Ajax(Asynchronous JavaScript and XML)技术和Lucene库,可以构建出高效、用户友好的搜索引擎。让我们深入探讨一下这个主题。...

Global site tag (gtag.js) - Google Analytics