问题
Based on Prakash's answer here, I thought I'd try something like this to remove the oldest lines in a file prior to adding a new line to it:
private ExceptionLoggingService()
{
_fileStream = File.OpenWrite(GetExecutionFolder() + "\\Application.log");
_streamWriter = new StreamWriter(_fileStream);
}
public void WriteLog(string message)
{
const int MAX_LINES_DESIRED = 1000;
StringBuilder formattedMessage = new StringBuilder();
formattedMessage.AppendLine("Date: " + DateTime.Now.ToString());
formattedMessage.AppendLine("Message: " + message);
// First, remove the earliest lines from the file if it's grown too much
List<string> logList = File.ReadAllLines(_fileStream).ToList();
while (logList.Count > MAX_LINES_DESIRED)
{
logList.RemoveAt(0);
}
File.WriteAllLines(_fileStream, logList.ToArray());
_streamWriter.WriteLine(formattedMessage.ToString());
_streamWriter.Flush();
}
...but in my version of .NET (Compact Framework, Windows CE C# project in VS 2008), neither ReadAllLines() nor WriteAllLines() are available.
What is the ReadAllLines/WriteAllLines-challenged way of accomplishing the same thing?
UPDATE
This is doubtless kludgy, but it seems like it should work, and I'm going to test it out. I moved the "shorten the log file" code from the WriteLog() method to the constructor:
private ExceptionLoggingService()
{
const int MAX_LINES_DESIRED = 1000;
string uriPath = GetExecutionFolder() + "\\Application.log";
string localPath = new Uri(uriPath).LocalPath;
if (!File.Exists(localPath))
{
File.Create(localPath);
}
_fileStream = File.OpenWrite(localPath);
// First, remove the earliest lines from the file if it's grown too much
StreamReader reader = new StreamReader(_fileStream);
List<String> logList = new List<String>();
while (!reader.EndOfStream)
{
logList.Add(reader.ReadLine());
}
while (logList.Count > MAX_LINES_DESIRED)
{
logList.RemoveAt(0);
}
if (logList.Count > MAX_LINES_DESIRED)
{
_fileStream.Close();
File.Delete(GetExecutionFolder() + "\\Application.log");
File.Create(GetExecutionFolder() + "\\Application.log");
_fileStream = File.OpenWrite(GetExecutionFolder() + "\\Application.log");
}
_streamWriter = new StreamWriter(_fileStream);
foreach (String s in logList)
{
_streamWriter.WriteLine(s);
_streamWriter.Flush();
}
}
public void WriteLog(string message)
{
StringBuilder formattedMessage = new StringBuilder();
formattedMessage.AppendLine("Date: " + DateTime.Now.ToString());
formattedMessage.AppendLine("Message: " + message);
_streamWriter.WriteLine(formattedMessage.ToString());
_streamWriter.Flush();
}
回答1:
ReadAllLines
and WriteAllLines
are just hiding a loop from you. Just do:
StreamReader reader = new StreamReader(_fileStream);
List<String> logList = new List<String>();
while (!reader.EndOfStream)
logList.Add(reader.ReadLine());
Note that this is nearly identical to the implementation of File.ReadAllLines
(from MSDN Reference Source)
String line;
List<String> lines = new List<String>();
using (StreamReader sr = new StreamReader(path, encoding))
while ((line = sr.ReadLine()) != null)
lines.Add(line);
return lines.ToArray();
WriteAllLines
is simialr:
StreamWriter writer = new StreamWriter(path, false); //Don't append!
foreach (String line in logList)
{
writer.WriteLine(line);
}
回答2:
I would write simple extension methods for this, that do the job lazily without loading whole file to memory.
Usage would be something like this:
outfile.MyWriteLines(infile.MyReadLines().Skip(1));
public static class Extensions
{
public static IEnumerable<string> MyReadLines(this FileStream f)
{
var sr = new StreamReader(f);
var line = sr.ReadLine();
while (line != null)
{
yield return line;
line = sr.ReadLine();
}
}
public static void MyWriteLines(this FileStream f, IEnumerable<string> lines)
{
var sw = new StreamWriter(f);
foreach(var line in lines)
{
sw.WriteLine(line);
}
}
}
来源:https://stackoverflow.com/questions/27429716/how-can-i-remove-the-oldest-lines-in-a-file-when-using-a-filestream-and-streamwr