Try to do next - i want to check if some information is already exist if csv file, if yes - open form with label, and put to this label information from file
Code is next:
public void getEventTime(string filePath, string currDate, string currentDateTimeHM)
{
//reading the *.csv file and convert to the array of data
FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read);
StreamReader sr = new StreamReader(fs);
//create array for getting any vlaue from string
string[] arrOfData = sr.ReadToEnd().Split(new string[] { Environment.NewLine }, StringSplitOptions.None);
sr.Close();
List<string> lines = new List<string>();
bool status=false;//variable for showing form if event exist
foreach (var l in arrOfData)
{
if (l.Contains(currDate) && l.Contains(currentDateTimeHM))
{
string[] temp = l.Split(',').Take(5).ToArray();
notLabel.Text = temp[1].ToString();
status = true;
}
}
if (status)
{
//show Notification Form
Form NotificationForm = new Notification();
NotificationForm.Visible = true;
}
}
all works perfect - if information exist - new form opens, but notLabel.Text = temp[0].ToString(); this part have return nothing. During debuging i got next
means that code is correct but in strange for me reason result in programm - without this text.
where I make some mistake?
Below form with label
checked
few rows from file NotificationDesigner.Form.cs
this.notLabel.AutoSize = true;
this.notLabel.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(204)));
this.notLabel.Location = new System.Drawing.Point(12, 22);
this.notLabel.Name = "notLabel";
this.notLabel.Size = new System.Drawing.Size(34, 13);
this.notLabel.TabIndex = 0;
this.notLabel.Text = "label";
where do you call the method getEventTime and what is notLabel.
if the method getEventTime is called and set the notLabel.Text but after that the text is set again to string.Empty that there is the problem, so you should probably search or debug every change to notLabel.Text.
are you sure the it is notLabel the it is shown in the form? you can check that by registering to the mouseDown event and see that it is called when you click on the Label
one more thing, add break;
after your line
status = true;
go to the design and press the label, press F4 and search the name property, i bet it is not notLabel:
EDIT
i think i fount your problem
correct me if i'm wrong but this lines
if (status)
{
//show Notification Form
Form NotificationForm = new Notification();
NotificationForm.Visible = true;
}
are happening after you change the text... when what you meant is:
public void getEventTime(string filePath, string currDate, string currentDateTimeHM)
{
Form NotificationForm = new Notification();
//reading the *.csv file and convert to the array of data
FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read);
StreamReader sr = new StreamReader(fs);
//create array for getting any vlaue from string
string[] arrOfData = sr.ReadToEnd().Split(new string[] { Environment.NewLine }, StringSplitOptions.None);
sr.Close();
List<string> lines = new List<string>();
bool status=false;//variable for showing form if event exist
foreach (var l in arrOfData)
{
if (l.Contains(currDate) && l.Contains(currentDateTimeHM))
{
string[] temp = l.Split(',').Take(5).ToArray();
NotificationForm.NotText = temp[1].ToString();
status = true;
}
}
if (status)
{
//show Notification Form
NotificationForm.Visible = true;
}
}
and in the notification form do
public string NotText
{
set { notLabel.Text = value; }
}
Related
I have a text file containing some information that I want to edit. The file looks something like this:
id: 31
name: Anna
profession: Doctor
I can read that entry with a StreamReader, and present it in my application. I then want the user to be able to change the name and profession of an entry, so I'd like to edit these specific rows to the new values, while keeping id intact (in my real code, there's not just a few rows, but a lot of rows where only some should be changed). So, for example, I want the file, at the end of my operation, to look like this.
id: 31
name: Emma
profession: Programmer
However, I also have to take into account that sometimes the rows don't exist beforehand. For example, before editing Anna to Emma, it's not certain that she had a profession, the file could have looked like this:
id: 31
name: Anna
And in that case, I want to add the line profession: Programmerto the end there.
I tried using a FileStreamwith ReadWrite access, that I give to a StreamReader and a StreamWriter, but then I found no way of changing or replacing a line of text, only reading it and writing a new identical line while keeping the old.
using (FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.ReadWrite))
using (StreamReader reader = new StreamReader(fileStream))
using (StreamWriter writer = new StreamWriter(fileStream))
{
bool idExists = false;
bool nameExists = false;
bool tagsExist = false;
string line;
while((line = reader.ReadLine()) != null)
{
if (line.StartsWith("id:"))
idExists = true;
else if (line.StartsWith("name:"))
{
nameExists = true;
line = $"name: {entryToSave.Name}";
writer.WriteLine(line); // Will write an additional line and not replace
}
else if (line.StartsWith("profession:"))
{
professionExists = true;
line = $"profession: {entryToSave.Profession}";
writer.WriteLine(line); // Will write an additional line and not replace
}
}
if (!idExists)
writer.WriteLine($"id: {generatedId}");
if (!nameExists)
writer.WriteLine($"name: {entryToSave.Name}");
if (!professionExists)
writer.WriteLine($"profession: {entryToSave.Profession}");
}
I also tried using File.ReadAllLines, loop through the lines, and then write back all the lines to the file, only modifying the lines that were to be modified. However, I don't have access to the file through File.WriteAllLines for some reason that I don't understand, as a StreamWriter has access. Code:
var previousData = File.ReadAllLines(filePath);
var newData = new List<string>();
bool idExists = false;
bool nameExists = false;
bool professionExists = false;
for (int i = 0; i < previousData.Length; i++)
{
var line = previousData[i];
if (line.StartsWith("id:")
idExists = true;
else if (line.StartsWith("name:")
{
nameExists = true;
line = $"name: {entryToSave.Name}";
}
else if (line.StartsWith("profession:"))
{
professionExists = true;
line = $"profession: {entryToSave.Profession}";
}
newData.Add(line);
}
if (!idExists)
newData.Add($"id: {generatedId}");
if (!nameExists)
newData.Add($"name: {entryToSave.Name}");
if (!professionExists)
newData.Add($"profession: {entryToSave.Profession}");
File.WriteAllLines(filePath, newData.ToArray()); // Access denied
How is this most easily achieved, without file streams interfering with each other?
If you've already presented the data to the user in entries, enabling the user to edit name and profession, you could just read the file, get the ID and fill the remainder of the file with the value of the entries. The following is an example console application.
static void Main(string[] args)
{
var filePath = "test.txt";
// Simulated input from user
// these should come from entries in the application?
var name = "Foo";
var profession = "Bar";
var personData = new PersonData(); // class declared below
using (FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.ReadWrite))
using (StreamReader reader = new StreamReader(fileStream))
{
string line;
while ((line = reader.ReadLine()) != null)
{
if (line.StartsWith("id:"))
personData.ID = line;
}
} // Now reader and filestream is closed, file is available again.
// You don't specify what you would like to happen if personData.ID is null,
// so I make an assumption the generatedId is what you'd like to use.
if (string.IsNullOrWhiteSpace(personData.ID)
personData.ID = $"id: {generatedId}";
// Add the data from the entries
personData.Name = $"name: {name}";
personData.Profession = $"profession: {profession}";
File.Delete(filePath); // remove the file
using (FileStream fileStream = new FileStream(filePath, FileMode.OpenOrCreate, FileAccess.ReadWrite))
using (StreamWriter writer = new StreamWriter(fileStream))
{
writer.WriteLine(personData.ID);
writer.WriteLine(personData.Name);
writer.WriteLine(personData.Profession);
}
}
private class PersonData
{
public string ID { get; set; }
public string Name { get; set; }
public string Profession { get; set; }
}
Now you just have to find out how to get access to the file if you're having permission problems.
so everytime this runs through
OpenFileDialog xmlOpenFileDialog = new OpenFileDialog();
xmlOpenFileDialog.Filter = #"XML|*.xml";
xmlOpenFileDialog.FilterIndex = 1;
//Start
//Implement a way for user to have last opened file shown if program is closed by accident?
//xmlOpenFileDialog.InitialDirectory = System.Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory);
//End
xmlOpenFileDialog.Multiselect = false;
DialogResult userClickedOk = xmlOpenFileDialog.ShowDialog();
if (userClickedOk == DialogResult.OK)
{
lastKnownFileName = xmlOpenFileDialog.FileName;
System.IO.Stream filestream = xmlOpenFileDialog.OpenFile();
using (System.IO.StreamReader reader = new StreamReader(filestream))
{
UpChart_Chart.Serializer.IsResetWhenLoading = false;
UpChart_Chart.Serializer.Content = SerializationContents.Data;
UpChart_Chart.Serializer.SerializableContent += ",DataPoint.AxisLabel,DataPoint.Label,Series.AxisLabels,Series.Name,Series.ChartType,ChartChartArea.Name";
UpChart_Chart.Serializer.Load(reader);
}
then the data we have in the chart resets when new inputs happens?
how do we make sure that the data we have is correctly put in the right areas?
I'm trying to allow the user to add another entry to the CSV file my program is building. It is building it out of a database like this:
public void CreateCsvFile()
{
var filepath = #"F:\A2 Computing\C# Programming Project\ScheduleFile.csv";
var ListGather = new PaceCalculator();
var records =
from record in ListGather.NameGain()
.Zip(ListGather.PaceGain(),
(a, b) => new { Name = a, Pace = b })
group record.Pace by record.Name into grs
select String.Format("{0},{1}", grs.Key, grs.Average()); //reduces the list of integers down to a single double value by computing the average.
File.WriteAllLines(filepath, records);
}
I then am calling it into a datagridview like this:
private void button2_Click(object sender, EventArgs e)
{
CreateExtFile CsvCreate = new CreateExtFile();
CsvCreate.CreateCsvFile();
return;
}
private void LoadAthletes()
{
string delimiter = ",";
string tableName = "Schedule Table";
string fileName = #"F:\A2 Computing\C# Programming Project\ScheduleFile.csv";
DataSet dataset = new DataSet();
StreamReader sr = new StreamReader(fileName);
dataset.Tables.Add(tableName);
dataset.Tables[tableName].Columns.Add("Athlete Name");
dataset.Tables[tableName].Columns.Add("Pace Per Mile");
string allData = sr.ReadToEnd();
string[] rows = allData.Split("\r".ToCharArray());
foreach (string r in rows)
{
string[] items = r.Split(delimiter.ToCharArray());
dataset.Tables[tableName].Rows.Add(items);
}
this.dataGridView1.DataSource = dataset.Tables[0].DefaultView;
}
A button opens a window which contains fields to add a new entry to the csv file. This is how I am doing this:
private void AddToScheduleBtn_Click(object sender, EventArgs e)
{
string FileName = #"F:\A2 Computing\C# Programming Project\ScheduleFile.csv";
string AthleteDetails = textBox1.Text + "," + textBox2.Text;
File.AppendAllText(FileName, AthleteDetails);
AddToSchedule.ActiveForm.Close();
}
Although this works once, When I try and add another entry to my csv file again it says it is open in another process and the program crashes. When the data first appears in my datagridview, there is an empty row at the bottom which there shouldn't be. What is the best way of allowing me to re-use the process so I can append to the file more than once?
I think your line,
StreamReader sr = new StreamReader(fileName);
has the file opened. You want to do the following:
string allData = sr.ReadToEnd();
sr.Close();
sr.Dispose();
I didn't build your code, but this error is usually raised when the file reader was not closed :)
You should add sr.close() to your LoadAthletes method or implement the using for an automatic closing:
using (StreamReader sr = new StreamReader(fileName))
{
allData = sr.ReadToEnd();
}
Or use the following method :
allData = File.ReadAllText(fileName);
Hope this Help
For more information see this question do-i-need-to-explicitly-close-the-streamreader-in-c-sharp-when-using-it-to-load
my application is MVC3 C#; I am populating two dropdownlists using json using the following:
public ActionResult CheckWord(string cword)
{
try
{
List<string[]> arrayList = new List<string[]>();
List<string[]> stateList = new List<string[]>();
//
List<string[]> fileList = new List<string[]>();
//
string[] filePaths = Directory.GetFiles(System.Web.HttpContext.Current.Server.MapPath("/Video"), "*.srt");
string[] fnList = new string[filePaths.Length];
for (int i = 0; i < fnList.Length; ++i)
{
FileInfo fi = new FileInfo(filePaths[i]);
fnList[i] = fi.Name.Substring(0, fi.Name.LastIndexOf(".srt"));
}
int nFiles = filePaths.Length;
string cacheline = "";
string line;
for (int i = 0; i < nFiles; ++i)
{
StreamReader file = new StreamReader(System.Web.HttpContext.Current.Server.MapPath("/Video/" + fnList[i] + ".srt"));
List<string> lines = new List<string>();
List<string> statments = new List<string>();
//
List<string> fnames = new List<string>();
//
while ((line = file.ReadLine()) != null)
{
if (line.Contains(cword))
{
statments.Add(line);
// fnames.Add(file);
lines.Add(cacheline);
}
cacheline = line;
}
file.Close();
var array = lines.ToArray();
arrayList.Add(array);
stateList.Add(statments.ToArray());
}
return Json(new { success = true, fnList = fnList, arrayList = arrayList.ToArray(), stateList = stateList.ToArray() });
}
catch { }
return Json(new { success = false });
}
I am checking if a word exists in a group of files; then display the names of files in one dropdownlist and the lines from each file in the other dropdownlist. It works fine, however it gives me a list of all files becasue I am sending back fnlist. However I am trying to display only the files that contain that word; I could not get the file name from the StreamReader and add it to an array fileList. I would appreciate your suggestions, thanks in advance.
Already so many lists! Why not another? You already open the file with fnList[i] within the context of the loop, so...
List<string[]> results = new List<string[]>();
....
while ((line = file.ReadLine()) != null) {
if (line.Contains(cword)) {
results.Add(fnList[i]);
break; // optional, if possible, but if you need to continue check for dupes
}
}
....
return Json(new {
success = true,
fnList = results.ToArray(),
arrayList = arrayList.ToArray(),
stateList = stateList.ToArray()
});
System.IO.StreamReader file = new System.IO.StreamReader("setup.txt");
Later on, we would like to print the name of the file being used by stream reader.
eg, if there is an error, I would like a message box that displays "error reading file: 'filename'"
MessageBox.Show("Error loading " + ((FileStream)file.BaseStream).Name);
Not sure what exactly you are looking for but since you are creating StreamReader from a file name why not have file name in a separate variable and use it later:
var fileName = System.Web.HttpContext.Current.Server.MapPath(
"/Video/" + fnList[i] + ".srt");
StreamReader file = new StreamReader(fileName);
I want to load content stored in a file, into the fields of a WinForms GUI.
My approach right now: I've got a streamwriter which writes each text box to a line in a .txt file. I have the streamreader setup but i have no idea how to get it to load each line into seperate text boxes. For example: Task1_name (line 1) and task1_desc (line 2) need to be in seperate text boxes, how could i get it to load into the boxes?
Thanks
Code:
Save Button:
void Save_buttonClick(object sender, EventArgs e)
{
DialogResult dialogResult = MessageBox.Show("Do you want to save?", "Save", MessageBoxButtons.YesNo);
if (dialogResult == DialogResult.Yes)
{
FileStream file = new FileStream("test.txt", FileMode.OpenOrCreate, FileAccess.Write);
StreamWriter sw = new StreamWriter(file);
sw.WriteLine(task1_name.Text);
sw.WriteLine(task1_desc.Text);
sw.WriteLine(task1_date.Value);
sw.WriteLine(task1_check.Checked);
sw.Close();
}
}
Load Button:
void Load_buttonClick(object sender, EventArgs e)
{
DialogResult dialogResult = MessageBox.Show("Do you want to load?", "Load", MessageBoxButtons.YesNo);
if (dialogResult == DialogResult.Yes)
{
FileStream file = new FileStream("test.txt", FileMode.OpenOrCreate, FileAccess.Write);
StreamReader sr = new StreamReader(file);
sr.Close();
}
}
Use XML Serialization. It would look something like this:
public class MySettings
{
public String name {get;set;}
public String name {get;set;}
public DateTime date {get;set;}
public bool checked {get;set;}
}
void Save()
{
var s = new MySettings
{
name = this.task1_Name.Text,
desc = this.task1_Desc.Text,
date = this.task1_Date.Value,
checked = this.task1_Check.Checked
};
var ser = new XmlSerializer(typeof(MySettings));
using (var fs = new FileStream(path, FileMode.Create))
{
using (var tw = new StreamWriter(fs, new UTF8Encoding()))
{
var ns = new XmlSerializerNamespaces();
ns.Add("", "");
ser.Serialize(tw, this, ns);
}
}
}
And to load it would look like this:
static MySettings Load()
{
var ser = new XmlSerializer(typeof(MySettings));
MySettings settings = null;
try
{
using (var s = File.OpenRead(path))
{
settings = (MySettings) ser.Deserialize(s);
// optionally validate here
}
}
catch (Exception ex1)
{
MessageBox.Show("Cannot read settings. " + ex1.Message,
"error");
settings = null;
}
return settings;
}
And then of course resetting your form would be like this:
var settings = Load();
this.task1_Name.Text = settings.name;
this.task1_Desc.Text = settings.desc;
this.task1_Date.Value = settings.date;
this.task1_Check.Checked = settings.checked;
You can add every line into a List and access them by index:
//...
List<string> lines = new List<string>();
using (StreamReader sr = new StreamReader(file))
{
while(!sr.EndOfStream)
{
lines.Add(sr.ReadLine());
}
}
task1_name.Text = lines[0];
task1_desc.Text = lines[1];
//...
Just read the lines and populate the form in the same order as you wrote them:
if (dialogResult == DialogResult.Yes)
{
FileStream file = new FileStream("test.txt", FileMode.OpenOrCreate, FileAccess.Write);
StreamReader sr = new StreamReader(file);
task1_name.Text = sr.ReadLine();
task1_desc.Text = sr.ReadLine();
task1_date.Value = DateTime.Parse(sr.ReadLine());
task1_checked.Checked = bool.Parse(sr.ReadLine());
sr.Close();
}