I am working on a program for personal use that will automatically sort a grocery list (from file) into a particular order. I want the program to open the file, read each line, and determine if each line contains certain words. For example, a line could contain "chicken breasts," and the program would just recognize that it contained "chicken." The idea is to have the program automatically order my list so that I'm not running back and forth getting items when I go to the store. Currently the external file line must have the exact text "chicken" for the program to recognize it ("chicken breasts" will not be recognized). Here is the section that I believe is giving me trouble:
if (groceries.Contains("chicken"))
{
chicken = "Chicken";
lstItems.Items.Add(chicken);
}
Groceries is an array with each element being a line from the file (I think I created it correctly). Below is the entire code:
private void btnImport_Click(object sender, EventArgs e)
{
//Grocery items
string chicken;
//StreamReader variable
StreamReader readFile;
string filePath;
//Counter variable
int index = 0;
//Display open file dialog box
OpenFileDialog openFileDialog1 = new OpenFileDialog();
openFileDialog1.ShowDialog();
if (openFileDialog1.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
//Set filepath as a variable
filePath = openFileDialog1.FileName;
// Assign the file as a variable
readFile = File.OpenText(filePath);
//Count lines in file and create array
int lineCount = File.ReadLines(filePath).Count();
string[] groceries = new string[lineCount];
//Read file's contents
while (index < groceries.Length && !readFile.EndOfStream)
{
groceries[index] = readFile.ReadLine();
index++;
if (groceries.Contains("chicken"))
{
chicken = "Chicken";
//Display items in label
lstItems.Items.Add(chicken);
}
}
//Close file
readFile.Close();
}
}
When the program is run, it will add "Chicken" to the listbox the same number of times as the number of lines in the file, even though only one line actually contains "chicken." My question is: How can I make it pick out the keyword from a longer line of text, and why is it adding the item more than once? Thanks!
Edit
(Sorry I don't know how to attach a file here)
I am currently importing a .txt file with the following data:
chicken
fish
Frosted Flakes cereal
pork tenderloin
ground beef
First, you need to remove the redundant openFileDialog1.ShowDialog();. And access the elements in groceries by index. Then add additional conditions to exclude rows that contain "chicken breasts". Note that index++ is executed after the if statement.
// define a varibale
bool chickenadded = false;
OpenFileDialog openFileDialog1 = new OpenFileDialog();
// remove the redundant ShowDialog
if (openFileDialog1.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
// code omitted ...
//Read file's contents
while (index < groceries.Length && !readFile.EndOfStream)
{
groceries[index] = readFile.ReadLine();
// check here
if (groceries[index].Contains("chicken") && !chickenadded /*&& !groceries[index].Contains("chicken breasts")*/)
{
chicken = "Chicken";
lstItems.Items.Add(chicken);
// set to true
chickenadded = true;
// another way is not define boolean, just use "break"
break;
}
// reset index here
index++;
}
Disregarding any other problem or what the overall goal of the application is. You forgot to look at the actual line
if (groceries[index].Contains("chicken"))
It's worth a note that you should likely be using File.ReadLines or File.ReadAllLines instead. As it gives you a collection or enumerable to work with
Related
I have been out of the coding game for quite some time now and have forgot most of what I knew. I am looking to be able to read individual lines from a txt file and append them to separate textboxes but keep getting stumped and i'm running out of time for my deadline.
I want the code to do something like this:
Read (Line 1) from (User.txt)
Append (Line 1) to (txtFirstName)
Read (Line 2) from (User.txt)
Append (Line 2) to (txtLastName)
If possible i'd like to have the txt file read in as an array so that the individual lines can be used to fill separate textboxes.
Okay, so what I had written was this:
private void btnUser_Click(object sender, EventArgs e)
{
if(lstbUsers.Text == "Jordan Atkinson")
{
TextReader reader = new StreamReader(#"*FILEADDRESS*Jordan.txt");
txtUserFirstName.Text = reader.ReadLine();
string[] lines = System.IO.File.ReadAllLines(#"*FILEADDRESS*Jordan.txt");
foreach (string line in lines)
{
lstvUsers.Items.Add(line);
}
}
}
However, using the reader.ReadLine() only reads the top line and I want to be able to specify what line I want to read from.
If you want to read just a specific line from your file, you can do that this way:
int lineNumber = 10; // the line which you want to read
string line = File.ReadLines(pathToFile).Skip(lineNumber - 1).First();
This code will return the 10th line of your file. If you want to append this string to another, you can simply use the += operator or StringBuilder class.
I have form:
and a csv file containing these values:
110977,3871933,317731,0,
How would I be able to copy the CSV data and paste it into all the correct fields in one copy and paste action? (All the data will be in the correct order)
Thanks in advance!
I would suggest reading the CSV file by opening it, then split by comma, put your values into the string array and then update your textBoxes.
Refer to the answer to this question.
You can also use OpenFileDialog to provide the UI for opening the file.
EDIT:
I prepared some basic example to handle exactly the case you asked for. It assumes you have 4 values in the copied CSV line separated by comma (anyway if you have more than 4 in copied line just first 4 will be put into textBoxes). It only requires to copy the CSV line and paste it using Ctrl + V into the first textBox (txtValue1) so it is then splitted by , and all those values from copied CSV line are put into corresponding textBoxes (txtValue1, txtValue2, txtValue3, txtValue4 consecutively).
My form looks just like that:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
txtValue1.KeyDown += TxtValue1_KeyDown;
}
private void TxtValue1_KeyDown(object sender, KeyEventArgs e)
{
if (e.Control && e.KeyCode == Keys.V)
{
string csvLine = Clipboard.GetText();
if (String.IsNullOrEmpty(csvLine))
return;
string[] values = csvLine.Split(',');
if (values.Count() < 4)
return;
txtValue1.Text = values[0];
txtValue2.Text = values[1];
txtValue3.Text = values[2];
txtValue4.Text = values[3];
e.SuppressKeyPress = true;
}
}
}
It could of course be made more generic and handle possible exceptions. This is only to show how to solve what you need easily.
Copy/Pasting? More like reading CSV from a stream ?
Create a Model aka a class to store the values once you start reading the CSV using any sort of stream reader. As you read the positions of the fields from the CSV you can start storing them into your model and then it is easy from there. You might want to think about reading everything into a List, so you only read once.
Here is your class
public class Model
{
public string InvoiceNumber { get; set; }
...
}
Here is the CSV reading piece
using (StreamReader sr = new StreamReader(sourceFileName))
{
List<Model> modelList = new List<Model>();
string headerLine = sr.ReadLine();
string currentLine;
for (int i = 0; i < strArray.Length; i++)
{
while ((currentLine = sr.ReadLine()) != null)
{
string[] strArray = currentLine.Split(',');
Model myModel = new Model();
switch (i)
{
case 0: myModel.InvoiceNumber = = strArray[i]; break;
case 1: myModel.InvoiceHeaderId = strArray[i]; break;
}
}
}
modelList.Add(myModel);
}
}
From Here you can assign this to the UI.It depends which row you want to read, maybe filter the result to get the id, or filter my other pieces of data. Up to you to decide, you can add those filters in the for each loop. Or even better, take a look at LINQ. :D
foreach (var item in modelList)
{
txtInvoiceNumber.Text = mymodel.InvoiceNumber;
txtinvoiceHeaderId.Text = mymodel.InvoiceHeaderId;
}
I have a text file that i want to read into a richtextbox on my form using a button
Here is the text file:
[1]
Hello this is a text file. I am reading this into a richtextbox.
I want multiple rows into the textbox to display on one button click.
[/1]
Here is my code:
private void button2_Click(object sender, EventArgs e)
{
using (StreamReader reader = new StreamReader(#"F:\test.txt"))
{
bool content = false;
while ((line = reader.ReadLine()) != null)
{
if (line.Contains("[1]"))
{
content = true;
}
if (content == true)
{
txtContent.AppendText(reader.ReadLine());
}
if (line.Contains("[/1]"))
{
content = false;
break;
//txtContent.AppendText(reader.ReadLine());
}
}
}
}
When i click button2 it only adds the first line
how can i read all the text in between [1] and [/1]
I have looked into the use of XML but my text file will have alot of data in by the end so ive tried to avoid using it.
I would like to then go onto using the same richtextbox to store text inbetween [2] and [/2] on another button click
Thanks for your help
Your logic looks like it may skips lines.
You read a line in from the file and if it contains [1] you set your flag. Then you check if your flag is set and read another line from the file. So this won't include the previously read line. Then you check if that next line contains[/1] and break from your reading loop.
Say you read your first line and its "[1]Hello this is a text file." Your logic will not include "Hello this is a text file" in the RichTextBox, because you've requested the next line to be read. Then you check for your end tag ([/1]), which would result in false. Now we come back to the top of the loop and read the next line ("I am reading this into a richtextbox."). This will fail your first check, and your content flag is still true so now this current line will not be added to the RichTextBox because we did another ReadLine().
Now your question is stated like the beginning tag ([1]) is on a line by itself. If that's true, then just continue your loop after you set the content flag to true.
If you don't want your tags [1] and [/1] to not be in the RichTextBox then Replace them in the line variable and add the line variable to your RichTextBox. Don't read another line to add to your RichTextBox, just use the line you already read in if it meets your condition of being between your tags.
This snippet should handle all (generic formats) of your file, unless your tags appear again within your tags (For example, "[1][1][/1][/1]")
private void button2_Click(object sender, EventArgs e)
{
using (StreamReader reader = new StreamReader (#"F:\test.txt"))
{
bool content = false;
while ((line = reader.ReadLine()) != null)
{
if (line.Contains("[1]"))
{
content = true;
// You only need this continue if this is on a line by itself
continue;
}
if (content == true)
{
// The Replace should remove your tags and add what's left to the RichTextBox
txtContent.AppendText(line.Replace("[1]", "").Replace("[/1]", ""));
}
if(line.Contains("[/1]"))
{
content = false;
break;
}
}
}
}
I load text file into RichTextBox using OpenFIleDialog. But when a large amount of text is (for example song text about 50-70 lines) and I click OPEN program hangs for a few second (~3-5). Is it normal? Maybe there is some faster way or component to load text file? If my question is an inappropriate just delete it. Thanx.
if (openFileDialog1.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
string text = File.ReadAllText(openFileDialog1.FileName);
for (int i = 0; i < text.Length - 1; i++)
{
richTextBox1.Text = text;
}
}
I guess maybe ReadAllLines impeds it?
There is a similar question that deals with the fastest way of reading/writing files: What's the fastest way to read/write to disk in .NET?
However, 50-70 lines is nothing.. no matter how you read, it should fly in immediately. Are you maybe reading from a network share or something else that is causing the delay?
Edit:
Now that I see your code: Remove the loop and just write richTextBox1.Text = text; once. It doesn't make sense to assign the string in the loop since you already read the complete content of the file by using ReadAllText.
if (openFileDialog1.ShowDialog() == System.Windows.Forms.DialogResult.OK) {
string text = File.ReadAllText(openFileDialog1.FileName);
richTextBox1.Text = text;
}
void LoadFileToRTB(string fileName, RichTextBox rtb)
{
rtb.LoadFile(File.OpenRead(fileName), RichTextBoxStreamType.PlainText); // second parameter you can change to fit for you
// or
rtb.LoadFile(fileName);
// or
rtb.LoadFile(fileName, RichTextBoxStreamType.PlainText); // second parameter you can change to fit for you
}
Remove the for loop, because is useless:
string text = File.ReadAllText(openFileDialog1.FileName);
richTextBox1.Text = text;
text is a string that already contains all the text of the file to pass to the textBox.
Doing:
for(int i=0, i < text.Lengt-1; i++)
richTextBox1.Text = text;
you're assigning the text read from the file text.Length-1 times (Length is the number of characters of the string) and that's useless.
if (openFileDialog1.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
richTextBox1.Text = File.ReadAllText(openFileDialog1.FileName);
}
I have a Windows application that takes the data in the textboxes and writes them into a randomly generated text file, kinda keeping logs. Then there is this listbox that lists all these separate log files. The thing I want to do is to have another listbox display the file info of the selected one, the 2nd, 7th, 12th, ..., (2+5n)th lines of the text files that is selected after the button 'list info' is clicked. How is it possible to do this?
My code to update the first listbox is:
private void button2_Click(object sender, EventArgs e)
{
listBox1.Items.Clear();
DirectoryInfo dinfo = new DirectoryInfo(#"C:\Users\Ece\Documents\Testings");
// What type of file do we want?...
FileInfo[] Files = dinfo.GetFiles("*.txt");
// Iterate through each file, displaying only the name inside the listbox...
foreach (FileInfo file in Files)
{
listBox1.Items.Add(file.Name + " " +file.CreationTime);
}
}
On the SelectedIndexChanged event you want to get the selected item. I wouldn't suggest showing the second part in another list box, but i'm sure you can work out how from the example below if you require it. I would personally have a richTextBox, and just read the file to there:
//Get the FileInfo from the ListBox Selected Item
FileInfo SelectedFileInfo = (FileInfo) listBox.SelectedItem;
//Open a stream to read the file
StreamReader FileRead = new StreamReader(SelectedFileInfo.FullName);
//Read the file to a string
string FileBuffer = FileRead.ReadToEnd();
//set the rich text boxes text to be the file
richTextBox.Text = FileBuffer;
//Close the stream so the file becomes free!
FileRead.Close();
Or if you are persistant to sticking with the ListBox then:
//Get the FileInfo from the ListBox Selected Item
FileInfo SelectedFileInfo = (FileInfo) listBox.SelectedItem;
//Open a stream to read the file
StreamReader FileRead = new StreamReader(SelectedFileInfo.FullName);
string CurrentLine = "";
int LineCount = 0;
//While it is not the end of the file
while(FileRead.Peek() != -1)
{
//Read a line
CurrentLine = FileRead.ReadLine();
//Keep track of the line count
LineCount++;
//if the line count fits your condition of 5n + 2
if(LineCount % 5 == 2)
{
//add it to the second list box
listBox2.Items.Add(CurrentLine);
}
}
//Close the stream so the file becomes free!
FileRead.Close();