So I want to put certain lines into a text box, say I use the "Search Function" to search transaction ID, it would look through the transactions.txt file and find the transaction ID and Read the 6 lines under it which show the transactions Details, once found this would then go to a the listbox which then you could edit the transaction.
I was wondering would you use loops and arrays to do this, and could someone show me how, Thank you!
Heres my current code:
//Creates a textfile with details of the transaction
public void CreateFile()
{
StreamWriter outputFile;
outputFile = File.AppendText("Transactions.txt");
outputFile.WriteLine("Investor :" +" " + InvestorNameLabel.Text);
outputFile.WriteLine("Initial Amount" + " " +AmountLabel.Text);
outputFile.WriteLine("Date Invested" +" " +DateLabel.Text);
outputFile.WriteLine("Period Chosen" + " "+DaysInvestedLabel.Text);
outputFile.WriteLine("Rate Chosen" + " " + RateLabel.Text);
outputFile.WriteLine("Total Interest" + " " +InterestAmountLabel.Text);
outputFile.WriteLine("Transaction Number :" + " " + TransactionIDLabel.Text);
outputFile.Close();
MessageBox.Show("Transaction file for Transaction: " + TransactionIDLabel.Text + " " +"Was Created", "Transaction File");
}
//puts all transactions in listbox
//needs to be able to find certain transactions
private void button1_Click(object sender, EventArgs e)
{
using (StreamReader sr = new StreamReader("transactions.txt"))
{
string line;
while ((line = sr.ReadLine()) != null)
{
listBox1.Items.Add(line);
}
}
}
Try This:
string ID = "23";
bool idFound=false;
int count = 0;
foreach (var line in File.ReadLines("transactions.txt"))
{
if (idFound && count < 6)
{
listBox1.Items.Add(line);
count++;
}
if(line.Contains(ID))//if you wantto match exactly use if(line.Equals(ID))
{
idFound = true;
}
}
Related
I'm making a program that writes a list of student objects to a text file and needs to be saved, I could either simply overwrite the contents of the file or delete the contents and rewrite the new list. This is the code I've tried using after some searching,
private void saveTSMI_Click(object sender, EventArgs e)
{
if (lstStudNames.Items.Count != 0)
{
SaveFileDia.Filter = "Text Files | *.txt";
if (SaveFileDia.ShowDialog() == DialogResult.OK)
{
//Clear the file
File.WriteAllText(SaveFileDia.FileName, string.Empty);
//Put all the student info into a string
foreach (Stud student in StudentList)
{
StudentInfoHolder += "Name: " + student.Name + Environment.NewLine +
"Subject: " + student.Subject + Environment.NewLine +
"Age: " + student.age + Environment.NewLine +
"Grade: " + student.Grade + Environment.NewLine
+ Environment.NewLine;
}
Clipboard.SetText(StudentInfoHolder);
File.WriteAllText(SaveFileDia.FileName, StudentInfoHolder);
}
}
else
{
MessageBox.Show("Nothing to save");
}
I've seen that File.WriteAllText() is meant to overwrite the file but nothing is overwritten when the program is saved.
You have to either reset the StudentInfoHolder class member before the foreach loop, or even better, use a local string variable in combination with String.Format method like this:
string studentInfoHolder;
foreach (Stud student in StudentList)
{
studentInfoHolder +=
string.Format("Name: {0}\r\nSubject: {1}\r\nAge: {2}\r\nGrade: {3}",
student.Name, student.Subject, student.age, student.Grade);
}
File.WriteAllText(SaveFileDia.FileName, studentInfoHolder);
Also, you're right that File.WriteAllText overwrites the file content, so this line is useless:
File.WriteAllText(SaveFileDia.FileName, string.Empty);
Update
As #kevin correctly pointed out, it is more efficient to use StringBuilder in the loop instead of the string concatenation:
StringBuilder studentInfoHolder;
foreach (Stud student in StudentList)
{
studentInfoHolder.AppendFormat("Name: {0}\r\nSubject: {1}\r\nAge: {2}\r\nGrade: {3}",
student.Name, student.Subject, student.age, student.Grade);
}
File.WriteAllText(SaveFileDia.FileName, studentInfoHolder.ToString());
Try something more like the following. It avoids opening the file twice, and string concatenation, which is not a great idea with immutable strings.
// This line over-writes the file if it exists, or otherwise creates it.
using (TextWriter fileWriter = new StreamWriter(SaveFileDia.FileName, append: false))
{
foreach (Stud student in StudentList)
{
fileWriter.WriteLine($"Name: {student.Name}");
fileWriter.WriteLine($"Subject: {student.Subject}");
fileWriter.WriteLine($"Age: {student.age}");
fileWriter.WriteLine($"Grade: {student.Grade}");
fileWriter.WriteLine();
}
}
There's no good reason to buffer all that in memory before writing it to the file. It's easier to open the file by calling File.CreateText, and then write each line to it, like this:
private void saveTSMI_Click(object sender, EventArgs e)
{
if (lstStudNames.Items.Count == 0)
{
MessageBox.Show("Nothing to save");
return;
}
SaveFileDia.Filter = "Text Files | *.txt";
if (SaveFileDia.ShowDialog() != DialogResult.OK)
{
return;
}
// Create the file (overwrite if it already exists),
// and write each student record.
using (var outFile = File.CreateText(SaveFileDia.FileName))
{
foreach (Stud student in StudentList)
{
outFile.WriteLine("Name: " + student.Name);
outFile.WriteLine("Subject: " + student.Subject);
outFile.WriteLine("Age: " + student.age);
outFile.WriteLine("Grade: " + student.Grade);
}
}
}
I also refactored your code a bit, reversing the logic on those two tests up front so as to reduce the nesting in your code.
Update after comment
If you really want a string to contain all that stuff, then you can modify the above to do it pretty easily. Replace the loop that writes to file with this one that uses a StringWriter:
// Create a StringWriter to hold the data, and write each line.
using (var sWriter = new StringWriter())
{
foreach (Stud student in StudentList)
{
sWriter.WriteLine("Name: " + student.Name);
sWriter.WriteLine("Subject: " + student.Subject);
sWriter.WriteLine("Age: " + student.age);
sWriter.WriteLine("Grade: " + student.Grade);
}
// write the data to the file
StudentInfoHolder = sWriter.ToString();
File.WriteAllText(SaveFileDia.FileName, StudentInfoHolder);
}
I need to fill a text file with information about workers. Then I need to read from the file and search for an ID that user tries to find. For example my file contains ids 1,2,3 and if I try to find id 3 and it matches, then this worker's all information is written in console. Otherwise it writes a text A worker cannot be found.
using System;
using System.IO;
class Program
{
static void Main(string[] args)
{
string file = "C:\\Temp\\registery.txt";
FileStream fOutStream = File.Open(file, FileMode.Append, FileAccess.Write);
StreamWriter sWriter = new StreamWriter(fOutStream);
int[] id = { 1, 2, 3 };
string[] name = { "John", "Carl", "Thomas" };
float[] salary = { 3500, 4800, 2100 };
for (int i = 0; i < id.Length; i++)
{
sWriter.WriteLine(id[i] + " " + name[i] + " " + salary[i]);
}
sWriter.Flush();
sWriter.Close();
FileStream fInStream = File.OpenRead(file);
StreamReader sReader = new StreamReader(fInStream);
int id2;
Console.WriteLine("Type worker's id");
id2 = int.Parse(Console.ReadLine());
bool a;
a = sReader.ReadToEnd().Contains(id2);
Console.WriteLine(a);
sReader.Close();
}
}
If you want to create a text file to be searchable, it should be delimited by a separator like comma /TAB
so modify your code:
sWriter.WriteLine(id[i] + "," + name[i] + "," + salary[i]);
To search your text file by id/name/..whatever and use AND/OR, you can use the method described here:
How would I convert data in a .txt file into xml? c#
BTW: Re-factor your code to create the file in a separate method, and the search in other one.
I found a solution myself to my problem and it worked good enough. It might not be the best solution. I removed bool things and I replaced the whole thing with this:
string line;
while ((line = sReader.ReadLine()) != null)
{
if (line.Contains("id: " + id2))
{
Console.WriteLine(line);
break;
}
else if ((line = sReader.ReadLine()) == null)
{
Console.WriteLine("Worker not found with id " + id2);
}
}
And I fixed the upper for loop to look like this:
sWriter.WriteLine("id: " + id[i] + " name: " + name[i] + " salary: " + salary[i]);
I have taken the input code through file and i have to generate data according to it and output it's result in a text file as well..
My Output Code is below..
public void Generator()
{
/// ....... Code
public void DisplayTOKENS()
{
using (StreamWriter writer =
new StreamWriter("C:\\Users\\saeed\\Documents\\Outputt.txt"))
{
for (int i = 0; i < j;i++ )
{
tok[i].Display_Token();
} }
}
// and in other structur named TOKEN
public void Display_Token()
{ /*
using (StreamWriter writer =
new StreamWriter("C:\\Users\\saeed\\Documents\\Outputt.txt"))
{
writer.Write("( " + this.Class_Part + " , ");
writer.Write(this.Value_Part + " , ");
writer.Write(this.Line_no + " )");
writer.WriteLine();
}*/
Console.Write("( " + this.Class_Part + " , ");
Console.Write(this.Value_Part + " , ");
Console.Write(this.Line_no + " )");
Console.WriteLine();
}
When i try to directly work in Display_Token then it just simply show the last line in file.. i want to display the complete array in the file. waiting for some positive response !!
That StreamWriter constructor overwrites the existing file. So, each token effectively deletes whatever was written earlier then writes its content. That is why you only see the last token's content in the file.
Use the overload with the "append" argument and pass true so that the existing file is not deleted.
You have to check if file exists and than do "append" operation instead of "overwrite".
// in DisplayTOKENS()
string fileName = "C:\\Users\\saeed\\Documents\\Outputt.txt";
if (System.IO.File.Exists(fileName))
System.IO.File.Delete(fileName);
for (int i = 0; i < j; i++)
{
tok[i].Display_Token(fileName);
}
// in Display_Token(string fileName)
System.IO.File.AppendAllText(fileName, "( " + this.Class_Part + " , " + this.Value_Part + " , " + this.Line_no + " )");
I have c# application where it displays a message on messagebox after the query is run.At the sametime I want it to write a logfile. This is what i tried but no luck. My logfile was empty.
It had created a empty file.
private void backgroundWorker_Import_DoWork(object sender, DoWorkEventArgs e)
{
//Finally, loop through each row in the dataView and execute INSERT Statements against database
int recCount = 0;
successCount = 0;
failedCount = 0;
dv.RowFilter = "execute_bit IN ('1')";
using (MySqlConnection connectionMySql = new MySqlConnection(connectionStringMySql))
{
connectionMySql.Open();
MySqlCommand commandMySql = new MySqlCommand();
commandMySql.Connection = connectionMySql;
foreach (DataRowView rowView in dv)
{
recCount++;
backgroundWorker_Import.ReportProgress(recCount);
commandMySql.CommandText = rowView["sql"].ToString();
try
{
successCount = successCount + commandMySql.ExecuteNonQuery();
//WriteToLogFile("");
//WriteToLogFile("");
**WriteToLogFile(DateTime.Now.ToString() + ", " + recCount.ToString() + "," + successCount.ToString() + "," + failedCount.ToString());
}**
catch (Exception)
{
failedCount++;
}
}
}
}
private void backgroundWorker_Import_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
string msg = "";
msg = msg + "Records successfully imported: " + successCount.ToString() + Environment.NewLine;
msg = msg + "Records that failed to import: " + failedCount.ToString() + Environment.NewLine + Environment.NewLine;
msg = msg + "Records excluded from import (20 minute grace-period): " + (tblVehicles.Rows.Count - successCount - failedCount).ToString();
progressBar1.Visible = false;
MessageBox.Show( msg, "Operation complete", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
**private void WriteToLogFile(string[] output)
{
StreamWriter sw = null;
FileStream fs = null;
string logfileFileName = System.IO.Path.Combine( "C:/luvi/logfile.txt");
fs = File.Open(logfileFileName, FileMode.Append, FileAccess.Write);
sw = new StreamWriter(fs, System.Text.Encoding.UTF8);
foreach (string line in output)
{
sw.WriteLine(line);
}
sw.Close();
sw = null;
}**
You could use File.WriteAllLines as shown in this topic.
Its' syntax is as follows:
public static void WriteAllLines(
string path,
string[] contents
)
In your case you would use it like so:
string logfileFileName = #"C:/luvi/logfile.txt";
File.WriteAllLines(logfileFileName, output);
Note: this overwrites the file, if you want to append them use File.AppendAllLines.
You need to actually call your method aswell, which may be a problem because I do not see that in your code. In the following changes I have replaced the string msg for an array, and added those (you could also use a list and call list.Add).
private void backgroundWorker_Import_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
string[] msg = new string[] {};
msg[0] = "Records successfully imported: " + successCount.ToString();
msg[1] = "Records that failed to import: " + failedCount.ToString();
msg[2] = "Records excluded from import (20 minute grace-period): " + (tblVehicles.Rows.Count - successCount - failedCount).ToString();
// Write to log!
WriteToLogFile(msg);
// Show to messagebox.
string showmsg = msg[0] + Environment.NewLine + msg[1] + Environment.NewLine + msg[2];
progressBar1.Visible = false;
MessageBox.Show(showmsg, "Operation complete", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
private void WriteToLogFile(string[] output)
{
string logfileFileName = "C:/luvi/logfile.txt";
File.AppendAllLines(logfileFileName, output);
}
it seem problem with WriteToLogFile( string[] output) method. You are passing single string while it is expecting arrary of string. catch block is failing it silently.
I am fairly new to C# and I have written several functioning programs, but all of them have been single thread applications. This is my first multi-threaded application and I am struggling to resolve this "Cross-thread operation not valid: Control 'cbLogType' accessed from a thread other than the one it was created on" error. My application searches Windows Event viewer for a user defined Event ID in a user defined Event Log Source(cbLogType). I am using a backgroundworker process to do all the work and I am using the worker.reportprogress to update a label, however, I receive the above error when debugging. I have tried several Invoke methods, but none seem to resolve my error. I have also tried removing the combobox and setting the Log Source directly in the code, which works to an extent, but still fails. I have included my code and any help would be greatly appreciated. I suspect that I might not be using the Invoke method correctly. Thanks in advance!
CODE:
private void bgWorker1_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = sender as BackgroundWorker;
{
if (File.Exists(#"C:\Events.log"))
MessageBox.Show("File 'Events.log' already exists. All new data will be appended to the log file!", "Warning!");
string message = string.Empty;
string eventID = (tbEventID.Text);
string text;
EventLog eLog = new EventLog();
Invoke((MethodInvoker)delegate() { text = cbLogType.Text; });
eLog.Source = (this.cbLogType.Text); // I am receiving the error here
eLog.MachineName = ".";
int EventID = 0;
string strValue = string.Empty;
strValue = tbEventID.Text.Trim();
//string message = string.Empty;
EventID = Convert.ToInt32(strValue); // Convert string to integer
foreach (EventLogEntry entry in eLog.Entries)
{
int entryCount = 1;
if (cbDateFilter.Checked == true)
{
if (entry.TimeWritten > dtPicker1.Value && entry.TimeWritten < dtPicker2.Value)
if (entry.InstanceId == EventID)
message = "Event entry matching " + (tbEventID.Text) + " was found in " + (cbLogType.Text);
using (StreamWriter writer = new StreamWriter(#"C:\Events.log", true))
writer.WriteLine("EventID: " + entry.InstanceId +
"\r\nDate Created: " + entry.TimeWritten +
"\r\nEntry Type: " + entry.EntryType +
"\r\nMachinename: " + entry.MachineName +
"\r\n" +
"\r\nMessage: " + entry.Message +
"\r\n");
if (entry.InstanceId != EventID)
message = "No event ids matching " + (tbEventID.Text) + " was found in " + (cbLogType.Text);
}
else
{
if (cbDateFilter.Checked == false)
{
if (entry.InstanceId == EventID)
using (StreamWriter writer = new StreamWriter(#"C:\Events.log", true))
writer.WriteLine("EventID: " + entry.InstanceId +
"\r\nDate Created: " + entry.TimeWritten +
"\r\nEntry Type: " + entry.EntryType +
"\r\nMachinename: " + entry.MachineName +
"\r\n" +
"\r\nMessage: " + entry.Message +
"\r\n");
else if (entry.InstanceId != EventID)
message = "No event ids matching " + (tbEventID.Text) + " was found in " + (cbLogType.Text);
}
bgWorker1.ReportProgress((entryCount) * 10, message);
entryCount++;
}
}
}
}
private void bgWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
lblStat.Text = e.UserState.ToString();
}
You're accessing cbLogType in a non-UI thread.
Change to
eLog.Source = text;