C# IO Stream not working like expected - c#

I have this piece of code here:
private void button1_Click(object sender, EventArgs e)
{
StreamReader sr = new StreamReader("TextFile1.txt");
while ((line = sr.ReadLine()) != null)
{
if (line == textBox1.Text)
{
line = sr.ReadLine();
if (line == textBox2.Text)
{
MessageBox.Show("Logged in! Welcome " + textBox1.Text);
new Form2().Show();
this.Hide();
LoginSucces = true;
}
}
}
sr.Close();
if (LoginSucces == false) MessageBox.Show("Login Failed :(");
}
And it reads from this text:
AverageJavaGuy
Password
Chezzy
Password
The problem is that it doesnt work!
When I type in:
textBox1 = Chezzy.
textBox2 = Password.
it doesnt work...
it only works for AverageJavaGuy.
Does anyone know how to fix this?

Dictionary<string, string> userPass_dict = new Dictionary<string, string>(); // add this at class level
using (StreamReader sr = new StreamReader("TextFile1.txt"))
{
string line = "";
string line2 = "";
while (!sr.EndOfStream)
{
line = sr.ReadLine();
line2 = sr.ReadLine();
userPass_dict.Add(line, line2);
}
}

So it works for the first login/password, but not the second ?
Have you checked your textfile ?
Isn't the problem related to the dot beside "Chezzy" (in you post!) ?
Try to add "Console.WriteLine" or use debugger to fix your code and see what happens it the loop.
Also, I think the inner " sr.ReadLine();" in the loop may cause unexpected "shifting" according to the textfile content, use it carefully...

move line = sr.ReadLine(); to the outside the if statement

Related

File cannot be accessed because it is being used by another process

I'm kind of new to coding and I've been trying to replace a word in a text file but when I execute the program it gives me the "File is used by another process error"
private void btnSave1_Click(object sender, EventArgs e)
{
string DOB = dateTimePicker1.Value.ToString();
string Fname = txtBFirstName.ToString();
string Lname = txtBLastName.ToString();
string IDnum = txtBIDnum.ToString();
string Address = txtBAddress.ToString();
string nationality = txtBNationality.ToString();
//string gender = cmbGender.SelectedItem.ToString();
// string marrStatus = cmbMaritialStatus.SelectedItem.ToString();
StreamReader read = null;
//write to file
try
{
// var lines = File.ReadAllLines("CV.txt");
string line;
read = new StreamReader("CurriculumVitae.txt");
while ((line = read.ReadLine()) != null)
{
string text = File.ReadAllText("CurriculumVitae.txt");
text = text.Replace("Empty", DOB);
File.WriteAllText("CurriculumVitae.txt",
File.ReadAllText("CurriculumVitae.txt")
.Replace("empty",DOB));
}
}
catch (Exception exc)
{
MessageBox.Show(exc.Message);
}
finally
{
read.Close();
}
//Open Next Form
Education objNextForm = new Education();
objNextForm.Visible = true;
}
Problem from these 3 lines
read = new StreamReader("CurriculumVitae.txt");
string text = File.ReadAllText("CurriculumVitae.txt");
File.WriteAllText("CurriculumVitae.txt"
,File.ReadAllText("CurriculumVitae.txt").Replace("empty",DOB));
Both StreamReader and File.ReadAllText will lock a file. And whenever they try to lock same file it will error
You should try to do thing once. Don't try to open file many times. And don't open same file before it closed
You can just take out this part around your code, as you're not using the StreamReader you created:
while ((line = read.ReadLine()) != null)
{
...
}
And change
File.WriteAllText("CurriculumVitae.txt",
File.ReadAllText("CurriculumVitae.txt");
To
File.WriteAllText("CurriculumVitae.txt", text);
You will want to update your StreamReader to open the file in "shared" mode so that it doesn't lock the file.
See this question for details on how to do that.
First, don't use a StreamReader when you use File.ReadAllText as it's not needed, the other error comes from this line:
File.WriteAllText("CurriculumVitae.txt", File.ReadAllText("CurriculumVitae.txt").Replace("empty", DOB));
You are opening the same file twice, try something like this:
string content = File.ReadAllText("CurriculumVitae.txt").Replace("empty", DOB);
File.WriteAllText("CurriculumVitae.txt", content);
Use either StreamReader or ReadAllText but not both at the same time...
Also I would really suggest to do "usings" wherever possible becuase this helps a lot closing objects (but is not your prime problem here)
// It will free resources on its own.
//
using (StreamReader reader = new StreamReader("file.txt"))
{
line = reader.ReadLine();
}
Console.WriteLine(line);
}

Trim a line on a text file from a website after making a list

Overview
Hey, what I am trying to do is create an add-on for a game where when they join it will check on my website a list of names I have in a text file.
Code
public override void Init()
{
Player.Joined += (object sender, PlayerEventArgs e) =>
{
string autokick = new WebClient().DownloadString("http://leeizazombie.cba.pl/server/autokick.txt");
StringReader sr = new StringReader(autokick);
List<string> autokicklist = new List<string>();
while (sr.Peek() != -1)
{
string line = sr.ReadLine();
autokicklist.Add(line);
}
if (autokicklist.Contains(e.Player.name))
{
e.Player.Kick("Auto-Kick: "); //Reason goes in this part after kicking the player.
}
};
}
Problem
I can't figure out how to get the reason part of the text and exclude the reason part when searching each line, This is an example of a line:
LeeIzaZombie+ : Kicked for a test run.
Where LeeIzaZombie+ is the username and "Kicked for a test run." is the reason.
If the message always contains a ':' after username you can Split it and get the reason like this:
e.Player.Kick("Auto-Kick: {0}", line.Split(':')[1].Trim());
This should work as expected if the reason doesn't contain any :. If it does you can try:
var reason = string.Join(":", line.Split(':').Skip(1));
e.Player.Kick("Auto-Kick: {0}", reason);
Update: in order to access line from if statement you should declare it outside of the loop:
string line = "";
while (sr.Peek() != -1)
{
line = sr.ReadLine();
autokicklist.Add(line);
}

How to prevent adding an empty line to my file?

Im creating a text file and the last line is ""
private void lastRunDate()
{
String lastLine = readLastDate();
String[] date = lastLine.Split('/');
DateTime dt = new DateTime(Int32.Parse(date[2]), Int32.Parse(date[0]), Int32.Parse(date[1]));
DateTime currentDT = DateTime.Now;
argValue = 1;
if ((dt.Month == currentDT.Month) && (argValue == 0))
{
MessageBox.Show("This application has already been run this month");
this.Close();
}
}
private void AddRecordToFile()
{
DateTime now = DateTime.Now;
prepareToEmail();
string path = filepath;
bool dirtyData = true;
// This text is added only once to the file.
if (!File.Exists(path))
{
// Create a file to write to.
using (StreamWriter sw = File.CreateText(path))
{
sw.Write(now.ToShortDateString());
}
dirtyData = false;
}
if (dirtyData)
{
// This text is always added, making the file longer over time
// if it is not deleted.
using (StreamWriter sw = File.AppendText(path))
{
sw.Write(now.ToShortDateString());
}
}
}
private String readLastDate()
{
using (StreamReader sr = new StreamReader(filepath))
{
// Initialize to null so we are not stuck in loop forever in case there is nothing in the file to read
String line = null;
do
{
line = sr.ReadLine();
// Is this the end of the file?
if (line == null)
{
// Yes, so bail out of loop
return "01/01/1900"; // I had to put something
}
// Is the line empty?
if (line == String.Empty)
{
// Yes, so skip it
continue;
}
// Here you process the non-empty line
return line;
} while (true);
}
}
is what I am using to create the file (or append it)
now is a DateTime object
I used your (Karl) code to create a method called "readLastDate()"
I get the 1st date instead.
I'm probably being way to pragmatic and simple, but skip all the stream stuff and use File class directly like this...
string newLine = "";
if (!isFirstLine)
newLine = Environment.NewLine;
File.AppendAllText(
filePath,
string.Format("{0}{1}", newLine, DateTime.Now.ToString()));
You could use a sw.Write and PRE-pend a linefeed. Unfortunately that will give you an empty line at the start of the file.
Have you tried using the command .Trimend ('\n')?
http://msdn.microsoft.com/en-us/library/system.string.trimend.aspx
Do this:
sw.Write(now.ToShortDateString());
Here is the MSDN documentation for StreamWriter.WriteLine.
Here is the MSDN documentation for StreamWriter.Write.
UPDATE:
Keep using the WriteLine, but change the way you read your values in from the file:
using (StreamReader sr = new StreamReader(path))
{
// Initialize to null so we are not stuck in loop forever in case there is nothing in the file to read
String line = null;
do
{
line = sr.ReadLine();
// Is this the end of the file?
if (line == null)
{
// Yes, so bail out of loop
return;
}
// Is the line empty?
if (line == String.Empty)
{
// Yes, so skip it
continue;
}
// Here you process the non-empty line
} while (true);
}
Adding a record should be a simple matter of calling File.AppendAllText, as pointed out in another answer. Although I would recommend:
File.AppendAllText(filePath, DateTime.Now.ToString() + Environment.NewLine);
To read the last date from the file is also very easy:
string lastGoodLine = "01/01/1900";
using (StringReader sr = new StringReader(filePath))
{
while (!sr.EndOfStream)
{
string line = sr.ReadLine();
if (!string.IsNullOrEmpty(line))
lastGoodLine = line;
}
}
return lastGoodLine;

Filtering a line out of a string c#

I want to read a .txt file in c# and filter a line out of the string and only show that line. If the match is on the first line, i get a good output using streamreader.ReadLine. But if it's on the second line, i need to get it filtered. (i tought by creating a ReadLine loop?)
Thanks in advance
private void comboBox3_SelectedIndexChanged(object sender, EventArgs e)
{
StreamReader sr = new StreamReader(textBox1.Text);
string BoxLM1 = sr.ReadLine();
if (comboBox3.Text == "Anderlecht")
{
if (BoxLM1.Contains("Anderlecht"))
{
label5.Text = BoxLM1;
}
else
{
string BoxLM2 = sr.ReadToEnd();
MessageBox.Show(BoxLM2);
}
You can check all lines at once using File.ReadLines() method and LINQ:
var firstAnderlecht = File.ReadLines(textBox1.Text).FirstOrDefault(s => s.Contains("Anderlecht"));
if (firstAnderlecht != null) {
label5.Text = firstAnderlecht;
}
The ReadLines produces an enumerable of lines from the file; the FirstOrDefault method lets you apply a condition to all lines of the file without a loop, and pick the first line where the condition applies.
If you are manipulating big files i recommend to use this iterator:
private static IEnumerable FileIterator(String filePathe)
{
using (StreamReader streamReader = new StreamReader(filePathe))
{
String line;
while ((line = streamReader.ReadLine()) != null)
{
yield return line;
}
yield break;
}
}
it will prevent the loading of full file to RAM

C# read line from file with StreamReader with DownloadFileAsync

I am having a problem reading file with StreamReader and while line != null add to textBox1
Code:
using(StreamReader reader = new StreamReader("lastupdate.txt"))
{
string line;
while((line = reader.ReadLine()) != null)
{
textBox1.Text = line;
}
reader.Close();
}
It's not working and I don't know why. I tried to use using StreamReader, I download the file from the URL and I can see in the folder that the file is downloaded. The lastupdate.txt is 1KB in size.
This is my current working code with MessageBox. If I remove the MessageBox, the code doesn't work. It needs some kind of wait or I don't know:
WebClient client = new WebClient();
client.DownloadFileAsync(new Uri(Settings.Default.patchCheck), "lastupdate.txt"); // ok
if(File.Exists("lastupdate.txt"))
{
MessageBox.Show("Lastupdate.txt exist");
using(StreamReader reader = new StreamReader("lastupdate.txt"))
{
string line;
while((line = reader.ReadLine()) != null)
{
textBox1.Text = line;
MessageBox.Show(line.ToString());
}
reader.Close();
}
File.Delete("lastupdate.txt");
}
Try :
StringBuilder sb = new StringBuilder();
using (StreamReader sr = new StreamReader("lastupdate.txt"))
{
while (sr.Peek() >= 0)
{
sb.Append(sr.ReadLine());
}
}
textbox.Text = sb.Tostring();
If you want the text in the text box it would be much more effective to read all of it and then put it into the text box:
var lines = File.ReadAllLines("lastupdate.txt");
textBox1.Lines = lines; //assuming multi-line text box
or:
textBox1.Text = File.ReadAllText("lastupdate.txt");
Edit:
After latest update - you are downloading the file asynchronously - it might not even be there, only partially there or in a state in-between when your code executes.
If you just want the text string in the file don't download it, use DownloadString instead:
string text = "";
using (WebClient wc = new WebClient())
{
text = wc.DownloadString(new Uri(Settings.Default.patchCheck));
}
textBox1.Text = text;
Try this :
using(StreamReader reader = new StreamReader(Path))
{
string line = reader.ReadLine();
while(line != null)
{
textBox1.Text += line;
line = reader.ReadLine()
}
reader.Close();
}
Web Client has a rather bizarre DownloadFileAsync method. The return type is void, so it is not awaitable. Also, that means we do not even get a Task, so ContinueWith is not possible. That leaves us with using the DownloadFileCompleted event.
const string FileName = "lastupdate.txt";
private void DownloadLastUpdate() {
var client = new WebClient();
client.DownloadFileCompleted += ( s, e ) => {
this.UpdateTextBox( e.Error );
client.Dispose();
};
client.DownloadFileAsync( new Uri( Settings.Default.patchCheck ), FileName );
}
I went with an optional exception parameter to relay any exception messages. Feel free to refactor as desired. File.ReadLines yields text line by line, so large files should not use very much memory.
private void UpdateTextBox( Exception exception = null ) {
textBox1.Text = string.Empty;
if ( exception != null ) {
textBox1.Text = exception.Message;
return;
}
if ( !File.Exists( FileName ) ) {
textBox1.Text = string.Format( "File '{0}' does not exist.", FileName );
return;
}
var lines = File.ReadLines( FileName );
textBox1.Text = string.Join( Environment.NewLine, lines );
}
the answer given above is correct, but in your piece of code, just change 1 line:
textBox1.Text += line;

Categories