I don't know what causes the issue, but whenever I try to read from a text file in this situation, the application freezes.
private void btnCount_Click(object sender, EventArgs e)
{
int totalVotes = 0;
int votesFirst = 0;
int votesSecond = 0;
string firstClub;
string secondClub;
FileStream fs = null;
StreamReader sr = null;
if (tb1.Text == "" || tb2.Text == "")
{
MessageBox.Show("Fill in the fields");
}
else
{
firstClub = tb1.Text;
secondClub = tb2.Text;
try
{
fs = new FileStream("C:\\Users\\dluuk\\source\\repos\\PopularFootballClubs\\Polls\\bin\\Debug\\FootballClubs.txt", FileMode.Open, FileAccess.Read);
sr = new StreamReader(fs);
string s = sr.ReadLine();
while (s != null)
{
if (s.Contains(firstClub))
{
votesFirst++;
totalVotes++;
}
else if (s.Contains(secondClub))
{
votesSecond++;
totalVotes++;
}
}
}
catch (IOException ex)
{
MessageBox.Show(ex.Message);
}
catch (Exception)
{
MessageBox.Show("something wrong happened");
}
finally
{
lblTotal.Text = totalVotes.ToString();
lbl1.Text = votesFirst.ToString();
lbl2.Text = votesSecond.ToString();
if (sr != null) { sr.Close(); }
if (fs != null) { fs.Close(); }
}
}
}
I'm closing connection and the path is correct, because I don't get any exceptions at this current state so I really can't see the problem. Maybe you can help?
You aren't updating s at all, so your loop is infinite. It's reading the first line, then looping over and over again, using the same line each time because ReadLine() is not called again in the scope of the loop (and thus you never reach the end of the file - or even line 2).
You could change to something like this:
string s;
while ((s = sr.ReadLine()) != null)
{
if (s.Contains(firstClub))
{
votesFirst++;
totalVotes++;
}
else if (s.Contains(secondClub))
{
votesSecond++;
totalVotes++;
}
}
As a side note, you should put using statements around your Streams. They are disposable and you won't need to handle it manually.
while (s != null)
You never change s in the loop, so it gets stuck in an infinite loop. Update s at the end of the loop:
while (s != null)
{
// do stuff
s = sr.ReadLine();
}
Related
StackOverFlowExceprion raised, when logDirectory = new DirectoryInfo(m_logFileDirectory); line was executing. How can I solve the problem? Please help me.
This procedure writeLogToFile write a logMessge to File to logDirectory.
It is part of Log write program.
private void writeLogToFile(string logMessge)
{
DirectoryInfo logDirectory = null;
try
{
Monitor.Enter(m_lock);
logDirectory = new DirectoryInfo(m_logFileDirectory);
if (!logDirectory.Exists)
{
logDirectory.Create();
}
if (m_streamWriter == null) newLogFile();
if (m_logFileAutoSeperate && (m_streamWriter.BaseStream.Length > m_logFileSize * 1024))
{
newLogFile();
m_streamWriter.WriteLine(logMessge);
}
else
{
m_streamWriter.WriteLine(logMessge);
}
// stream writer uses internal buffer.
// if directWriting option is true, the file will be write(flush) once.
if (directWriting) m_streamWriter.Flush();
}
catch (StackOverflowException sofex)
{
AppExceptionHandler.writeException(sofex);
}
catch (AppException aex)
{
AppExceptionHandler.writeException(aex);
}
catch (Exception ex)
{
AppExceptionHandler.writeException(ex);
}
finally
{
Monitor.Exit(m_lock);
}
}
From the comments, this is what newLogFile looks like:
private void newLogFile()
{
try
{
Monitor.Enter(m_lock);
if (m_streamWriter != null)
{
endLogging();
m_streamWriter.Flush();
m_streamWriter.Close();
}
m_logFileNameSuffix = getLogFileNewSuffix();
m_streamWriter = File.AppendText(getLogFileName());
startLogging();
}
}
So im making a simple register and login in unity and ive came across a wall. My code works fine if it has any character or word in it but with it blank the loop doesnt work because it is a while line != null. I know that is the problem but i dont know any other loops to use in this scenario. Im using streamreader so i can constantly update the file as i can close it.
v
if (Input.GetKeyDown(KeyCode.Return))
{
StreamReader sr = new StreamReader("C:/Users/jorda/OneDrive/2D GAME REMAKE/Assets/login.txt",true);
line = sr.ReadLine();
while (line != null)
{
change =false;
if (line == Logdetails)
{
Debug.LogWarning("Account already exists");
username.GetComponent<InputField>().text = "";
password.GetComponent<InputField>().text = "";
break;
}
else if (Username == "" || Password == "")
{
Debug.LogWarning("There is an empty field");
break;
}
else
{
change = true;
}
line = sr.ReadLine();
}//while loop ends
sr.Close();
if (change == true)
{
Write();
}
}
public void Write()
{
StreamWriter sw = new StreamWriter("C:/Users/jorda/OneDrive/2D GAME REMAKE/Assets/login.txt", true);
{
sw.WriteLine(Logdetails);
username.GetComponent<InputField>().text = "";
password.GetComponent<InputField>().text = "";
sw.Close();
SceneManager.LoadScene(1);
}
}
Use a do while loop, which makes sure the code runs at least once, meaning for empty files one of your else branches is executed:
do
{
change =false;
if (line == Logdetails)
{
...
}
...
}
while(line != null)
I have a append-only log file which is monitored by a FileSystemWatcher. When the file is changed, Read() is called for the LogFile object.
The log file should be read line by line.
The goal is to read only changes i.e. lines add to the log file (skip already readed lines).
Thus the StreamReader should start to read from the position where it ended on the previous read.
My solution so far doesn't work. When I add
1
2
3
4
line by line in Notepad++ to my textfile & save each time when a line was added, the Debug output is
Initial read
1 //OK
2 //OK
3 //OK
1 //looks like the log file is read again from the beginning
2
3
4
Output should be
Initial read
1
2
3
4
Any ideas to solve this problem?
Console code
public class LogFile
{
public List<string> Contents { get; }
string _fullPath;
long position;
public LogFile(string fullPath)
{
if (File.Exists(fullPath))
{
_fullPath = fullPath;
Contents = new List<string>();
Read();
}
else
{
throw new FileNotFoundException($"{fullPath} not found");
}
}
public void Read(FileSystemWatcher fsw = null)
{
if (fsw != null)
fsw.EnableRaisingEvents = false; //set to false to prevent Changed event be fired twice
FileStream fs = null;
StreamReader sr = null;
try
{
fs = new FileStream(_fullPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
try
{
sr = new StreamReader(fs, Encoding.UTF8);
if (Contents.Count == 0)
{
Debug.WriteLine($"Initial read");
AddToContents(_fullPath, sr);
position = fs.Length; //store the length of the stream
}
else
{
sr.DiscardBufferedData();
sr.BaseStream.Seek(position, SeekOrigin.Begin);
AddToContents(_fullPath, sr);
position = fs.Length; //store the length of the stream
}
}
catch (Exception ex)
{
Debug.WriteLine($"Error while reading from {_fullPath}");
//log exception
}
finally
{
if (sr != null)
sr.Close();
}
}
catch (Exception ex)
{
Debug.WriteLine($"Error while opening {_fullPath}");
//log exception
}
finally
{
if (fs != null)
fs.Close();
if (fsw != null)
fsw.EnableRaisingEvents = true; //set raise events for the filesystemwatcher to true
}
}
private List<string> AddToContents(string fullPath, StreamReader sr)
{
List<string> newLines = new List<string>();
try
{
while (!sr.EndOfStream)
{
try
{
string line = sr.ReadLine();
if (line != string.Empty)
{
Contents.Add(line);
newLines.Add(line);
Debug.WriteLine(line);
}
}
catch (Exception ex)
{
Debug.WriteLine($"Error processing line in {fullPath}");
throw;
}
}
return newLines;
}
catch (Exception ex)
{
Debug.WriteLine($"Error while reading from {fullPath}");
throw;
}
}
}
class Program
{
static LogFile file;
static FileSystemWatcher fsw;
static void Main(string[] args)
{
string path = #"C:\Temp\test.txt";
file = new LogFile(path);
CreateWatcher(path);
Console.ReadKey();
}
private static FileSystemWatcher CreateWatcher(string fileNameFullPath)
{
fsw = new FileSystemWatcher(Path.GetDirectoryName(fileNameFullPath)); //constructor only accepts directory path
fsw.IncludeSubdirectories = false;
fsw.Filter = Path.GetFileName(fileNameFullPath); //filter for the given file
fsw.NotifyFilter = NotifyFilters.LastWrite;
fsw.EnableRaisingEvents = true;
fsw.Changed += Fsw_Changed;
return fsw;
}
private static void Fsw_Changed(object sender, FileSystemEventArgs e)
{
if (file != null)
file.Read(fsw);
}
}
Problem is
position = fs.Length; //store the length of the stream
You should store current position of the stream into position field not length of stream because sometimes FileStream.Length is zero (I don't know why)
this.position = fs.Position;
and check if FileStream.Length is zero skip that change
fs = new FileStream(this._fullPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
if (fs.Length != 0)
{
try
{
sr = new StreamReader(fs);
if (this.Contents.Count == 0)
{
......
Now it's working
Consider the following:
private void Read()
{
StreamReader r = new StreamReader(clientObject.GetStream());
string str = r.ReadLine();
if ((str == null) || (str == "")) { Disconnect(); }
Client_dataReceived(str);
Read();
}
When I connect this client to a server, it hangs. When I break it with Intellisense,
"string str = r.ReadLine();" is highlighted, I assume this is what the program was working on just before it started hanging. Why does it hang like this? I have created applications previously the exact same way, they don't hang.
Thanks in advance!
EDIT:
I just tried this:
private void Read()
{
StreamReader r = new StreamReader(clientObject.GetStream());
string str;
while ((str = r.ReadLine()) != null)
{
Client_dataReceived(str);
}
}
But I get the same effect...
private void Read()
{
StreamReader r = new StreamReader(clientObject.GetStream());
string str;
while (!(String.IsNullOrEmpty(str=r.ReadLine())))
{
Client_dataReceived(str);
}
}
Because it is a recursive call with no exit. You call Read inside of Read. It does not matter where it breaks.
private void Read()
{
StreamReader r = new StreamReader(clientObject.GetStream());
string str = r.ReadToEnd();
if ((str == null) || (str == "")) { Disconnect(); }
Client_dataReceived(str);
}
You have a recursive call. You will eventually get a StackOverflowException. (How coincidental. I just realized that!)
Try this:
private void Read()
{
using (var r = new StreamReader(clientObject.GetStream()))
{
string str;
while ((str = r.ReadLine()) != null)
{
Client_dataReceived(str);
}
Disconnect();
}
}
NOTE: I intentionally removed your str == "" test, as returning an empty string doesn't mean you've read to the end of the stream, while a null return does. If you have a special case where the empty line is important to be triggered on, be sure to restore that test.
Now if the clientObject is something that waits for input, like a TcpClient, then you need to evaluate it differently. It would help if we knew what clientObject was.
I can't comment because of low reputation so I'm writing it here...
Try adding a return(); statement after disconnect(); in your first code snippet.
Okay I need help, again! For some reason it is not working, no idea why.. nothing even appears on my catch request..
public void load(object sender, DoWorkEventArgs e)
{
int repeat = 1;
int proxyIndex = 1;
if (listBox1.Items.Count == proxyIndex) //If we're at the end of the proxy list
{
proxyIndex = 0; //Make the selected item the first item in the list
}
try
{
int i = 0;
while (i < listBox1.Items.Count)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(textBox1.Text);
string proxy = listBox1.Items[1].ToString();
string[] proxyArray = proxy.Split(':');
WebProxy proxyz = new WebProxy(proxyArray[0], int.Parse(proxyArray[1]));
request.Proxy = proxyz;
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
using (StreamReader reader = new StreamReader(response.GetResponseStream()))
{
string str = reader.ReadToEnd();
}
}
/*HttpWebRequest request = (HttpWebRequest)WebRequest.Create(textBox1.Text);
string proxy = listBox1.Items[i].ToString();
string[] proxyArray = proxy.Split(':');
WebProxy proxyz = new WebProxy(proxyArray[0], int.Parse(proxyArray[1]));
request.Proxy = proxyz;
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
StreamReader reader = new StreamReader(response.GetResponseStream());
string str = reader.ReadToEnd();
Thread.Sleep(100);
{
if (str != null)
{
listBox2.Items.Add("Starting connection.");
Thread.Sleep(1000);
{
listBox2.Items.Add("Waiting..");
Thread.Sleep(500);
{
listBox2.Items.Add("Connection closed.");
repeat++;
continue;
}
}
}
else if (str == null)
{
listBox2.Items.Add("Reply was null, moving on.");
proxyIndex++;
repeat++;
}
}
*/
}
}
catch (Exception ex) //Incase some exception happens
{
MessageBox.Show(ex.Message);
return;
// listBox2.Items.Add("Error:" + ex.Message);
}
}
How can I get it to work?
It looks like you're trying to use a BackgroundWorker to perform this operation, and in the absence of any more detailed information on what isn't working, I'd guess it's because you aren't assigning any result or errors which can be picked up by main thread.
You should assign the results of the request in the case of success:
using (StreamReader reader = new StreamReader(response.GetResponseStream()))
{
e.Result = reader.ReadToEnd();
}
Since you seem to be making multiple requests you should probably make the result a List<string> or similar.
You should remove the try/catch block and deal with any errors in the RunWorkerCompleted event of the BackgroundWorker:
private void BackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if(e.Error != null)
{
MessageBox.Show("Error in async operation: " + ex.Message);
}
else
{
//process results
}
}