Search Unity

AppendFormat "0:0.####" is adding commas instead of decimals??? (Latin Brazil)

Discussion in 'Scripting' started by CloudyVR, Oct 17, 2019.

  1. CloudyVR

    CloudyVR

    Joined:
    Mar 26, 2017
    Posts:
    715
    I am generating a CSV file from a script that builds a comma-separated string of float values using the AppendFormat function:
    Code (CSharp):
    1. builder.AppendFormat("{0:0.####},{1:0.####},{2:0.####},{3:0.####},{4:0.####},{5:0.####},",
    2.     myPosition.x,
    3.     myPosition.y,
    4.     myPosition.z,
    5.  
    6.     myRotation.eulerAngles.x,
    7.     myRotation.eulerAngles.y,
    8.     myRotation.eulerAngles.z
    9. );
    But my friend in Brazil just sent me a CSV file created in my application and all of the decimals points are commas!!!

    This causes some serious decoding issues:


    He is using WIndows 10 but he informed me that in Latin languages they use comma as decimal separator. I think Windows is causing this formatring issue.

    Can I force AppendFormat to use a decimal point "." as the separator under all circumstances (regardless of culture)?
     
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,697
    I think you can by using the first overload of that function that takes an IFormatProvider as the first argument to .AppendFormat().

    I didn't see where to get a culture-neutral IFormatProvider but when I googled I landed here, so maybe you can dig further?

    https://docs.microsoft.com/en-us/dotnet/api/system.globalization.cultureinfo?view=netframework-4.8

    EDIT: maybe this?

    https://docs.microsoft.com/en-us/dotnet/api/system.iformatprovider?view=netframework-4.8

    Just ask for an "en_US" cultureinfo all the time??? Not sure what is best future-proofed practice... good luck!
     
    CloudyVR likes this.
  3. mvaz_p

    mvaz_p

    Joined:
    Aug 22, 2018
    Posts:
    80
    I would say the best practice is to use CultureInfo.InvariantCulture as the first parameter, unless you need it to be a specific culture.
     
  4. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,697
    I have googled this and I concur. Thanks!
     
  5. CloudyVR

    CloudyVR

    Joined:
    Mar 26, 2017
    Posts:
    715
    Thanks everyone for those quick responses. I have added the changes by searching through my project and adding the CultureInfo.InvariantCulture directive to each format function in my CSV class.

    I wonder if there is a way to just enforce InvariantCulture globally?


    But for now I have changed my earlier example to something resembling this:
    Code (CSharp):
    1. builder.AppendFormat(CultureInfo.InvariantCulture, "{0:0.####},{1:0.####},{2:0.####},{3:0.####},{4:0.####},{5:0.####},",
    2.     myPosition.x,
    3.     myPosition.y,
    4.     myPosition.z,
    5.  
    6.     myRotation.eulerAngles.x,
    7.     myRotation.eulerAngles.y,
    8.     myRotation.eulerAngles.z
    9. );
    And I was on the lookout for string.format functions too:
    myFloatString = string.Format(CultureInfo.InvariantCulture, "{0}_{1}", float1, float2);


    I wasn't able to find a convenient way to specify InvariantCulture directive on Array.ConvertAll().

    Now I wait, and hope my friend has time to test out the changes :)
     
    Last edited: Oct 17, 2019
  6. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,697
    Well lookie what I just found:

    Code (csharp):
    1. Thread.CurrentThread.CurrentCulture = System.Globalization.CultureInfo.InvariantCulture;
    I found it here:

    https://stackoverflow.com/questions/12729922/how-to-set-cultureinfo-invariantculture-default

    And no, I did not test it. To test it:

    - change the locale of your target device / machine
    - do a regular old AppendFormat() without specifying anything
    - verify you see commas where you want to see periods
    - redo the test but insert the above line before your AppendFormat() call

    Observe results, ensure they are periods as you want.

    And don't forget to switch your locale back.
     
    CloudyVR likes this.
  7. CloudyVR

    CloudyVR

    Joined:
    Mar 26, 2017
    Posts:
    715
    I just attempted this on a Windows 7 machine, and using the exact same application that I sent to my friend.

    I really would like to recreate the issue here, but how do I set Windows to use Latin formatting in Unity?

    I tried both Portuguese (Brazil) and Azeri (Latin, Azerbaijan) system locale settings, but in both instances the decimal separator remained as a period characters.
     
    Last edited: Oct 17, 2019
  8. I don't have Windows 7 anymore, and it was years ago, so I have no idea if this is still true or not (but maybe Google helps?):
    https://answers.microsoft.com/en-us...a-to-dot/953556fb-00d0-45ad-bd4f-6ca8afa5025a
     
  9. CloudyVR

    CloudyVR

    Joined:
    Mar 26, 2017
    Posts:
    715
    Brilliant! Thank you so much, I can confirm this works just fine, case closed. :D

    I was able to reproduce the exact problem too by going to the Format tab in Windows and changing the Format to Protuguese (Brazil). Then in my game running on Windows 7 I saw that it was adding commas for all decimal separators causing CSV corruption:

    I verified Kurt's suggestion using Win7 and running two identical versions of my game where one called:
    Thread.CurrentThread.CurrentCulture = System.Globalization.CultureInfo.InvariantCulture;

    and the other was unmodified.

    The build that set InvariantCulture globally was working perfectly fine (decimal separator = '.').
    The unmodified build was full of bugs and corrupted csv was everywhere (decimal separator = ',').

    An interesting note, in Windows 10 I saw a different result. I changed the format setting (as above) but both builds still ran fine. I also noticed that the Decimal symbol dropdowns differs between the two OSes where Windwos 10 has multiples??

    And when changing only the system locale setting then rebooting, it did not reproduce the issue and both builds ran fine:


    I was not expecting Windows formatting options to be capable of completely wrecking my game, guess it just goes to show how one should always test every possible configuration. And I know from now on I will be including that little line of code in every projects I ever create.

    Thanks again for helping me to solve this!!
     
    Last edited: Oct 17, 2019
  10. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,697
    Yeah, I get where you're coming from but unfortunately more and more of the our game engines rely on passing thickly through the OS, such as video drivers, audio, etc., so an unexpected change in some middleware layer and bam, down we go in flames. I coulda fallen for this same problem I'm sure.

    I'm gonna bet the Win10 problem difference is just because you haven't installed some patch, or else some "locale package" or something, or else your computer OS isn't licensed for those countries, silly stuff like that.

    You're welcome, glad it worked out.
     
    CloudyVR likes this.