[英]Edit a specific Line of a Text File in C#
我有兩個文本文件,Source.txt 和 Target.txt。 源永遠不會被修改並包含 N 行文本。 所以,我想刪除 Target.txt 中的特定文本行,並用 Source.txt 中的特定文本行替換,我知道我需要多少行,實際上是第 2 行,兩個文件。
我有這樣的東西:
string line = string.Empty;
int line_number = 1;
int line_to_edit = 2;
using StreamReader reader = new StreamReader(@"C:\target.xml");
using StreamWriter writer = new StreamWriter(@"C:\target.xml");
while ((line = reader.ReadLine()) != null)
{
if (line_number == line_to_edit)
writer.WriteLine(line);
line_number++;
}
但是當我打開 Writer 時,目標文件被擦除,它寫入行,但是,當打開時,目標文件只包含復制的行,其余的都丟失了。
我能做什么?
最簡單的方法是:
static void lineChanger(string newText, string fileName, int line_to_edit)
{
string[] arrLine = File.ReadAllLines(fileName);
arrLine[line_to_edit - 1] = newText;
File.WriteAllLines(fileName, arrLine);
}
用法 :
lineChanger("new content for this line" , "sample.text" , 34);
您不能在不重寫整個文件的情況下重寫一行(除非這些行恰好具有相同的長度)。 如果您的文件很小,那么將整個目標文件讀入內存然后再次將其寫出可能是有意義的。 你可以這樣做:
using System;
using System.IO;
class Program
{
static void Main(string[] args)
{
int line_to_edit = 2; // Warning: 1-based indexing!
string sourceFile = "source.txt";
string destinationFile = "target.txt";
// Read the appropriate line from the file.
string lineToWrite = null;
using (StreamReader reader = new StreamReader(sourceFile))
{
for (int i = 1; i <= line_to_edit; ++i)
lineToWrite = reader.ReadLine();
}
if (lineToWrite == null)
throw new InvalidDataException("Line does not exist in " + sourceFile);
// Read the old file.
string[] lines = File.ReadAllLines(destinationFile);
// Write the new file over the old file.
using (StreamWriter writer = new StreamWriter(destinationFile))
{
for (int currentLine = 1; currentLine <= lines.Length; ++currentLine)
{
if (currentLine == line_to_edit)
{
writer.WriteLine(lineToWrite);
}
else
{
writer.WriteLine(lines[currentLine - 1]);
}
}
}
}
}
如果您的文件很大,最好創建一個新文件,以便您可以在寫入另一個文件時從一個文件讀取流。 這意味着您不需要一次將整個文件保存在內存中。 你可以這樣做:
using System;
using System.IO;
class Program
{
static void Main(string[] args)
{
int line_to_edit = 2;
string sourceFile = "source.txt";
string destinationFile = "target.txt";
string tempFile = "target2.txt";
// Read the appropriate line from the file.
string lineToWrite = null;
using (StreamReader reader = new StreamReader(sourceFile))
{
for (int i = 1; i <= line_to_edit; ++i)
lineToWrite = reader.ReadLine();
}
if (lineToWrite == null)
throw new InvalidDataException("Line does not exist in " + sourceFile);
// Read from the target file and write to a new file.
int line_number = 1;
string line = null;
using (StreamReader reader = new StreamReader(destinationFile))
using (StreamWriter writer = new StreamWriter(tempFile))
{
while ((line = reader.ReadLine()) != null)
{
if (line_number == line_to_edit)
{
writer.WriteLine(lineToWrite);
}
else
{
writer.WriteLine(line);
}
line_number++;
}
}
// TODO: Delete the old file and replace it with the new file here.
}
}
一旦您確定寫入操作成功(沒有拋出異常並且寫入器已關閉),您就可以隨后移動文件。
請注意,在這兩種情況下,您對行號使用基於 1 的索引都有些令人困惑。 在您的代碼中使用基於 0 的索引可能更有意義。 如果您願意,您可以在程序的用戶界面中使用基於 1 的索引,但在進一步發送之前將其轉換為 0 索引。
此外,用新文件直接覆蓋舊文件的缺點是,如果中途失敗,那么您可能會永久丟失未寫入的任何數據。 通過首先寫入第三個文件,您只有在確定您有另一個(更正)副本后才刪除原始數據,因此如果計算機中途崩潰,您可以恢復數據。
最后一句話:我注意到你的文件有一個 xml 擴展名。 您可能需要考慮使用 XML 解析器來修改文件的內容而不是替換特定行是否更有意義。
當您創建StreamWriter
它總是從頭開始創建一個文件,您必須創建第三個文件並從目標復制並替換您需要的內容,然后替換舊的。 但正如我所看到的,您需要的是 XML 操作,您可能希望使用XmlDocument
並使用 Xpath 修改您的文件。
我想下面應該工作(而不是你的例子中的作者部分)。 不幸的是,我沒有構建環境,所以它來自記憶,但我希望它有所幫助
using (var fs = File.Open(filePath, FileMode.Open, FileAccess.ReadWrite)))
{
var destinationReader = StreamReader(fs);
var writer = StreamWriter(fs);
while ((line = reader.ReadLine()) != null)
{
if (line_number == line_to_edit)
{
writer.WriteLine(lineToWrite);
}
else
{
destinationReader .ReadLine();
}
line_number++;
}
}
您需要打開輸出文件以進行寫訪問,而不是使用新的 StreamReader,它總是會覆蓋輸出文件。
StreamWriter stm = null;
fi = new FileInfo(@"C:\target.xml");
if (fi.Exists)
stm = fi.OpenWrite();
當然,您仍然必須在輸出文件中尋找正確的行,這將很難,因為您無法從中讀取,因此除非您已經知道要尋找的字節偏移量,否則您可能真的想要讀/寫使用權。
FileStream stm = fi.Open(FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None);
使用此流,您可以閱讀直到到達要進行更改的點,然后再寫入。 請記住,您正在寫入字節,而不是行,因此要覆蓋一行,您需要寫入與要更改的行相同數量的字符。
好的,解決方案工作正常。 但是當相同的文本出現在多個地方時,我需要更改單行文本。 為此,需要定義一個trackText
以在該文本之后開始查找,最后將oldText
更改為newText
。
private int FindLineNumber(string fileName, string trackText, string oldText, string newText)
{
int lineNumber = 0;
string[] textLine = System.IO.File.ReadAllLines(fileName);
for (int i = 0; i< textLine.Length;i++)
{
if (textLine[i].Contains(trackText)) //start finding matching text after.
traced = true;
if (traced)
if (textLine[i].Contains(oldText)) // Match text
{
textLine[i] = newText; // replace text with new one.
traced = false;
System.IO.File.WriteAllLines(fileName, textLine);
lineNumber = i;
break; //go out from loop
}
}
return lineNumber
}
希望對其他人有所幫助。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.