We develop an established software which works fine on all known computers except one. The problem is to parse strings that begin with "8". It seems like "8" in the beginning of a string is a reserved character.
Parsing:
int.Parse("8") -> Exception message: Input string was not in a correct format.
int.Parse("80") -> 0
int.Parse("88") -> 8
int.Parse("8100") -> 100
CurrentCulture: sv-SE
CurrentUICulture: en-US
The problem is solved using int.Parse("8", CultureInfo.InvariantCulture). However, it would be nice to know the source of the problem.
Question: Why do we get this behaviour of "8" if we don't specify invariant culture?
Additional information:
I did send a small program to my client achieve the result above:
private int ParseInt(string s)
{
int parsedInt = -1000;
try
{
parsedInt = int.Parse(s);
textBoxMessage.Text = "Success: " + parsedInt;
}
catch (Exception ex)
{
textBoxMessage.Text =
string.Format("Error parsing string: '{0}'", s) + Environment.NewLine +
"Exception message: " + ex.Message;
}
textBoxMessage.Text += Environment.NewLine + Environment.NewLine +
"CurrentCulture: " + Thread.CurrentThread.CurrentCulture.Name + "\r\n" +
"CurrentUICulture: " + Thread.CurrentThread.CurrentUICulture.Name + "\r\n";
return parsedInt;
}
Update
I stumbled across this link, a bug in the microsoft connect database:
https://connect.microsoft.com/VisualStudio/feedback/details/253265/int32-parse-fails-to-convert-the-string-0-zero-on-some-systems
It seems like there's an issue with similiar symptoms, but no real root cause. If anyone could elaborate on this I would be grateful!
For the sv-SE culture 8 represents CurrencyNegativePattern and that's why you're getting the error you describe.
You can check this by running the following example:
var ci = new CultureInfo("sv-SE");
var nfi = (NumberFormatInfo)ci.GetFormat(typeof(NumberFormatInfo));
Console.WriteLine(nfi.CurrencyNegativePattern);
Console.WriteLine(nfi.CurrencyPositivePattern);
This will output:
// 8
// 3
You can explicitly say that you are parsing an integer and not a currency by using the Parse overload that accepts a NumberStyles enumeration.
Int32.Parse("8", NumberStyles.Integer, new CultureInfo("sv-SE"));
This time since you are specifying that you're parsing an integer no error will occur.
However, IIRC the Int32.Parse should interpret the input as an integer by default, so why you're getting to the error with that sample code is beyond me.
Update:
From the information you recently added it seems that you should make sure that the problem is not external. This is, if the user for example changed the positive sign setting of the windows locale to 8 it would be normal and make perfect sense for you to get the error you are obtaining. It would be just like setting the + as the positive sign and then trying to parse it:
var ci = new CultureInfo("sv-SE");
var nfi = (NumberFormatInfo)ci.GetFormat(typeof(NumberFormatInfo));
nfi.PositiveSign = "+";
Int32.Parse("+", nfi); // This will throw
Ask the user for it's locale registry settings like indicated in the Connect issue and check that they are what you would expect.
Side note: Welcome to SO and by the way next time you need to add further information to your question you should edit it instead of providing it in an answer.
Related
I am doing this calculation:
void TESTINGtesting()
{
string aa = "33,9";
//float a1 = float.Parse(aa, CultureInfo.InvariantCulture.NumberFormat);
txt_Slask.text = "(" + aa.ToString() + ") - ";
float a1 = float.Parse(aa.Replace(',', '.'));
print("a1: " + a1);
txt_Slask.text += "++>(";
txt_Slask.text += a1.ToString();
txt_Slask.text += ")";
txt_Slask.text += "<++";
}
I get the following result in the Editor:
And the following result when I upload to my iPhone:
What I am doing is this:
Read in a string with the following format "33.9" (dot)
I am reading the file and the number that comes out is "33,9" (comma) -
As a backup I am trying to convert the "33,9" to "33.9"
When I use the attached code on Editor all is OK but nothing comes up in the UI Text in the iPhone
I have tried with "InvariantCulture" but with the same result.
BTW, my iPhone is Swedish region.
I am puzzled and have not been able to find a solution.
You seem to be dancing around culture and what you're expecting out of the wrong culture.
Let's start with your commented out code, I'm assuming that's an earlier attempt that (predictably) failed:
string aa = "33,9";
float a1 = float.Parse(aa, CultureInfo.InvariantCulture.NumberFormat);
The invariant culture in .Net is en-us, and your number in that culture would be represented as 33.9, not 33,9. And so your conversion fails.
Then you threw things at the compiler until you finally got the result you want:
float.Parse(aa.Replace(',', '.'))
However, if you enable the C# static analysis package, you'll get a warning on that line saying that you need to pass the culture to the function, because strings get converted differently to numbers in different cultures.
Specifically, you mentioned your phone is under a Swedish culture, which expects a comma as a decimal separator, which you are thoughtlessly replacing with the line above.
What happens next is up to your framework. I'm assuming an exception is generated and it's ignored, but your stack is unwound, so the rest of your function doesn't run anymore.
Long story short, stick to a specific culture for string representations of numbers in code (invariant is fine), and whenever you do the conversion of these strings, use the correct culture.
string aa = "33.9";
float a1 = float.Parse(aa, CultureInfo.InvariantCulture);
Well it seems I finally solved the problem so thank you for help.
void TESTINGtesting()
{
Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo("en-US");
Thread.CurrentThread.CurrentCulture = CultureInfo.GetCultureInfo("en-US");
string aa = "33,9";
txt_Slask.text = "B(" + aa.ToString() + ") - ";
aa = aa.Replace(',', '.');
float a1 = float.Parse(aa);
txt_Slask.text += "++>(";
txt_Slask.text += a1.ToString();
txt_Slask.text += ")";
txt_Slask.text += "<++";
}
I added a function to my application recently that reads a date from a downloaded file and finds the difference in days between current date and the date from the file. When done, it is displayed in a label in one of my forums.
There is an exception: if the string in the file equals "Lifetime", it should not process it as a date and follow alternate logic. But when I try to check if the string is "Lifetime", it does not return true, even if the string = "Lifetime".
EDIT: I fixed the FormatException with help from Nisarg. Now, my labels aren't changing to the values. This is the problem.
EDIT2: I feel stupid. I found out that I was initiating Main twice in one function, then using main1 to switch between forms and main to set the labels.
This is why the labels weren't working right. Thanks Nisarg and all other contributors.
Code example:
string subScript = File.ReadAllText(Path.GetTempPath() + txtUsername.Text + ".txt");
Main main = new Main();
double dSubLeft;
main.dateLabel.Text = subScript;
if (subScript == "Lifetime") // it bypasses this, apparently blank
{
main.daysLeftLabel.Text = "Expires: Never";
}
if (subScript != "Lifetime") //Goes here and throws error saying subScript is not valid DateTime
{
dSubLeft = Math.Round(Convert.ToDouble(Convert.ToString(((Convert.ToDateTime(subScript)) - DateTime.Now).TotalDays)));
string sSubLeft = Convert.ToString(dSubLeft);
main.daysLeftLabel.Text = "Expires: " + sSubLeft + " Days";
}
While using files you often get trailing blank spaces or newline characters. Try trimming the string before comparing it to Lifetime:
subScript = subScript.Trim().Trim(Environment.NewLine.ToCharArray());
Another (less likely) problem could be with the comparison itself. In C# the comparison in case-sensitive. So if you're comparing lifetime with Lifetime they are considered unequal. You should rather use case-insensitive comparison:
if(string.Equals(subScript, "Lifetime", StringComparer.OrdinalIgnoreCase))
OR
if(subScript.ToLower() == "lifetime")
You could also check if the subScript you are getting from the file is a valid date or not using DateTime.TryParse.
string subScript = File.ReadAllText(Path.GetTempPath() + txtUsername.Text + ".txt");
Main main = new Main();
double dSubLeft;
main.dateLabel.Text = subScript;
DateTime subScriptDate;
if(!DateTime.TryParse(subScript, out subScriptDate))
{
main.daysLeftLabel.Text = "Expires: Never";
}
else //Goes here and throws error saying subScript is not valid DateTime
{
dSubLeft = Math.Round(Convert.ToDouble(Convert.ToString((subScriptDate - DateTime.Now).TotalDays)));
string sSubLeft = Convert.ToString(dSubLeft);
main.daysLeftLabel.Text = "Expires: " + sSubLeft + " Days";
}
I think it is because main is the starting point of a program in C#, make another methodname if you donĀ“t want it to reset things from where the program is supposed to start from
That is my guess only, make a breakpoint in the beginning of your code and check through what info you get from each row in the code
Almost certainly, the actual content of the string is not actually the string "Lifetime". Probably because of white-space on either side. Try trimming.
Relevant edit:
if (subscript.Trim() == "Lifetime")
{
main.daysLeftLabel.Text = "Expires: Never";
}
else // don't retest for the opposite condition
{
...
As you can see, this thing is awfully fragile, because the string could still be many things that aren't a valid DateTime. Smells like homework, but there you go...
i think you should use
if(string.Equals(subScript, "Lifetime", StringComparer.OrdinalIgnoreCase))
{
//statement
}
else
{
//statement
}
I have a string variable called reason for failure which contains user added text for instance the following:
({0}) on arm ({1}} (82) Kits
Now this variable is part of a method where I am using string.format. I need the string.format to not confuse with {0} {1} in the text of the above variable because I am getting the the exception, Input string was not in correct format
The reason you're getting the exception, The input string is not in the correct format is due to the way you're constructing the string. In your variable you have two closing braces where string.Format expects only one: on arm ({1}}. If you add this variable as a parameter to String.Format as shown in the first example below, it should resolve this issue.
Otherwise, if you are saying that the variable serviceEntry.ReasonForFailure contains the characters {0} and {1}, and that when you place this variable inside a String.Format, those characters are being replaced by the String.Format arguments, then this is by design, at least the way you're constructing your string.
Instead of inserting your variable in the string using the + operator, include it as another parameter to the String.Format call. This way, the {0} in your variable will be preserved.
message.Body = string.Format(
"<html><body>Request is complete<br/>" +
"Service Request initiated by you is Complete<br/>" +
"Please use the following link to access " +
"{0}{1}<br/>" +
"Reason For Failure: {2}<br/></body></html>",
RunLogURL, runLogID, serviceEntry.ReasonForFailure);
Now, if you want to replace the {0} and {1} in serviceEntry.ReasonForFailure with some other values, you can nest a String.Format inside another:
serviceEntry.ReasonForFailure = "10003 Insufficient Liquid Level detected at " +
"pipettor channel ({0}) on arm ({1}) (82)";
var channelId = 87;
var armId = 42;
message.Body = string.Format(
"<html><body>Request is complete<br/>" +
"Service Request initiated by you is Complete<br/>" +
"Please use the following link to access " +
"{0}{1}<br/>" +
"Reason For Failure: {2}<br/></body></html>",
RunLogURL, runLogID,
String.Format(serviceEntry.ReasonForFailure, channelId, armId));
Or you can do it in two operations:
serviceEntry.ReasonForFailure = "10003 Insufficient Liquid Level detected at " +
"pipettor channel ({0}) on arm ({1}) (82)";
var channelId = 87;
var armId = 42;
var reasonForFailure = String.Format(serviceEntry.ReasonForFailure, channelId, armId);
message.Body = string.Format(
"<html><body>Request is complete<br/>" +
"Service Request initiated by you is Complete<br/>" +
"Please use the following link to access " +
"{0}{1}<br/>" +
"Reason For Failure: {2}<br/></body></html>",
RunLogURL, runLogID, reasonForFailure);
The problem is that your variable serviceEntry.ReasonForFailure contains a format item. If don't want them to be treated as format items you'll have to escape them with an extra set of braces. For instance: {0} becomes {{0}} as explained here.
The quick and dirty solution to your problem would be to replace all opening and closing braces by a double brace:
"Reason For Failure:" + serviceEntry.ReasonForFailure.Replace("{","{{").Replace("}","}}") + "<br/>"
A better solution would be to do the replacement using a regular expression:
public string EscapeCurlyBraces(string value)
{
string strRegex = #"(\{\d+\})";
Regex myRegex = new Regex(strRegex, RegexOptions.None);
string strReplace = #"{$1}";
return myRegex.Replace(value, strReplace);
}
And then use it like this:
"Reason For Failure:" + EscapeCurlyBraces(serviceEntry.ReasonForFailure) + "<br/>"
Update
I suggest you ditch the current solution and rewrite it using a StringBuilder:
var emailBody = new StringBuilder();
emailBody.Append("<html><body>RSLMS - Service Request is complete<br/>");
emailBody.Append("Service Request initiated by you is Complete <br/>");
emailBody.AppendFormat("Please use the following link to access Run Log Entry {0}{1}<br/>", RunLogURL, runLogID);
// ommited some lines
emailBody.AppendFormat("Service ID: {0}<br/><br/>", serviceEntry.ID.ToString());
// ommited some lines
emailBody.AppendFormat("Reason For Failure: {0}<br/><br/>", serviceEntry.ReasonForFailure);
emailBody.Append("Thank you <br/> RSLMS Administrator <br/></body></html>");
message.Body = emailBody.ToString();
Since you have two String.Format, you didnt provide parameter for the external , lets say you have x and y for the external Format, this is what you need to do. You need to do double curly braces for those you want to escape from the inner format as in :
var reasonForFailure = "({{0}}) on arm ({{1}}) (82) Kits should still have 50 tests left after run, but it seems like the instrument is not able to pipette anymore from the kits.";
var message = string.Format(string.Format(
"<html><body>Request is complete<br/>" +
"Service Request initiated by you is Complete" + " <br/> " +
"Please use the following link to access {0}{1} <br/>" +
"Reason For Failure: " + reasonForFailure+"<br/>" +
"</body></html>", RunLogURL, runLogID),x,y);
I take data from four different pages and different domains.
1- .com
2- .co.uk
3- .ca
4- .co.jp
For all of the above i take number from Html and Convert them to Double using line:
string lowestSellerPrice = (Convert.ToDouble(fbalPrice) +
Convert.ToDouble(fbalsPrice)).ToString();
This works perfectly fine for the first 3 domains but for .co.jp even though there is always a number in fbalPrice and fbalsPrice it is always giving exception :
Input string was not in a correct format
Any suggestion as i have been struggling with this for too long now no result i also tried the try parse solution but no luck.
UPDATE:
See this:
I solved it like this :
The string were like " 1234" and " 111" and i then did Replace(" ",""); . And only number lift this however did not work so i did this:
if (fbalPrice.Contains(" "))
{
fbalPrice = fbalPrice.Remove(0, fbalPrice.IndexOf(" ") + 1).Replace(",","").Trim();
}
if(fbalsPrice.Contains(" "))
{
fbalsPrice = fbalsPrice.Remove(0, fbalsPrice.IndexOf(" ") + 1).Replace(",", "").Trim();
}
And then added them and it worked.
I want to submit a pig job with the .NET SDK to HDInsight (but it also happens when I submit it with PowerShell, tested that already). Using following Statement:
string queryString = "REGISTER wasb:///PigTestFolder/myudfs.jar;" +
" A = LOAD 'wasb:///PigTestFolder/wordlist.txt' USING PigStorage()AS Line:chararray;" +
" B =ORDER A BY Line asc;" +
" D= Limit B 20;" +
" Dump D;" +
" STORE D INTO 'wasb:///PigTestFolder/results/' USING PigStorage ('\t');";
When I remove the STORE command everything works perfectly fine. But Storing the result to the BLOB is a pain in the arse. It say in the error log: "AS was unexpected at this time". But if I remove the schema and define the column with $0 it says: B was unexpected at this time.
The following Code prints out: Dump unexpected at this time.
string queryString = " A = LOAD 'wasb:///PigTestFolder/wordlist.txt' USING PigStorage();" +
" Dump A;" +
" STORE A INTO 'wasb:///PigTestFolder/results/' USING PigStorage ('\t');";
I tested the code with the Hortonworks Sandbox and it works. No problem. Another mystery is, when using only the following two lines of PigLatin code it works as well:
string queryString = " A = LOAD 'wasb:///PigTestFolder/wordlist.txt' USING PigStorage();" +
"STORE D INTO 'wasb:///PigTestFolder/results/' USING PigStorage ('\t');";
Does anyone have any idea what I am doing wrong?