2009-03-21 66 views
31

Tôi gặp sự cố: làm cách nào để xóa một dòng khỏi tệp văn bản trong C#?Làm thế nào để xóa một dòng từ một tập tin văn bản trong C#?

+0

Anh ấy/cô ấy có nghĩa là làm thế nào để xóa nó theo lập trình tôi đoán. – splattne

+35

@ John Saunders: Thật khó hiểu OP có muốn xóa một dòng từ một tệp văn bản bằng C# không? Làm thế nào là không cụ thể? Chúng ta hãy chào đón hơn một chút với những người mới. –

Trả lời

24

Đọc tệp, xóa dòng trong bộ nhớ và đưa nội dung trở lại tệp (ghi đè). Nếu tệp lớn, bạn có thể muốn đọc dòng đó cho dòng và tạo tệp tạm thời, sau đó thay thế tệp gốc.

17

Tôi đồng ý với John Saunders, đây không thực sự là C# cụ thể. Tuy nhiên, để trả lời câu hỏi của bạn: về cơ bản bạn cần viết lại tệp. Có hai cách bạn có thể làm điều này.

  • đã đọc toàn bộ tập tin vào bộ nhớ (ví dụ với File.ReadAllLines)
  • Tháo dòng vi phạm (trong trường hợp này có lẽ đơn giản nhất để chuyển đổi mảng chuỗi thành một List<string> sau đó loại bỏ các dòng)
  • Viết tất cả các phần còn lại của dòng trở lại (ví dụ như với File.WriteAllLines) - có khả năng chuyển đổi các List<string> thành một mảng chuỗi lại sử dụng ToArray

Điều đó có nghĩa bạn phải biết rằng bạn đã có đủ bộ nhớ Tuy nhiên. Một thay thế:

  • mở cả các tập tin đầu vào và đầu ra một tập tin mới (như là một TextReader/TextWriter, ví dụ như với File.OpenTextFile.CreateText)
  • Đọc một dòng (TextReader.ReadLine) - nếu bạn không muốn xóa nó, hãy viết nó vào tập tin đầu ra (TextWriter.WriteLine)
  • Khi bạn đã đọc tất cả các dòng, gần cả người đọc và người viết (nếu bạn sử dụng using báo cáo cho cả hai, điều này sẽ xảy ra tự động)
  • Nếu bạn muốn để thay thế đầu vào bằng đầu ra, xóa e tệp đầu vào và sau đó di chuyển tệp đầu ra vào vị trí.
+0

Tôi đang ở trong tình huống tương tự mà tôi đã loại bỏ tiêu đề của một tập tin và nối nó vào một tập tin khác. Trên Windows, nếu tôi sử dụng các hàm DOS thông qua C#, bạn có nghĩ rằng nó sẽ là hiệu suất đạt được không? Đây là lệnh .. > MORE +1 "sourcefilepath"> "targetFilePath" –

+0

@ImranAmjad: Tôi không biết, nhưng có vẻ như sẽ không khó để kiểm tra. Đây có phải là một phần đặc biệt quan trọng về hiệu suất của quy trình làm việc của bạn không? –

+0

Có, kích thước tệp có thể lớn hơn một nửa GB và tôi phải thực hiện thường xuyên. Làm điều đó từ các lệnh DOS có tất cả các gánh nặng và tôi chỉ chắc chắn rằng nó nhanh hơn khi lệnh dos bỏ qua tất cả các lớp hệ điều hành. Tôi không chắc chắn về phần lớn nội bộ. Nó cũng tiết kiệm rất nhiều dòng mã cũng như khả năng đọc mã được thỏa hiệp với một số ppl. –

63

Đối rất file lớn, tôi muốn làm một cái gì đó như thế này

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

Cập nhật tôi ban đầu được viết lại này trong năm 2009 và tôi nghĩ rằng nó có thể là thú vị với một bản cập nhật. Hôm nay bạn có thể thực hiện ở trên sử dụng LINQ and deferred execution

var tempFile = Path.GetTempFileName(); 
var linesToKeep = File.ReadLines(fileName).Where(l => l != "removeme"); 

File.WriteAllLines(tempFile, linesToKeep); 

File.Delete(fileName); 
File.Move(tempFile, fileName); 

Đoạn mã trên là gần như chính xác giống như ví dụ đầu tiên, đọc từng dòng và trong khi vẫn giữ một lượng tối thiểu của các dữ liệu trong bộ nhớ.

Tuyên bố từ chối trách nhiệm có thể theo thứ tự. Vì chúng ta đang nói về các tập tin văn bản ở đây bạn rất hiếm khi phải sử dụng đĩa làm phương tiện lưu trữ trung gian. Nếu bạn không xử lý các tệp nhật ký rất lớn, sẽ không có vấn đề gì khi đọc nội dung vào bộ nhớ và tránh phải xử lý tệp tạm thời.

File.WriteAllLines(fileName, 
    File.ReadLines(fileName).Where(l => l != "removeme").ToList()); 

Lưu ý rằng .ToList là rất quan trọng ở đây để thực thi ngay lập tức. Cũng lưu ý rằng tất cả các ví dụ giả sử các tập tin văn bản được mã hóa UTF-8.

2

tôi muốn rất đơn giản:

  • Mở tệp để đọc/viết
  • Đọc/tìm kiếm thông qua nó cho đến khi bắt đầu dòng bạn muốn xóa
  • Đặt con trỏ ghi vào con trỏ đọc hiện tại
  • Đọc qua đến cuối dòng chúng tôi đang xóa và bỏ qua các dấu phân tách dòng mới (đếm số ký tự khi chúng ta đi, chúng ta sẽ gọi nó là đường viền)
  • Đọc từng byte và ghi từng byte vào file
  • Khi hoàn thành cắt ngắn tập tin thành (orig_length - nline).
5

tôi mở rộng những gì Markus Olsson gợi ý, và đã đưa ra lớp này có thêm nhiều chuỗi tìm kiếm và một vài sự kiện:

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

Cách sử dụng:

 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"); 
5

Để loại bỏ mục từ tệp văn bản, trước tiên di chuyển tất cả văn bản vào danh sách và xóa bất kỳ mục nào bạn muốn. Sau đó, viết văn bản được lưu trữ trong danh sách vào tệp văn bản

List<string> quotelist=File.ReadAllLines(filename).ToList(); 
      string firstItem= quotelist[0]; 
      quotelist.RemoveAt(0); 
      File.WriteAllLines(filename, quotelist.ToArray()); 
      return firstItem; 
+1

Làm thế nào về "nửa kia" (được, 0,05 phần trăm khác) không có ReadAllLines() hoặc WriteAllLines() trong phiên bản .NET của họ. –

2

Xin chào các bạn, tôi đã viết một phương pháp để xóa các dòng khỏi tệp. Chương trình này sử dụng using System.IO

Xem mã của tôi:

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

Tại sao không thể sử dụng điều này? Đầu tiên, tạo một mảng:

string[] lines = File.ReadAllLines(openFileDialog1.FileName); 

Sau đó nhìn lên dòng bạn cần phải xoá bỏ và thay thế bằng "":

lines[x].Replace(lines[x], ""); 

Xong!

+1

Điều này không * loại bỏ * dòng từ tập tin, tất cả nó làm là làm cho dòng 'x' trống rỗng. Vì vậy, nếu bạn đã làm điều này rất nhiều, bạn sẽ chỉ kết thúc với một loạt các trả về sản phẩm nào trong tệp, điều này có thể làm hỏng các chỉ mục. – carefulnow1

Các vấn đề liên quan