Writing flat file US Culture, whether Assembly is loaded into diffrent culture
I have a class library that read a flat file written from a Delphi legacy application then process the data and writes back the flat file.
Problem comes when user have different culture of OS and also we have localized that dll to write localized strings to flat file.
Problem comes when we write double valves according to culture i.e. 1,60 instead of 1.60. As legacy application have ',' as separator we cannot write 1,60.
Is there a way we always write double values in En-US culture.
Also, side by side we are converting Delphi application to C#. I am thinking let a person with Romanian culture creates a file that will have 1,25 as double value and when it is sent to a US culture people his assem开发者_如何学Pythonbly will expect 1.25 so will that crash in trying to convert from string to double. So in that case also always writing and reading from a En-US culture file will help, what you guys say?
You can set the localization of the current thread so that it will follow your chosen localization rules.
Use this:
Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");
CultureInfo oldCulture = Thread.CurrentThread.CurrentCulture;
Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");
//make your process in here. It will be in en-US culture
Thread.CurrentThread.CurrentCulture = oldCulture; // then return your original culture
If you don't want to track the culture your files were written, then an option is as you imply, use a uniform format within your file for numbers regardless of culture. To accomplish this goal, you can use functions that accept IFormatProvider as a parameter. These functions include (but are not limited to) Parse, TryParse, and ToString for most data types. This way, you don't have to change your thread's culture, but can still read or write in another culture.
// 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));
}
However, if you are generally writing flat files in multiple cultures, then you really should be marking them with the culture they were written, whether it be in the file name or within the file header. That way you can import based on the culture of the file. This is standard practice for any type of file with multiple encodings.
This may also be beneficial if the files are human-readable, thus preserving what each culture expects to see, rather than choosing one culture and making everyone else conform to it.
The idea remains the same in using functions that accept an IFormatProvider parameter, such as the following:
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();
}
I realize this question was asked awhile back, and the original poster may not even need this anymore, but I also don't see any acceptable answers. And since I had a similar issue to the original poster's problem, I figured I'd post the answer I discovered.
精彩评论