Reputation: 13620
Im trying to open a file. Here is my output (string i build up in try/catch):
Error opening c:\Program Files (x86)\MyApp\storedUsers.txt -> System.FormatException -> Input string was not in a correct format.
And here is how im opening it:
installPath = @"C:\Program Files (x86)\MyApp\";
FileStream userFile = new FileStream(installPath + "storedUsers.txt", FileMode.OpenOrCreate, FileAccess.Read);
StreamReader userStream = new StreamReader(userFile);
while (userStream.Peek() >= 0)
{
string line = userStream.ReadLine();
storedUsers.Add(line.Split(',')[0], int.Parse(line.Split(',')[0]));
}
userStream.Close();
My catch:
WriteToLogFile("Error opening " + installPath + "storedUsers.txt -> " + ex.GetType() + " -> " + ex.Message);
I cant wrap my head around whats wrong...
Upvotes: 1
Views: 871
Reputation: 3224
I think you should start with a checklist (or test cases), like:
Does the file exist? I am assuming here - yes.
Am I opening the file to read or write? If only read, then don't use FileMode.OpenOrCreate
, but FileMode.Open
.
What does string line
contain?
a) Is it blank?
4) What is the result of Split
function call?
a) Is it null?
b) Are you accepting empty entries in this array?
c) Are there entries more than 0?
Then, avoid repeating code, if possible.
//Pseudo-code + C#
string line = userStream.ReadLine();
string[] arr = line.Split(','); //called once
if (arr.Length > 0 && arr[0].Trim().Length > 0) storedUsers.Add(arr[0], int.Parse(arr[0]));
//you can put extra checks.
Upvotes: 0
Reputation: 391634
I'm going to hazard a guess here, since you haven't given us enough to really give you a solid answer.
I bet the problem is the parsing of that line part, this expression:
int.Parse(line.Split(',')[0])
That this doesn't, in all cases, actually give you a number.
So you should look at the file, and possibly change the code to this:
string[] parts = line.Split(',');
... int.Parse(parts[0]) ...
Then you can inspect the contents of that array to see what is really in that first column.
As noted in the comments, a better approach would be to not blindly assume the parsing will succeed, and additionally you would probably want to ensure you're using the right cultural information.
Here's what I would do, assuming the numbers are output by a program, for reading into another program:
int value;
if (Int32.TryParse(parts[0], NumberStyles.Integer, CultureInfo.InvariantCulture, out value))
... your code here, use value where you need it
else
what to do in the case of unable to parse the string as a number
On a hunch, do you need to trim the contents? Try this simple change:
... int.Parse(line.Split(',')[0].Trim()) ...
^--+--^
|
+-- add this
Other tips:
Use Path.Combine
to combine paths:
new FileStream(Path.Combine(installPath, "storedUsers.txt")
Rewrite your reading loop to this:
string line;
while ((line = userStream.ReadLine()) != null)
{
...
}
Use the using
clause for disposing of your stream:
using (FileStream userFile = new FileStream(...))
{
...
}
// delete the .Close() line, this is handled by the } on the preceeding line
Final version:
installPath = @"C:\Program Files (x86)\MyApp\";
using (FileStream userFile = new FileStream(
Path.Combine(installPath, "storedUsers.txt"),
FileMode.OpenOrCreate, FileAccess.Read))
using (StreamReader userStream = new StreamReader(userFile))
{
string line;
while ((line = userStream.ReadLine()) != null)
{
string[] parts = line.Split(',');
int userId;
if (Int32.TryParse(parts[0], NumberStyles.Integer, CultureInfo.InvariantCulture, out userId))
storedUsers.Add(userId);
}
}
Of course, if the file isn't too big, you can rewrite the whole shebang using a bit of LINQ:
// warning, LINQ with side-effects, evaluate here, don't use it lazily
int tempUserId = 0;
List<int> userIds = File
.ReadAllLines(Path.Combine(installPath, "storedUsers.txt"))
.Select(l => l.Split(',')[0])
.Where(p0 => Int32.TryParse(p0, NumberStyles.Integer, CultureInfo.InvariantCulture, out tempUserId))
.Select(dummy => tempUserId)
.ToList();
Upvotes: 5