How can I make this universal, so whether it is a dot or comma my program
will not crash?
Also, if I wrote floats back to the file, how do I handle it universally?
I am really hoping there is some easy way to do this and dont have to have
if then code branches...
It's easy to keep your program from crashing. Just check for the error
instead of letting it take your program down.
As far as handling the format goes, that really depends on how lenient
you want to be. One approach would be to always replace commas with
periods before trying to parse the data. But that obviously assumes the
input string will _always_ use _either_ commas or periods for decimal
separators, and will have _no_ other separators (e.g. thousands).
An alternative approach would be to allow the user to specify the
culture for the file by name, so that you can use the appropriate
culture during parsing (using a parse overload that allows you to pass
the culture in).
Yet another alternative would be to just ask the user "commas or
periods" and choose your parsing based on that (this may require using
TryParseExact() so you can supply an exact format...that may or may not
work well with the data as it's formatted in the file, but is certainly
worth a try).
Of course, you don't say what the source of the file is. But if it's
emitted only by your own code, you could simply always write the file
using the InvariantCulture culture, or you could write the name of the
culture into the file somewhere so that you know what culture to use
when parsing it (the former being preferable for files intended only for
machine consuption, the latter probably being preferable if you expect
humans to be reading the file).
> Also, if I wrote floats back to the file, how do I handle it universally?
That depends entirely on what other consumers of the file you expect
there to be and how much control you have over the file format.
> I am really hoping there is some easy way to do this and dont have to have
> if then code branches...
You certainly should be able to do it without an effusion of if/then
statements.
Unfortunately, without more specifics about the source of the data and
how you want it to be used, I can't offer much more than the above.
Pete
It is a good practice that everything stored or transfered between
applications (in files or some communication protocol) should be
locale-independent.
For .NET you should use the InvariantCulture (for read and write):
http://msdn.microsoft.com/en-us/library/4c5zdc6a.aspx
--
Mihai Nita [Microsoft MVP, Visual C++]
http://www.mihai-nita.net
------------------------------------------
Replace _year_ with _ to get the real email
I needed to do:
float.Parse(
val,
System.Globalization.NumberStyles.AllowDecimalPoint,
System.Globalization.CultureInfo.InvariantCulture
);
That's not consistent with the question you asked. But, whatever.
That will still not parse floats that were written with a culture
setting that uses comma as decimal separator.
The AllowDecimalPoint value may be a bit misleading, what it does is to
allow a decimal separator in the string, the decimal separator is
specified in the number style (culture).
The invariant culture uses a period as decimal separator, it doesn't
allow either a comma or a period as separator.
You might want to consider using the round-trip format for writing the
floats to the file:
file.Write(number.ToString("R", CultureInfo.InvariantCulture));
This will ensure that the value will be exactly the same when it's parsed.
--
Göran Andersson
_____
http://www.guffa.com
What I was doing at first worked simply like so: There is a .txt file where my data is kept. Like "materials.txt" for example. The program reads in the data line by line, and looks for tags. So the line "[DENSITY] 7.874" tells the program it needs to work on the density variable. (Because line.StartsWith("[DENSITY]").) It clips off that tag, and simply has a string named 'line' with the data I need, "7.874".
However, a lot of users that I assume are not in America or have weird settings are having problems at the specific line of "density = float.Parse(line);". One user manually edited the text file to replace all periods with commas, and it worked on his system. So the issue is that float.Parse is autocorrecting by region, and no one seems to be able to have a simple way of telling it not to change by region.
There's System.Globalization.CultureInfo.InvariantCulture. And wow is that a long one. But the problem there is that NOW it's having a problem reading floats with a negative sign. The furthest any of this has helped, even though it still doesn't work. So I'll tell you what I did.
That "density = float.Parse(line);" line, and in fact every time I read in a float, is wrapped in a try-catch block. I hate using those for regular control, but it's the only good way I can think of to do this. If the first try fails, the catch block attempts "density = float.Parse(DecimalSwitch(line));", where DecimalSwitch(string s) is a method I wrote. It's hackish and I hate it.
DecimalSwitch(string s) takes the string and turns it into a character array c. I then go through each character in that array and toggle it from either '.' to ',' or ',' to '.'. Not with a foreach loop because foreach loops don't like you actually doing anything to the data you're working with. I have to manually get the length of the array and do a regular for loop using that because for loops don't care until they actually hit a problem where they can't continue. Anyway, once all the ',' and '.' are toggled, it returns the character array as a string.
I know I sound angry, but I've just wasted yet another hour of dev time because apparently it isn't a problem common enough for people to come out and say clearly how to fix it, and instead complain about the answers that come close to doing something. Programming in C# by the way.
> On Friday, November 06, 2009 11:21 PM trant wrote:
> I have a program which parses float values from a file. European users are
> getting an error because their floats use commas instead of dots.
>
> How can I make this universal, so whether it is a dot or comma my program
> will not crash?
>
> Also, if I wrote floats back to the file, how do I handle it universally?
>
> I am really hoping there is some easy way to do this and dont have to have
> if then code branches...
>> On Friday, November 06, 2009 11:58 PM Peter Duniho wrote:
>> trant wrote:
>>
>> it is easy to keep your program from crashing. Just check for the error
>> instead of letting it take your program down.
>>
>> As far as handling the format goes, that really depends on how lenient
>> you want to be. One approach would be to always replace commas with
>> periods before trying to parse the data. But that obviously assumes the
>> input string will _always_ use _either_ commas or periods for decimal
>> separators, and will have _no_ other separators (e.g. thousands).
>>
>> An alternative approach would be to allow the user to specify the
>> culture for the file by name, so that you can use the appropriate
>> culture during parsing (using a parse overload that allows you to pass
>> the culture in).
>>
>> Yet another alternative would be to just ask the user "commas or
>> periods" and choose your parsing based on that (this may require using
>> TryParseExact() so you can supply an exact format...that may or may not
>> work well with the data as it is formatted in the file, but is certainly
>> worth a try).
>>
>> Of course, you do not say what the source of the file is. But if it is
>> emitted only by your own code, you could simply always write the file
>> using the InvariantCulture culture, or you could write the name of the
>> culture into the file somewhere so that you know what culture to use
>> when parsing it (the former being preferable for files intended only for
>> machine consuption, the latter probably being preferable if you expect
>> humans to be reading the file).
>>
>>
>> That depends entirely on what other consumers of the file you expect
>> there to be and how much control you have over the file format.
>>
>>
>> You certainly should be able to do it without an effusion of if/then
>> statements.
>>
>> Unfortunately, without more specifics about the source of the data and
>> how you want it to be used, I cannot offer much more than the above.
>>
>> Pete
>>> On Saturday, November 07, 2009 4:36 AM Mihai N. wrote:
>>> It is a good practice that everything stored or transfered between
>>> applications (in files or some communication protocol) should be
>>> locale-independent.
>>> For .NET you should use the InvariantCulture (for read and write):
>>> http://msdn.microsoft.com/en-us/library/4c5zdc6a.aspx
>>>
>>>
>>> --
>>> Mihai Nita [Microsoft MVP, Visual C++]
>>> http://www.mihai-nita.net
>>> ------------------------------------------
>>> Replace _year_ with _ to get the real email
>>>> On Saturday, November 07, 2009 10:23 AM trant wrote:
>>>> Nevermind friends, I found out the answer later.
>>>>
>>>> I needed to do:
>>>>
>>>> float.Parse(
>>>> val,
>>>> System.Globalization.NumberStyles.AllowDecimalPoint,
>>>> System.Globalization.CultureInfo.InvariantCulture
>>>> );
>>>>> On Saturday, November 07, 2009 1:39 PM Peter Duniho wrote:
>>>>> trant wrote:
>>>>>
>>>>> That's not consistent with the question you asked. But, whatever.
>>>>>> On Saturday, November 07, 2009 1:44 PM G?ran Andersson wrote:
>>>>>> trant wrote:
>>>>>>
>>>>>> That will still not parse floats that were written with a culture
>>>>>> setting that uses comma as decimal separator.
>>>>>>
>>>>>> The AllowDecimalPoint value may be a bit misleading, what it does is to
>>>>>> allow a decimal separator in the string, the decimal separator is
>>>>>> specified in the number style (culture).
>>>>>>
>>>>>> The invariant culture uses a period as decimal separator, it does not
>>>>>> allow either a comma or a period as separator.
>>>>>>
>>>>>>
>>>>>> You might want to consider using the round-trip format for writing the
>>>>>> floats to the file:
>>>>>>
>>>>>> file.Write(number.ToString("R", CultureInfo.InvariantCulture));
>>>>>>
>>>>>> This will ensure that the value will be exactly the same when it is parsed.
>>>>>>
>>>>>> --
>>>>>> G??ran Andersson
>>>>>> _____
>>>>>> http://www.guffa.com
>>>>>> Submitted via EggHeadCafe - Software Developer Portal of Choice
>>>>>> Book Review: Google Analytics
>>>>>> http://www.eggheadcafe.com/tutorials/aspnet/a855a620-50a8-487c-9fac-b85f8fda2442/book-review-google-analytics.aspx
Try (you'll need to add a using for System.Globalization):
float.Parse(
val,
NumberStyles.Float,
CultureInfo.InvariantCulture
);
--
Tom Shelton