开发者

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜