So I have this piece of code to add items from a text file into a combobox for an assignment. How would I go about adding all of the items in the text file altogether instead of one by one like I'm doing now.
private void Form1_Load(object sender, EventArgs e)
{
TextReader tr;
try
{
cboCity.Items.Clear();
tr = File.OpenText("C:\\Users\\Alexander\\Desktop\\CPI Institute\\CPR\\Debugging\\cities.txt");
for (int counter = 4; counter < 5; counter++)
{
cboCity.Items.Add(tr.ReadLine());
cboCity.Items.Add(tr.ReadLine());
cboCity.Items.Add(tr.ReadLine());
cboCity.Items.Add(tr.ReadLine());
tr.Close();
}
}
catch (Exception ex)
{
MessageBox.Show("Error opening cities file", "ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
You may use
cboCity.Items.AddRange(File.ReadAllLines("C:\\Users\\Alexander\\Desktop\\CPI Institute\\CPR\\Debugging\\cities.txt"));
to do that in one line.
everytime you call ReadLine method, it will proceed to next line, so the purpose of your loop is gone.
Do something like this,
string line;
StreamReader file = new System.IO.StreamReader("C:\\Users\\Alexander\\Desktop\\CPI Institute\\CPR\\Debugging\\cities.txt");
while((line = file.ReadLine()) != null)
{
cboCity.Items.Add(line);
}
file.Close();
Use Items.AddRange():
cboCity.Items.AddRange(new string[] { tr.ReadLine(), tr.ReadLine(), tr.ReadLine(), tr.ReadLine() });
Related
I'm trying to code on my own for the first time, and decided to make a music player on Winforms.
I have a CheckedListBox that is already populated with the names of songs in a folder.
When I click a button, it's supposed to send the names of my selected songs into a .txt file for further manipulation, before closing the form.
For simplification, I'm just going with 1 selected song first.
private void selectbtn_Click(object sender, EventArgs e)
{
selectedSongs = checkedListBox1.CheckedItems.ToString();
songRecord.writeRecord(selectedSongs); //i initialised my streamreader/streamwriter class and called it songRecord
this.Close();
}
in my streamreader/writer class, this is what I have
class DataRecord
{
public void writeRecord(string line)
{
StreamWriter sw = null;
try
{
sw = new StreamWriter(#"C:\Users\Me\Desktop\JAM_MACHINE\record.txt", true);
sw.WriteLine(line);
}
catch (FileNotFoundException)
{
Console.WriteLine("Error: File not found.");
}
catch (IOException)
{
Console.WriteLine("Error: IO");
}
catch(Exception)
{
throw;
}
finally
{
if (sw != null)
sw.Close();
}
}
public void readRecord()
{
StreamReader sr = null;
string myInputline;
try
{
sr = new StreamReader(#"C:\Users\Me\Desktop\JAM_MACHINE\record.txt");
while ((myInputline = sr.ReadLine()) != null) ; //readline reads whole line
Console.WriteLine(myInputline);
}
catch (FileNotFoundException)
{
Console.WriteLine("Error: File not found");
}
catch(IOException)
{
Console.WriteLine("Error: IO");
}
catch (Exception)
{
throw;
}
finally
{
if (sr != null)
sr.Close();
}
}
}
When I run it, the .txt file doesn't show my selection. It only shows:
System.Windows.Forms.CheckedListBox+CheckedItemCollection
What went wrong?
Iterate through the CheckedItems Collection and collect each item inside a string array. I assume you fill the checkedListBox with strings
private void selectbtn_Click(object sender, EventArgs e)
{
string[] checkedtitles = new string[checkedListBox1.CheckedItems.Count];
for (int ii = 0; ii < checkedListBox1.CheckedItems.Count; ii++)
{
checkedtitles[ii] = checkedListBox1.CheckedItems[ii].ToString();
}
string selectedSongs = String.Join(Environment.NewLine, checkedtitles);
songRecord.writeRecord(selectedSongs);
this.Close();
}
In my program I am loading a text files information into a rich text box. When the user clicks the clear button I want the files contents to be empty and display it again on the rich text box. However when I try to clear an error pops up that the file is already in use.
I am not sure of of what is going on with this, I have a suspicion it has to do with closing the stream reader or creating a new one. Either way I am not quite sure.
Does anyone have any thoughts of what is going on with this?
Code:
namespace FileLocationAutomation
{
public partial class ViewLog : Form
{
public ViewLog()
{
InitializeComponent();
}
#region Variables
string str = "";
#endregion
#region Ok Button
private void btnOK_Click(object sender, EventArgs e)
{
this.Close();
}
#endregion
#region Form Load
private void ViewLog_Load(object sender, EventArgs e)
{
//catch any exception
try
{
//load the log thats kept on the users machine into the rich text object
StreamReader read = new StreamReader(GlobalVars.strLogPath);
str = read.ReadToEnd();
rtxtView.Text = str;
read.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
#endregion
#region Clear Log
//clear the log file and display it on the rich text box
private void btnClear_Click(object sender, EventArgs e)
{
try
{
StreamReader read = new StreamReader(GlobalVars.strLogPath);
File.WriteAllText(GlobalVars.strLogPath, String.Empty);
str = read.ReadToEnd();
rtxtView.Text = str;
read.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
#endregion
}
}
The problem is that you try to write to the file to clear it while still holding it open. The simplest change is to move the call to File.WriteAllText(GlobalVars.strLogPath, String.Empty); to after where you close the file, as follows:
#region Clear Log
//clear the log file and display it on the rich text box
private void btnClear_Click(object sender, EventArgs e)
{
try
{
StreamReader read = new StreamReader(GlobalVars.strLogPath);
str = read.ReadToEnd();
rtxtView.Text = str;
read.Close();
File.WriteAllText(GlobalVars.strLogPath, String.Empty);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
A better change would probably to use the static read method, since you're reading the whole file in one go there's no need to use the StreamReader.
private void btnClear_Click(object sender, EventArgs e)
{
try
{
rtxtView.Text = File.ReadAllText(GlobalVars.strLogPath);
File.WriteAllText(GlobalVars.strLogPath, String.Empty);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
The problem is strictly here:
try
{
StreamReader read = new StreamReader(GlobalVars.strLogPath);
File.WriteAllText(GlobalVars.strLogPath, String.Empty);
str = read.ReadToEnd();
rtxtView.Text = str;
read.Close();
}
Make it look like this:
try
{
File.WriteAllText(GlobalVars.strLogPath, String.Empty);
StreamReader read = new StreamReader(GlobalVars.strLogPath);
str = read.ReadToEnd();
rtxtView.Text = str;
read.Close();
}
Or since reading a blank file back is useless, do it like this:
try
{
File.WriteAllText(GlobalVars.strLogPath, String.Empty);
rtxtView.Text = String.Empty;
}
enclose the StreamReader declaration in using block {}to make sure that it gets disposed.
Try This:
using(StreamReader read = new StreamReader(GlobalVars.strLogPath))
{
str = read.ReadToEnd();
rtxtView.Text = str;
}
OR
rtxtView.Text = File.ReadAllText(GlobalVars.strLogPath);
You may change the order.
try
{
StreamReader read = new StreamReader(GlobalVars.strLogPath);
File.WriteAllText(GlobalVars.strLogPath, String.Empty);
str = read.ReadToEnd();
// close the stream first.
read.Close();
rtxtView.Text = str;
}
This is really short question. I don't understand try-catch mechanism completely.
This is my current code:
public static void WriteText(string filename, string text)
{
try
{
System.IO.StreamWriter file = new System.IO.StreamWriter(filename);
file.Write(text);
file.Close();
}
catch(Exception exc)
{
MessageBox.Show("File is probably locked by another process.");
}
}
Background:
Im writing application that shares configuration files with another application.
I need some dialog messagebox with "retry" and "abort" buttons, when that file is used by other application. When that message will appear - I will close that other application and I will try to rewrite that file again by pressing "Retry" button.
Whatr we have is using a counter for re-tries and possibly a thread sleep.
So something like
int tries = 0;
bool completed = false;
while (!completed)
{
try
{
System.IO.StreamWriter file = new System.IO.StreamWriter(filename);
file.Write(text);
file.Close();
completed = true;
}
catch(Exception exc)
{
tries++;
//You could possibly put a thread sleep here
if (tries == 5)
throw;
}
}
Even though there's a good answer already I'll submit one that's more tuned towards the OP's question (let the user decide instead of using a counter).
public static void WriteText(string filename, string text)
{
bool retry = true;
while (retry)
{
try
{
System.IO.StreamWriter file = new System.IO.StreamWriter(filename);
file.Write(text);
file.Close();
retry=false;
}
catch(Exception exc)
{
MessageBox.Show("File is probably locked by another process.");
// change your message box to have a yes or no choice
// yes doesn't nothing, no sets retry to false
}
}
}
If you need more info on how to implement the messagebox check out the following links;
http://msdn.microsoft.com/en-us/library/0x49kd7z.aspx
MessageBox Buttons?
I would do it like that:
public static void WriteText(string filename, string text, int numberOfTry = 3, Exception ex = null)
{
if (numberOfTry <= 0)
throw new Exception("File Canot be copied", ex);
try
{
var file = new System.IO.StreamWriter(filename);
file.Write(text);
file.Close();
}
catch (Exception exc)
{
WriteText(filename,text,--numberOfTry,ex);
}
}
I like it more like this (example tries to save a RichTextBox on close and allows retrying save or aborting close):
protected override void OnClosing(CancelEventArgs e)
{
if (richTextBox_Query.Modified)
{
DialogResult result;
do
try
{
richTextBox_Query.SaveFile(
Path.ChangeExtension(Application.ExecutablePath, "sql"),
RichTextBoxStreamType.UnicodePlainText);
result = DialogResult.OK;
richTextBox_Query.Modified = false;
}
catch (Exception ex)
{
result = MessageBox.Show(ex.ToString(), "Exception while saving sql query",
MessageBoxButtons.AbortRetryIgnore);
e.Cancel = result == DialogResult.Abort;
}
while (result == DialogResult.Retry);
}
base.OnClosing(e);
}
I am trying to figure out how to read multiple lines whith StreamReader. I have a text file with a list of commands inside it that I need to read from. My code works, however it will only read the first line. This causes me to have to move all my commands to a single line with a space between them. This is not a very tidy way of doing this seeing as I need to leave comments next to the commands. Example: CONNECT: "Connects to given IP."
public void ConsoleEnter_KeyDown(object sender, KeyEventArgs e)
{
string line;
if (e.KeyCode == Keys.Enter)
{
// Read the file and display it line by line.
StreamReader file = new StreamReader("C:\\Users\\Home\\Desktop\\commands.txt");
while ((line = file.ReadLine()) != null)
{
if (line.Contains(ConsoleEnter.Text))
{
COMBOX.Items.Add(ConsoleEnter.Text);
COMBOX.Items.Remove("");
ConsoleEnter.Text = "";
}
else
{
COMBOX.Items.Add("Invalid Command");
COMBOX.Items.Remove("");
ConsoleEnter.Text = "";
}
}
}
}
This is what am using in one of my app and its working fine hope it'll help you out.......
if (TxtPath.Text != string.Empty)
{
StreamReader srr = new StreamReader(TxtPath.Text);
try
{
ss = srr.ReadToEnd().Split('\n');
MessageBox.Show("File Successfully Loded in Memory \n" + TxtPath.Text, "System Manager", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
catch (Exception)
{
throw new Exception("File are not readable or write protacted");
}
LblLineCount.Text = ss.Count().ToString();
}
else
{
MessageBox.Show("Please Browse any Log File 1st", "System Manager", MessageBoxButtons.OK, MessageBoxIcon.Stop);
}
you can also trim the
.Split('\n')
to take all data in single line, i can't try it right now but if check it will get u out of stuck...........
u should empty the variable after the loop, not inside the loop
public void ConsoleEnter_KeyDown(object sender, KeyEventArgs e)
{
string line;
if (e.KeyCode == Keys.Enter)
{
// Read the file and display it line by line.
StreamReader file = new StreamReader("C:\\Users\\Home\\Desktop\\commands.txt");
while ((line = file.ReadLine()) != null)
{
if (line.Contains(ConsoleEnter.Text))
{
COMBOX.Items.Add(ConsoleEnter.Text);
}
else
{
COMBOX.Items.Add("Invalid Command");
}
}
COMBOX.Items.Remove("");
ConsoleEnter.Text = "";
}
}
public void ConsoleEnter_KeyDown(object sender, KeyEventArgs e)
{
string line;
string path = #"C:\\Users\\Home\\Desktop\\commands.txt";
WebClient client = new WebClient();
System.IO.Stream stream = client.OpenRead(path);
System.IO.StreamReader str = new StreamReader(stream);
string Text=str.ReadToEnd();
string[] words = Text.Split(':');
if (e.KeyCode == Keys.Enter)
{
for(int i=1;i<words.Length;i++)
{
if (string.compare(words[i],textBox1.text)==0)
{
COMBOX.Items.Add(ConsoleEnter.Text);
COMBOX.Items.Remove("");
ConsoleEnter.Text = "";
}
else
{
COMBOX.Items.Add("Invalid Command");
COMBOX.Items.Remove("");
ConsoleEnter.Text = "";
}
}
}
}
try this ..
use namespace using System.Net;
The following are my codes but it cant handle more than 500 lines at one time.
It needs to add a , to the end of the line and at the same time detect. What i'm currently doing is separating them into 2 different textbox then save the one which i need by copy pasting but the app seems to hang if the file is too big.
Can someone help me with making it more efficient. Would really appreciate it.
private void button1_Click_1(object sender, EventArgs e)
{
if (openFileDialog1.ShowDialog() == DialogResult.Cancel)
return;
System.IO.StreamReader Reader = new System.IO.StreamReader(openFileDialog1.FileName);
//Create a filestream
FileStream fStr;
try
{
//Set filestream to the result of the pick of the user
fStr = new FileStream(openFileDialog1.FileName, FileMode.Open, FileAccess.Read);
//Create a streamreader, sr, to read the file
StreamReader sr = new StreamReader(fStr);
//While the end of the file has not been reached...
while (sr.Peek() >= 0)
{
//Create a 'line' that contains the current line of the textfile
string line = sr.ReadLine().ToLower();
if (line.Contains("staff"))
{
line += ","; //Add a , to the end of the line**Important**
textBox1.Text += line + Environment.NewLine;
releventcount += 1;
}
else
{
line += ","; //Add a , to the end of the line**Important**
textBox2.Text += line + Environment.NewLine;
irreleventcount += 1;
}
label1.Text = "Relevent: ";
label2.Text = "Irrelevant: ";
}
//Close the file so other modules can access it
sr.Close();
//If something goes wrong, tell the user
}
catch (Exception)
{
MessageBox.Show("Error opening file", "Check the CODE ! ~.~");
}
}
I'm not sure what it is you're eventually trying to accomplish here. There are several more succinct ways to do what your current code is doing, but they won't significantly improve the speed of reading.
The bottleneck in your code is that you're appending strings. Using a StringBuilder is good advice, but you can do better than that by creating a List<string> and then calling string.Join at the end. For example:
if (openFileDialog1.ShowDialog() == DialogResult.Cancel)
return;
List<string> staff = new List<string>();
List<string> other = new List<string>();
foreach (var line in File.ReadLines(openFileDialog1.FileName))
{
line = line.ToLower();
if (line.Contains("staff"))
{
staff.Add(line);
}
else
{
other.Add(line);
}
}
relevantcount = staff.Count;
irrelevantCount = other.Count;
textBox1.Text = string.Join(","+Environment.NewLine, staff);
textBox2.Text = string.Join("."+Environment.NewLine, other);
Also, you say that your code can only handle 500 lines at a time. Is there something in your user interface that prevents it from handling more? Certainly, there's nothing in the code you showed that has such a low limit.
500 lines is nothing.
Try File.ReadAllLines and File.WriteAllLines.
Then you can do your work on an array of strings in memory and avoid the iterative IO.
Reading files line by line is very slow. You can make this code much faster by reading a large block of data (or even the entire file if it's not too enormous). For example, use a File.ReadAllLines to read the entire file as separate lines, or use a FileStream and Read() into a buffer, and find the individual lines for yourself by looking for newline (\n, \r) characters.
To export the data, don't copy and paste it fom a text box - Write the results to one or two new files, and then just open them.
It is much, much more efficient to use StringBuilders to gather the text for the textboxes than to continuously append text.
Also, you should wrap your various streams in using blocks.
Here is a rewrite that should be much more efficient:
private void button1_Click_1(object sender, EventArgs e)
{
if (openFileDialog1.ShowDialog() == DialogResult.Cancel)
return;
try
{
//Set filestream to the result of the pick of the user
using (var fStr = new FileStream(openFileDialog1.FileName, FileMode.Open, FileAccess.Read))
{
//Create a streamreader, sr, to read the file
using (var sr = new StreamReader(fStr))
{
var sbTextBox1 = new System.Text.StringBuilder(10000);
var sbTextBox2 = new System.Text.StringBuilder(10000);
//While the end of the file has not been reached...
while (sr.Peek() >= 0)
{
//Create a 'line' that contains the current line of the textfile
string line = sr.ReadLine().ToLower();
if (line.Contains("staff"))
{
//Add a , to the end of the line**Important**
sbTextBox1.Append(line).Append(",").AppendLine();
releventcount += 1;
}
else
{
//Add a , to the end of the line**Important**
sbTextBox2.Append(line).Append(",").AppendLine();
irreleventcount += 1;
}
}
textBox1.Text = sbTextBox1.ToString();
textBox2.Text = sbTextBox2.ToString();
label1.Text = "Relevent: ";
label2.Text = "Irrelevant: ";
//Close the file so other modules can access it
sr.Close();
}
}
}
catch (Exception)
{
MessageBox.Show("Error opening file", "Check the CODE ! ~.~");
}
}