C# 写入平面文件US区域性,是否将程序集加载到不同的区域性中
我有一个类库,它读取从Delphi遗留应用程序编写的平面文件,然后处理数据并写回平面文件 当用户有不同的操作系统文化时,问题就来了,我们也本地化了dll,将本地化字符串写入平面文件 当我们根据文化(即1,60而不是1.60)编写双阀门时,问题就出现了。由于遗留应用程序使用“,”作为分隔符,我们无法写入1,60 在美国文化中,有没有一种方式可以让我们写下双重价值观C# 写入平面文件US区域性,是否将程序集加载到不同的区域性中,c#,localization,culture,C#,Localization,Culture,我有一个类库,它读取从Delphi遗留应用程序编写的平面文件,然后处理数据并写回平面文件 当用户有不同的操作系统文化时,问题就来了,我们也本地化了dll,将本地化字符串写入平面文件 当我们根据文化(即1,60而不是1.60)编写双阀门时,问题就出现了。由于遗留应用程序使用“,”作为分隔符,我们无法写入1,60 在美国文化中,有没有一种方式可以让我们写下双重价值观 同时,我们正在将Delphi应用程序转换为C#。我在想,让一个有罗马尼亚文化的人创建一个文件,该文件的双倍值为1,25,当它被发送到一
同时,我们正在将Delphi应用程序转换为C#。我在想,让一个有罗马尼亚文化的人创建一个文件,该文件的双倍值为1,25,当它被发送到一个美国文化的人时,他的大会期望值为1.25,所以在尝试从字符串转换为双倍值时,会崩溃。因此,在这种情况下,始终从En-US区域性文件中进行写入和读取也会有所帮助,大家怎么说?您可以设置当前线程的本地化,以便它将遵循您选择的本地化规则 使用以下命令:
Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");
如果您不想跟踪文件编写的区域性,那么您可以选择在文件中使用统一格式来表示数字,而不考虑区域性。要实现此目标,可以使用接受IFormatProvider作为参数的函数。对于大多数数据类型,这些函数包括(但不限于)Parse、TryParse和ToString。这样,您不必更改线程的区域性,但仍然可以在另一个区域性中读取或写入
// Simulated file containing one number per line in en-US culture
string file = "2.3\n3.5\n5.7";
// Assumed that files all use en-US culture for numbers
System.Globalization.NumberFormatInfo numberFormat = CultureInfo.GetCultureInfo("en-US").NumberFormat;
foreach (string line in file.Split('\n'))
{
// Parse en-US string to double
double number = double.Parse(line, numberFormat);
// Debugging/Logging using thread's current culture
Debug.WriteLine(number.ToString("F1"));
// Write to console or possibly another file in en-US culture
Console.WriteLine(number.ToString("F1", numberFormat));
}
但是,如果您通常在多个区域性中编写平面文件,那么您确实应该使用所编写的区域性对其进行标记,无论是在文件名中还是在文件头中。这样,您就可以基于文件的区域性进行导入。这是具有多种编码的任何类型文件的标准做法
如果文件是人类可读的,那么这也可能是有益的,从而保留每个文化期望看到的内容,而不是选择一种文化并使其他所有人都遵守它
在使用接受IFormatProvider参数的函数时,思路保持不变,例如:
public static void Main(string[] args)
{
// Simulated file containing one number per line in fr-CA culture
MemoryStream inputStream = new MemoryStream();
StreamWriter writer = new StreamWriter(inputStream);
writer.WriteLine("2,3");
writer.WriteLine("3,5");
writer.WriteLine("5,7");
writer.Flush();
inputStream.Seek(0, SeekOrigin.Begin);
// Simulated output file that we want in en-CA culture
MemoryStream outputStream = new MemoryStream();
Convert(inputStream, CultureInfo.GetCultureInfo("fr-CA"), outputStream, CultureInfo.GetCultureInfo("en-CA"));
// Print output file
outputStream.Seek(0, SeekOrigin.Begin);
StreamReader reader = new StreamReader(outputStream);
string line;
while ((line = reader.ReadLine()) != null)
{
Console.WriteLine(line);
}
}
public static void Convert(Stream inputStream, CultureInfo inputCulture, Stream outputStream, CultureInfo outputCulture)
{
// Get number format for input and output cultures
NumberFormatInfo inputNumberFormat = inputCulture.NumberFormat;
NumberFormatInfo outputNumberFormat = outputCulture.NumberFormat;
// Setup reader and writer for input and output streams
StreamReader reader = new StreamReader(inputStream);
StreamWriter writer = new StreamWriter(outputStream);
// Read each line of input stream and write to output stream, while preserving culture of thread, input, and output
string line;
while ((line = reader.ReadLine()) != null)
{
// Parse string from input stream to double using input culture
double number = double.Parse(line, inputNumberFormat);
// Debugging/Logging using thread's current culture
Debug.WriteLine(number.ToString("F1"));
// Write double to output stream using output culture
writer.WriteLine(number.ToString("F1", outputNumberFormat));
}
writer.Flush();
}
我意识到这个问题很久以前就被问过了,原来的海报可能不再需要这个了,但我也看不到任何可以接受的答案。由于我遇到了与原始海报问题类似的问题,我想我应该发布我发现的答案。这就是我的想法,但在编写输出文件时,我还编写了一个日志文件,指出对该文件所做的更改,并且该日志必须本地化。因此,设置整个线程的文化是行不通的。我所想的是,将为double-like(number.ToString(“c”,new CultureInfo(“En-US”));)创建一个扩展方法ToString,因此当我将要写入平面文件时,我将使用double.ToString(),当writind to log时,将使用double.ToString()。你所说的……这种方法将非常缺乏活力,如果另一个国家加入俱乐部会发生什么:)所以我将在美国文化中记录文件,并在美国写作。其他的一切都是一样的same@Mohit:我的理解正确吗?当你写文件的时候,你也写日志文件,两个写过程都可以在不同的文化中完成?@Roy T:是的,我知道这是非动态的。但当我面对这样的问题时,我找到了我所写的解决方案。你有不同的建议吗?
public static void Main(string[] args)
{
// Simulated file containing one number per line in fr-CA culture
MemoryStream inputStream = new MemoryStream();
StreamWriter writer = new StreamWriter(inputStream);
writer.WriteLine("2,3");
writer.WriteLine("3,5");
writer.WriteLine("5,7");
writer.Flush();
inputStream.Seek(0, SeekOrigin.Begin);
// Simulated output file that we want in en-CA culture
MemoryStream outputStream = new MemoryStream();
Convert(inputStream, CultureInfo.GetCultureInfo("fr-CA"), outputStream, CultureInfo.GetCultureInfo("en-CA"));
// Print output file
outputStream.Seek(0, SeekOrigin.Begin);
StreamReader reader = new StreamReader(outputStream);
string line;
while ((line = reader.ReadLine()) != null)
{
Console.WriteLine(line);
}
}
public static void Convert(Stream inputStream, CultureInfo inputCulture, Stream outputStream, CultureInfo outputCulture)
{
// Get number format for input and output cultures
NumberFormatInfo inputNumberFormat = inputCulture.NumberFormat;
NumberFormatInfo outputNumberFormat = outputCulture.NumberFormat;
// Setup reader and writer for input and output streams
StreamReader reader = new StreamReader(inputStream);
StreamWriter writer = new StreamWriter(outputStream);
// Read each line of input stream and write to output stream, while preserving culture of thread, input, and output
string line;
while ((line = reader.ReadLine()) != null)
{
// Parse string from input stream to double using input culture
double number = double.Parse(line, inputNumberFormat);
// Debugging/Logging using thread's current culture
Debug.WriteLine(number.ToString("F1"));
// Write double to output stream using output culture
writer.WriteLine(number.ToString("F1", outputNumberFormat));
}
writer.Flush();
}