我正在创建一个程序,将学生对象列表写入文本文件并需要保存,我可以简单地覆盖文件内容或删除内容并重写新列表。这是我在搜索后尝试使用的代码,
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");
}
我已经看到File.WriteAllText()
意在覆盖文件,但保存程序时不会覆盖任何内容。
答案 0 :(得分:2)
您必须在StudentInfoHolder
循环之前重置foreach
类成员,或者更好,使用本地字符串变量和String.Format
方法,如下所示:
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);
另外,你是File.WriteAllText
覆盖文件内容是对的,所以这一行没用:
File.WriteAllText(SaveFileDia.FileName, string.Empty);
<强>更新强>
正如@kevin正确指出的那样,在循环中使用StringBuilder
而不是字符串连接更有效:
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());
答案 1 :(得分:0)
尝试更多类似以下的内容。它避免了两次打开文件,以及字符串连接,这对于不可变字符串来说不是一个好主意。
// 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();
}
}
答案 2 :(得分:0)
没有充分的理由在将其写入文件之前缓冲内存中的所有内容。通过调用File.CreateText打开文件更容易,然后将每一行写入其中,如下所示:
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);
}
}
}
我还稍微重构了你的代码,预先颠倒了这两个测试的逻辑,以减少代码中的嵌套。
如果你真的想要一个包含所有内容的字符串,那么你可以修改上面的内容来轻松完成。使用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);
}