问题
-
线上遇到有玩家资源加载异常,发现资源路径出现异常字符:
-
发现是土耳其语下字符串转小写不符合预期:
"I".ToLower()
->ı
解决方案
-
String.ToLower
改成String.ToLowerInvariant
-
全局修改禁用文化差异:https://stackoverflow.com/questions/12729922/how-to-set-cultureinfo-invariantculture-default
// 这两行改了,但打印没I转小写还是有问题
CultureInfo.DefaultThreadCurrentCulture = CultureInfo.InvariantCulture;
CultureInfo.DefaultThreadCurrentUICulture = CultureInfo.InvariantCulture;
// 这个可以,见下图
CultureInfo.CurrentCulture = CultureInfo.InvariantCulture;
其他
- Lua 不会有这个问题
涉及的接口
下面直接抄至ChatGPT
1. 字符串处理
会受地区影响的接口:
-
string.ToLower()
和string.ToUpper()
- 根据
CultureInfo
转换大小写,例如土耳其语中I
转为小写是ı
而不是i
。
- 根据
-
string.Compare()
和string.Equals()
- 默认是基于当前文化进行比较。例如,
string.Compare("straße", "strasse")
在德语中可能被视为相等,而在其他文化中则不一定。
- 默认是基于当前文化进行比较。例如,
-
string.IndexOf()
和string.LastIndexOf()
- 这些方法在查找子字符串时,字符比较会受当前文化的影响。
示例:
using System;
using System.Globalization;
CultureInfo.CurrentCulture = new CultureInfo("tr-TR");
string text = "Istanbul";// 转小写
Console.WriteLine(text.ToLower()); // 输出 "ıstanbul"
2. 数字格式化
会受地区影响的接口:
-
ToString()
-
默认使用当前文化,格式化数字时会根据区域使用不同的千位分隔符、小数点。
-
例如:
-
英文(
en-US
):1234.56
转为1,234.56
-
法文(
fr-FR
):1234.56
转为1 234,56
-
-
-
Convert.ToDouble(string)
和double.Parse()
- 解析字符串为数字时,小数点和分隔符格式会受区域影响。
示例:
CultureInfo.CurrentCulture = new CultureInfo("fr-FR");
double number = 1234.56;
Console.WriteLine(number.ToString()); // 输出 "1 234,56"
3. 日期时间
会受地区影响的接口:
-
DateTime.ToString()
-
日期格式根据文化不同会有所变化。例如:
-
英文(
en-US
):12/21/2024
-
中文(
zh-CN
):2024/12/21
-
法文(
fr-FR
):21/12/2024
-
-
-
DateTime.Parse()
和DateTime.TryParse()
-
解析日期时,格式会根据文化而变化。例如:
-
12/21/2024
在en-US
中解析为 2024 年 12 月 21 日。 -
12/21/2024
在fr-FR
中会抛出错误,因为fr-FR
期望格式为DD/MM/YYYY
。
-
-
示例:
CultureInfo.CurrentCulture = new CultureInfo("fr-FR");
DateTime now = DateTime.Now;
Console.WriteLine(now.ToString("D")); // 输出 "21 décembre 2024"
4. 排序与比较
会受地区影响的接口:
-
Array.Sort()
和List<T>.Sort()
-
字符串排序会依赖当前的
CultureInfo
。 -
例如,瑞典语中的
ä
排在z
后,而德语中则可能不同。
-
-
Comparer<string>.Default.Compare()
- 使用默认的文化比较字符串,结果会因文化而异。
示例:
CultureInfo.CurrentCulture = new CultureInfo("sv-SE");
stringwords = { "apple", "äpple", "banana" };
Array.Sort(words);
Console.WriteLine(string.Join(", ", words)); // 瑞典语排序:"apple, banana, äpple"
5. 正则表达式(Regex)
-
Regex.IsMatch()
- 某些模式匹配可能受到文化影响,例如大小写敏感性(默认基于
CultureInfo.CurrentCulture
)。
- 某些模式匹配可能受到文化影响,例如大小写敏感性(默认基于
示例:
CultureInfo.CurrentCulture = new CultureInfo("tr-TR");
string pattern = "i";
Regex regex = new Regex(pattern, RegexOptions.IgnoreCase);
Console.WriteLine(regex.IsMatch("Istanbul")); // 输出 false,因为 "I" 不等于 "i"(土耳其语)
6. 序列化与反序列化
-
JSON/XML 序列化
- 在序列化数字和日期时,如果未显式指定文化,默认使用当前的
CultureInfo
。
- 在序列化数字和日期时,如果未显式指定文化,默认使用当前的
示例:
CultureInfo.CurrentCulture = new CultureInfo("fr-FR");
double value = 1234.56;// 序列化string json = JsonSerializer.Serialize(value);
Console.WriteLine(json); // 输出 "1234,56"
避免地区影响的最佳实践:
-
使用不变区域(
CultureInfo.InvariantCulture
):-
对大小写转换、数字和日期格式化,始终使用不变区域来确保一致性。
string result = text.ToLowerInvariant();
double number = double.Parse(input, CultureInfo.InvariantCulture);
-
-
显式指定文化:
- 如果需要支持多语言,显式传入目标文化:
DateTime.Parse(input, new CultureInfo("en-US"));
-
避免使用默认文化:
- 不依赖
CultureInfo.CurrentCulture
,明确指定文化环境。
- 不依赖