2009-05-08 20 views
36

Bạn sẽ chuẩn hóa tất cả các chuỗi dòng mới trong một chuỗi thành một loại như thế nào?Cách nhanh chóng để buộc CRLF trong C#/.NET là gì?

Tôi đang tìm cách biến chúng thành CRLF cho mục đích gửi email (tài liệu MIME). Lý tưởng nhất điều này sẽ được gói trong một phương pháp tĩnh, thực hiện rất nhanh chóng, và không sử dụng các biểu thức thông thường (vì các phương sai của ngắt dòng, trả về vận chuyển, vv bị giới hạn). Có lẽ có một phương pháp BCL mà tôi đã bỏ qua?

GIẢI THÍCH: Sau khi suy nghĩ thêm một chút, tôi nghĩ đó là một giả định an toàn để nói rằng CR là một trong hai độc lập hoặc một phần của chuỗi CRLF. Đó là, nếu bạn thấy CRLF thì bạn biết tất cả CR có thể được gỡ bỏ. Nếu không, sẽ rất khó để biết có bao nhiêu dòng sẽ xuất phát từ một thứ như "\ r \ n \ n \ r".

Trả lời

52
input.Replace("\r\n", "\n").Replace("\r", "\n").Replace("\n", "\r\n") 

Điều này sẽ có tác dụng nếu đầu vào chỉ chứa một loại ngắt dòng - hoặc CR hoặc LF, hoặc CR + LF.

+0

Cũng hoạt động để hiển thị văn bản không xác định trên trang HTML bằng cách sử dụng thay thế cuối cùng để chèn thẻ BR. Server.HtmlEncode (đầu vào) .Đặt lại ("\ r \ n", "\ n") Thay thế ("\ r", "\ n") Thay thế ("\ n", "
"); –

+0

Đường nối này để khắc phục sự cố với mẫu T4.Tôi tiếp tục nhận được lợi nhuận điên rồ trong sản lượng tạo ra của tôi. – DaImTo

4
string nonNormalized = "\r\n\n\r"; 

string normalized = nonNormalized.Replace("\r", "\n").Replace("\n", "\r\n"); 
+1

Ví dụ này tạo ra bốn ngắt dòng, trong khi chuỗi không chuẩn hóa chứa hai. –

+0

Đúng, nó sẽ trả lời một câu hỏi hay về thời điểm một chuỗi được sử dụng và khi nào nó chỉ bị loại bỏ (bỏ qua). –

28

Tùy thuộc vào chính xác yêu cầu là gì. Đặc biệt, bạn muốn tự xử lý "\ r" như thế nào? Điều đó có nên được tính là ngắt dòng hay không? Ví dụ, "a \ n \ rb" nên được xử lý như thế nào? Đó có phải là một ngắt dòng rất lẻ, một "\ n" ngắt và sau đó là một "r" rogue, hoặc hai dòng riêng biệt? Nếu "\ r" và "\ n" cả hai có thể là dấu ngắt dòng, thì tại sao "\ r \ n" không được coi là hai dấu ngắt dòng?

Dưới đây là một số mã mà tôi nghi ngờ là hợp lý hiệu quả.

using System; 
using System.Text; 

class LineBreaks 
{  
    static void Main() 
    { 
     Test("a\nb"); 
     Test("a\nb\r\nc"); 
     Test("a\r\nb\r\nc"); 
     Test("a\rb\nc"); 
     Test("a\r"); 
     Test("a\n"); 
     Test("a\r\n"); 
    } 

    static void Test(string input) 
    { 
     string normalized = NormalizeLineBreaks(input); 
     string debug = normalized.Replace("\r", "\\r") 
           .Replace("\n", "\\n"); 
     Console.WriteLine(debug); 
    } 

    static string NormalizeLineBreaks(string input) 
    { 
     // Allow 10% as a rough guess of how much the string may grow. 
     // If we're wrong we'll either waste space or have extra copies - 
     // it will still work 
     StringBuilder builder = new StringBuilder((int) (input.Length * 1.1)); 

     bool lastWasCR = false; 

     foreach (char c in input) 
     { 
      if (lastWasCR) 
      { 
       lastWasCR = false; 
       if (c == '\n') 
       { 
        continue; // Already written \r\n 
       } 
      } 
      switch (c) 
      { 
       case '\r': 
        builder.Append("\r\n"); 
        lastWasCR = true; 
        break; 
       case '\n': 
        builder.Append("\r\n"); 
        break; 
       default: 
        builder.Append(c); 
        break; 
      } 
     } 
     return builder.ToString(); 
    } 
} 
+0

Rất mát mẻ; điều này chắc chắn sẽ hữu ích trên đầu vào tùy ý hơn! Đối với trường hợp của tôi, tôi đã chọn để đi với một giả định (thực hiện một chỉnh sửa), nhưng tôi đã bỏ phiếu này lên bất kể. –

+0

Phải. Nếu hiệu suất thực sự quan trọng, bạn có thể muốn đánh giá giải pháp này so với giải pháp được chấp nhận - nhưng chỉ khi bạn đã thực sự xác định rằng nó có ý nghĩa thông qua một hồ sơ! Tôi sẽ * hy vọng * điều này nhanh hơn, vì nó chỉ cần thực hiện một lượt đi qua dữ liệu. –

+0

Điều gì sẽ xảy ra khi sử dụng RegExpr? hiệu suất không tốt? http://stackoverflow.com/questions/140926/normalize-newlines-in-c-sharp – Kiquenet

3

biến thể đơn giản:

Regex.Replace(input, @"\r\n|\r|\n", "\r\n") 

Đối với hiệu suất tốt hơn:

static Regex newline_pattern = new Regex(@"\r\n|\r|\n", RegexOptions.Compiled); 
[...] 
    newline_pattern.Replace(input, "\r\n"); 
0

Đây là một cách nhanh chóng để làm điều đó, tôi có ý nghĩa.

Nó không sử dụng chức năng regex đắt tiền. Nó cũng không sử dụng nhiều chức năng thay thế mà mỗi cá nhân đã lặp qua dữ liệu với một số kiểm tra, phân bổ và v.v.

Vì vậy, tìm kiếm được thực hiện trực tiếp trong 1 cho vòng lặp. Đối với số lần công suất của mảng kết quả phải được tăng lên, một vòng lặp cũng được sử dụng trong hàm Array.Copy. Đó là tất cả các vòng lặp. Trong một số trường hợp, kích thước trang lớn hơn có thể hiệu quả hơn.

public static string NormalizeNewLine(this string val) { 
    if (string.IsNullOrWhiteSpace(val)) 
     return val; 

    const int page = 6; 
    int a = page; 
    int j = 0; 
    int len = val.Length; 
    char[] res = new char[len]; 
    for (int i = 0; i < len; i++) { 
     char ch = val[i]; 
     if (ch == '\r') { 
      int ni = i + 1; 
      if (ni < len && val[ni] == '\n') { 
       res[j++] = '\r'; 
       res[j++] = '\n'; 
       i++; 
      } else { 
       if (a == page) { //ensure capacity 
        char[] nres = new char[res.Length + page]; 
        Array.Copy(res, 0, nres, 0, res.Length); 
        res = nres; 
        a = 0; 
       } 
       res[j++] = '\r'; 
       res[j++] = '\n'; 
       a++; 
      } 
     } 
     else if (ch == '\n') { 
      int ni = i + 1; 
      if (ni < len && val[ni] == '\r') { 
       res[j++] = '\r'; 
       res[j++] = '\n'; 
       i++; 
      } else { 
       if (a == page) { //ensure capacity 
        char[] nres = new char[res.Length + page]; 
        Array.Copy(res, 0, nres, 0, res.Length); 
        res = nres; 
        a = 0; 
       } 
       res[j++] = '\r'; 
       res[j++] = '\n'; 
       a++; 
      } 
     } else { 
      res[j++] = ch; 
     } 
    } 
    return new string(res, 0, j); 
} 

Hiện tại, '\ n \ r' không thực sự được sử dụng trên nền tảng cơ bản. nhưng: Ai sẽ sử dụng hai loại ngắt dòng liên tiếp để chỉ ra 2 dấu ngắt dòng? Nếu bạn muốn biết điều đó, bạn cần phải xem trước khi biết \ n và \ r đều được sử dụng riêng trong cùng một tài liệu hay không.

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