Zach R
Zach R

Reputation: 181

Overwrite/delete contents of a text file in c# .net

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.

Upvotes: 2

Views: 3538

Answers (3)

Jim Mischel
Jim Mischel

Reputation: 134125

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);
    }

Upvotes: 0

yuvin
yuvin

Reputation: 383

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());

Upvotes: 2

glenebob
glenebob

Reputation: 1983

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();
    }
}

Upvotes: 0

Related Questions