[英]How to delete a line from a text file in C#?
我有一個問題:如何從 C# 的文本文件中刪除一行?
對於非常大的文件,我會做這樣的事情
string tempFile = Path.GetTempFileName();
using(var sr = new StreamReader("file.txt"))
using(var sw = new StreamWriter(tempFile))
{
string line;
while((line = sr.ReadLine()) != null)
{
if(line != "removeme")
sw.WriteLine(line);
}
}
File.Delete("file.txt");
File.Move(tempFile, "file.txt");
更新我最初是在 2009 年寫的,我認為更新可能會很有趣。 今天,您可以使用LINQ 和延遲執行來完成上述操作
var tempFile = Path.GetTempFileName();
var linesToKeep = File.ReadLines(fileName).Where(l => l != "removeme");
File.WriteAllLines(tempFile, linesToKeep);
File.Delete(fileName);
File.Move(tempFile, fileName);
上面的代碼與第一個示例幾乎完全相同,逐行讀取,同時在 memory 中保留最少量的數據。
但是,免責聲明可能是正確的。 由於我們在這里討論的是文本文件,因此您很少需要將磁盤用作中間存儲介質。 如果您不處理非常大的日志文件,則將內容讀入 memory 應該沒有問題,並且避免處理臨時文件。
File.WriteAllLines(fileName,
File.ReadLines(fileName).Where(l => l != "removeme").ToList());
請注意, .ToList
在這里對於強制立即執行至關重要。 另請注意,所有示例都假定文本文件是 UTF-8 編碼的。
讀取文件,刪除 memory 中的行並將內容放回文件(覆蓋)。 如果文件很大,您可能希望逐行讀取它,並創建一個臨時文件,然后替換原始文件。
我同意 John Saunders 的觀點,這並不是 C# 特定的。 但是,要回答您的問題:您基本上需要重寫文件。 有兩種方法可以做到這一點。
File.ReadAllLines
)List<string>
然后刪除該行可能是最簡單的)File.WriteAllLines
) - 可能使用ToArray
再次將List<string>
轉換為字符串數組這意味着你必須知道你有足夠的 memory。 替代:
TextReader
/ TextWriter
,例如使用File.OpenText
和File.CreateText
)TextReader.ReadLine
) - 如果您不想刪除它,請將其寫入 output 文件 ( TextWriter.WriteLine
)using
語句,這將自動發生)要從文本文件中刪除項目,首先將所有文本移動到列表中,然后刪除您想要的任何項目。 然后將存儲在列表中的文本寫入文本文件:
List<string> quotelist=File.ReadAllLines(filename).ToList();
string firstItem= quotelist[0];
quotelist.RemoveAt(0);
File.WriteAllLines(filename, quotelist.ToArray());
return firstItem;
我擴展了 Markus Olsson 的建議,並提出了這個 class,它添加了多個搜索字符串和幾個事件:
public static class TextLineRemover
{
public static void RemoveTextLines(IList<string> linesToRemove, string filename, string tempFilename)
{
// Initial values
int lineNumber = 0;
int linesRemoved = 0;
DateTime startTime = DateTime.Now;
// Read file
using (var sr = new StreamReader(filename))
{
// Write new file
using (var sw = new StreamWriter(tempFilename))
{
// Read lines
string line;
while ((line = sr.ReadLine()) != null)
{
lineNumber++;
// Look for text to remove
if (!ContainsString(line, linesToRemove))
{
// Keep lines that does not match
sw.WriteLine(line);
}
else
{
// Ignore lines that DO match
linesRemoved++;
InvokeOnRemovedLine(new RemovedLineArgs { RemovedLine = line, RemovedLineNumber = lineNumber});
}
}
}
}
// Delete original file
File.Delete(filename);
// ... and put the temp file in its place.
File.Move(tempFilename, filename);
// Final calculations
DateTime endTime = DateTime.Now;
InvokeOnFinished(new FinishedArgs {LinesRemoved = linesRemoved, TotalLines = lineNumber, TotalTime = endTime.Subtract(startTime)});
}
private static bool ContainsString(string line, IEnumerable<string> linesToRemove)
{
foreach (var lineToRemove in linesToRemove)
{
if(line.Contains(lineToRemove))
return true;
}
return false;
}
public static event RemovedLine OnRemovedLine;
public static event Finished OnFinished;
public static void InvokeOnFinished(FinishedArgs args)
{
Finished handler = OnFinished;
if (handler != null) handler(null, args);
}
public static void InvokeOnRemovedLine(RemovedLineArgs args)
{
RemovedLine handler = OnRemovedLine;
if (handler != null) handler(null, args);
}
}
public delegate void Finished(object sender, FinishedArgs args);
public class FinishedArgs
{
public int TotalLines { get; set; }
public int LinesRemoved { get; set; }
public TimeSpan TotalTime { get; set; }
}
public delegate void RemovedLine(object sender, RemovedLineArgs args);
public class RemovedLineArgs
{
public string RemovedLine { get; set; }
public int RemovedLineNumber { get; set; }
}
用法:
TextLineRemover.OnRemovedLine += (o, removedLineArgs) => Console.WriteLine(string.Format("Removed \"{0}\" at line {1}", removedLineArgs.RemovedLine, removedLineArgs.RemovedLineNumber));
TextLineRemover.OnFinished += (o, finishedArgs) => Console.WriteLine(string.Format("{0} of {1} lines removed. Time used: {2}", finishedArgs.LinesRemoved, finishedArgs.TotalLines, finishedArgs.TotalTime.ToString()));
TextLineRemover.RemoveTextLines(new List<string> { "aaa", "bbb" }, fileName, fileName + ".tmp");
我寫了一個從文件中刪除行的方法。
該程序using System.IO
。
查看我的代碼:
void File_DeleteLine(int Line, string Path)
{
StringBuilder sb = new StringBuilder();
using (StreamReader sr = new StreamReader(Path))
{
int Countup = 0;
while (!sr.EndOfStream)
{
Countup++;
if (Countup != Line)
{
using (StringWriter sw = new StringWriter(sb))
{
sw.WriteLine(sr.ReadLine());
}
}
else
{
sr.ReadLine();
}
}
}
using (StreamWriter sw = new StreamWriter(Path))
{
sw.Write(sb.ToString());
}
}
我很簡單:
我意識到這已經很長時間了,但這對我有幫助,所以我想改進它。 Leonhard 的回答對我非常有用。 但是,如果您的文本文件真的像我的一樣大,StringBuilder 將給出內存不足錯誤。 所以我改為這樣使用它。 創建一個新文件並寫入其中。 然后,您可以根據需要刪除第一個文件。 請注意, Line 變量確定文件將被刪除到哪一行。 您可以對其進行修改以指定要刪除的行的間隔。
void File_DeleteLine(int Line, string Path, string newPath)
{
StreamReader reader = new StreamReader(Path);
StreamWriter writer = new StreamWriter(newPath);
int Countup = 0;
while (!reader.EndOfStream)
{
Countup++;
if (Countup > Line)
{
writer.WriteLine(reader.ReadLine());
}
else
{
reader.ReadLine();
}
}
}
string fileIN = @"C:\myTextFile.txt";
string fileOUT = @"C:\myTextFile_Out.txt";
if (File.Exists(fileIN))
{
string[] data = File.ReadAllLines(fileIN);
foreach (string line in data)
if (!line.Equals("my line to remove"))
File.AppendAllText(fileOUT, line);
File.Delete(fileIN);
File.Move(fileOUT, fileIN);
}
從多個文件中刪除一段代碼
為了擴展@Markus Olsson 的答案,我需要從多個文件中刪除一段代碼。 我在核心項目中遇到瑞典字符問題,因此我需要安裝 System.Text.CodePagesEncodingProvider nuget package 並使用 System.Text.Encoding.GetEncoding(1252) 而不是 System.Text.Encoding.UTF8。
public static void Main(string[] args)
{
try
{
var dir = @"C:\Test";
//Get all html and htm files
var files = DirSearch(dir);
foreach (var file in files)
{
RmCode(file);
}
}
catch (Exception e)
{
Console.WriteLine(e.Message);
throw;
}
}
private static void RmCode(string file)
{
string tempFile = Path.GetTempFileName();
using (var sr = new StreamReader(file, Encoding.UTF8))
using (var sw = new StreamWriter(new FileStream(tempFile, FileMode.Open, FileAccess.ReadWrite), Encoding.UTF8))
{
string line;
var startOfBadCode = "<div>";
var endOfBadCode = "</div>";
var deleteLine = false;
while ((line = sr.ReadLine()) != null)
{
if (line.Contains(startOfBadCode))
{
deleteLine = true;
}
if (!deleteLine)
{
sw.WriteLine(line);
}
if (line.Contains(endOfBadCode))
{
deleteLine = false;
}
}
}
File.Delete(file);
File.Move(tempFile, file);
}
private static List<String> DirSearch(string sDir)
{
List<String> files = new List<String>();
try
{
foreach (string f in Directory.GetFiles(sDir))
{
files.Add(f);
}
foreach (string d in Directory.GetDirectories(sDir))
{
files.AddRange(DirSearch(d));
}
}
catch (System.Exception excpt)
{
Console.WriteLine(excpt.Message);
}
return files.Where(s => s.EndsWith(".htm") || s.EndsWith(".html")).ToList();
}
為什么不能用這個? 首先,創建一個數組:
string[] lines = File.ReadAllLines(openFileDialog1.FileName);
然后查找您需要刪除的行並用“”替換它:
lines[x].Replace(lines[x], "");
完畢!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.