StreamReader NullReferenceException - c#

I'm making a function that will get the number of lines from a StreamReader excluding comments (lines which starts with '//') and new lines.
This is my code:
private int GetPatchCount(StreamReader reader)
{
int count = 0;
while (reader.Peek() >= 0)
{
string line = reader.ReadLine();
if (!String.IsNullOrEmpty(line))
{
if ((line.Length > 1) && (!line.StartsWith("//")))
{
count++;
}
}
}
return count;
}
My StreamReader's data is:
// Test comment
But I'm getting an error, 'Object reference not set to an instance of an object.' Is there any way to fix this error?
EDIT
Turns out this occurs when my StreamReader is null. So with musefan and Mr. Smith's suggested code, I came up with this:
private int GetPatchCount(StreamReader reader, int CurrentVersion)
{
int count = 0;
if (reader != null)
{
string line;
while ((line = reader.ReadLine()) != null)
if (!String.IsNullOrEmpty(line) && !line.StartsWith("//"))
count++;
}
return count;
}
Thanks for the help!

There is no need to Peek(), this may actually be the problem too. You can just do this:
string line = reader.ReadLine();
while (line != null)
{
if (!String.IsNullOrEmpty(line) && !line.StartsWith("//"))
{
count++;
}
line = reader.ReadLine();
}
Of course if you StreamReader is null then you have a problem, but you example code alone is not enough to determine this - you need to debug it. There should be plenty of debugging information for you to work out which object is actually null

Sounds like your reader object is null:
You can check if the reader is null by doing:
if (reader == null) {
reader = new StreamReader("C:\\FilePath\\File.txt");
}

Slightly neater variant of musefan's suggested code; just a single ReadLine() code. +1 for suggesting the removal of the Length check btw.
private int GetPatchCount(StreamReader reader)
{
int count = 0;
string line;
while ((line = reader.ReadLine()) != null)
if (!String.IsNullOrEmpty(line) && !line.StartsWith("//"))
count++;
return count;
}

Your code is not enough information to resolve your problem. I have made a small application with VS 2010 base on my assume and it work well. I believe your code get problem with streamReader. If the streamReader is null your code will throw 'Object reference not set to an instance of an object.'
You should check the streamReader is not null and make sure the streamReader are available.
You can reference code below. With make sure the TextFile1.txt existing at D:\
Hope this help.
namespace ConsoleApplication1
{
using System;
using System.IO;
class Program
{
static void Main(string[] args)
{
using (StreamReader streamReader = new StreamReader(#"D:\\TextFile1.txt"))
{
int count = GetPatchCount(streamReader);
Console.WriteLine("NUmber of // : {0}", count);
}
Console.ReadLine();
}
private static int GetPatchCount(StreamReader reader)
{
int count = 0;
while (reader.Peek() >= 0)
{
string line = reader.ReadLine();
if (!String.IsNullOrEmpty(line))
{
if ((line.Length > 1) && (!line.StartsWith("//")))
{
count++;
}
}
}
return count;
}
}
}

Related

Check if a String contains something between quotes

I am writing I application where the user can input a document. Then I read each line of the Document and work further with the attributes.
In Each line we have 5 attributes. The Attributes get separated by a semicolon.
For Example:
If a Attribute have a semicolo in his name the user will input the attribute then so in the Document:
"test;with"
Now I want to check if the attribute is in quotes and ignore it. How would you guys do it?
Here is the important code snippet:
foreach (string line in lines)
{
if (line == "")
{
continue;
}
if (lineindex > lines.Length)
{
continue;
}
lineindex++;
string[] words = line.Split(';'); // i would add here a if statement
foreach (string word in words)
{
count++;
if (count == 6)
{
attribNewValue = "";
maskName = "";
actualAttrbValue = "";
actualAttrbName = "";
attribNameForEdit = "";
count = 1;
maskexist = false;
attribexist = false;
}
else
{
// Or here to each word
if (count == 1)
{
maskName = word;
}
else if (count == 2)
{
actualAttrbName = word;
}
else if (count == 3)
{
actualAttrbValue = word;
}
else if (count == 4)
{
attribNameForEdit = word;
}
else if (count == 5)
{
attribNewValue = word;
}
}
Thank you in advance!
You can use String.IndexOf(char value) and String.LastIndexOf(char value) to determine this:
string[] words;
int semicolonIndex = line.IndexOf(';');
int firstQuoteIndex = line.IndexOf('"');
int lastQuoteIndex = line.LastIndexOf('"');
if (firstQuoteIndex == lastQuoteIndex)
continue;
if (semicolonIndex > firstQuoteIndex && semicolonIndex < lastQuoteIndex)
words = line.Split(';');
More information:
IndexOf(): https://msdn.microsoft.com/en-us/library/system.string.indexof(v=vs.110).aspx
LastIndexOf(): https://msdn.microsoft.com/en-us/library/system.string.lastindexof(v=vs.110).aspx
As one of the comments mentioned, this can also be achieved with regular expressions in far fewer lines of code than my solution, but gauging your skill level (no offense) I think this is easier for you to read, understand, and get started with. Regardless of whether or not there is a more elegant solution, string manipulation is a pretty basic things and it would be good to familiarize yourself with all of the methods on the String class as found here: https://msdn.microsoft.com/en-us/library/system.string_methods(v=vs.110).aspx
Lastly, while this is purely developer-preference, I would recommend using String.Empty instead of "". This makes your code's intentions more explicit to other readers / developers. By using "", one might ask "Well did they MEAN to use an empty string, or did they make a typo and aren't assigning what they think they're assigning?" By using String.Empty, there is no question that you meant to use an empty string. So I would do if (line == String.Empty) continue; instead of if (line == "") continue;

I want to read text files from a folder?

In the code Below:
I read from just one text file, but i want to read from multiple files in a folder and then assign the variables and create a new instance of appointment for each file??
public bool Load()
{
DateTime start = new DateTime(2000,01,01);
int length = 0;
string screenDiscription = "";
string line;
int i = 1;
StreamReader sr = new StreamReader("Appointments.txt");
if (!File.Exists("Appointments.txt"))
{
return true;
}
while ((line = sr.ReadLine()) != null)
{
if (i % 4 == 1)
{
start = DateTime.ParseExact(line, "dd/MM/yyyy HHmm", CultureInfo.CreateSpecificCulture("en-GB"));
}
if (i % 4 == 2)
{
length = int.Parse(line);
}
if (i % 4 == 3)
{
screenDiscription = line;
apps.Add(new Appointment(start, length, screenDiscription));
}
i++;
}
sr.Close();
return true;
}
To get the all the files in a directory use the function System.IO.Directory.GetFiles("directoryPath");
Read this page for the documentation
https://msdn.microsoft.com/en-us/library/system.io.directory(v=vs.110).aspx

How to skip multiple iterations in a while loop

I'm reading a text file line by line in a While loop. When I reach a specific line I want to skip the the current and the next 3 iterations.
I guess I can do it using a counter and things like that. But I was wondering if there is a more elegant way?
using (var sr = new StreamReader(source))
{
string line;
while ((line = sr.ReadLine()) != null)
{
if (line == "Section 1-1")
{
// skip the next 3 iterations (lines)
}
}
}
Have a for loop to execute sr.ReadLine 3 times and discard the result like:
using (var sr = new StreamReader(source))
{
string line;
while ((line = sr.ReadLine()) != null)
{
if (line == "Section 1-1")
{
for (int i = 0; i < 3; i++)
{
sr.ReadLine();
}
}
}
}
You should check for sr.ReadLine returning null or if the stream has come to an end.
You can use File.ReadAllLines with method extesions:
public static IEnumerable<string> SkipLines(string file, string line, int count)
{
var enumerable = File.ReadLines(file).GetEnumerator();
while (enumerable.MoveNext())
{
var currentLine = enumerable.Current;
if (currentLine == line)
{
var currentCount = 0;
while(enumerable.MoveNext() && currentCount < count)
{
currentCount += 1;
}
}
yield return currentLine;
}
}
usage:
foreach (var line in SkipLines(source, "Section 1-1", 3))
{
// your line
}
Keep in mind: ReadLines is lazy - not all lines are loaded into memory at once.
Make yourself a function that discards a given number of lines (DiscardLines) and use it:
string line;
while ((line = sr.ReadLine()) != null)
{
if (line == "Section 1-1")
{
DiscardLines(sr, 3);
}
}
That keeps the main loop very simple. The counter is now hidden in DiscardLines.
using (var sr = new StreamReader(source))
{
string line;
int linesToSkip = 0;
while ((line = sr.ReadLine()) != null)
{
if (linesToSkip > 0)
{
linesToSkip -= 1;
continue;
}
if (line == "Section 1-1")
{
// skip the next 3 iterations (lines)
linesToSkip = 3;
}
}
}

Counting the number of words from a file

A word in this context is defined is a letter or a number. However, something like \n is not considered a word.
Below in my code I am trying to count the number of words in a file but at the for loop's local variable declaration I get the error Null Reference exception.
I am not sure why I get this error. I get the variable Line equal to null which shouldn't happen because the text file DOES have one word "hello world" in it..
StreamReader sr = new StreamReader(filePath);
while (sr.ReadLine()!=null)
{
Line =sr.ReadLine();
for (**int i = 1**; i < (Line.Length+1); i++)
{
if (Char.IsLetterOrDigit(Line[i]) == true && Char.IsLetterOrDigit(Line[i - 1]) == true)
{
if (LetterRecent == false)
{
wordCount = wordCount + 1;
}
LetterRecent = true;
}
else
{
LetterRecent = false;
}
}
}
sr.Close();
You're doing ReadLine() twice for each line.
You could do something like:
count = 0;
while (line = sr.ReadLine()) {
char oldChar = 0;
for (char c in line) {
if (c != oldChar && Char.IsLetterOrDigit(c)) count++;
oldChar = c;
}
}
You are discarding half of the lines in the file by calling sr.ReadLine() twice. If you read the last line of the file in the while statement, the call to Line.Length will throw the null reference exception.
Try something this:
var wordCount = 0;
var line = sr.ReadLine();
while( line != null ) {
for( var i = 1; i < line.Length; i++ ) {
// Count words
}
line = sr.ReadLine();
}
You need to declare wordCount before using it.
Int wordCount = 0;
while (sr.ReadLine()!=null)
{
Update your loop condition to be like this:
while (sr.Peek() >= 0)
{
Line = sr.ReadLine();
}

c# Get array index id

Not sure if am on the right track but I want to find a index id of an array and check if it's equal to another id then display a message. it not working for some reason.
int _findID = 1;
using (StreamReader reader = new StreamReader("textfile.txt"))
{
string line = reader.ReadLine();
while (line != null)
{
string[] array = {line};
for (int i = 0; i < array.Length; i++)
{
if (array[i] == findID)
{
MesssageBox.show("Line found!!")
}
}
}
}
Any help appreciated
try
if(int.Parse(array[i]) == findID)
instead of
if (array[i] == findID)
You have to convert your string representation of your number to a int and then compare both int's.
this is even shorter than iterating over an array which always has 1 element:
while (line != null) {
if(int.Parse(array[i]) == findID)
MesssageBox.Show("Line found!!")
}
EDIT
Try
int _findID = 1;
List<String> names = new List<string>()
using (StreamReader reader = new StreamReader("textfile.txt"))
{
string line = reader.ReadLine();
int lineCount = 0;
while (line != null)
{
lineCount++;
names.Add(line);
if (lineCount == _findID)
MessageBox.Show("Line found!!");
}
}
#user1285872: array.Length this will give array length 1 in your case when you check if (array[i] == findID) thi will be (0==findID) if the value of findID ==0 then message will show.
Your code has various problems:
First if the file is not empty you have an endless loop as you read the line once and always check the same line:
string line = reader.ReadLine();
while (line != null) {}
The array is always 1 item long as you create it in the loop itself.
But for the problem with the lineID, what exactly is the content of such a line?

Categories

Resources