2010-08-03 22 views
26

Gần đây tôi đã đọc rằng trong StringWriterStringReader được sử dụng để viết và đọc từ StringBuilder.StringBuilder Vs StringWriter/StringReader

Khi tôi sử dụng StringBuilder Đối tượng, đây có vẻ là một lớp học tự cung tự cấp.

Chúng tôi có mọi cách đọc và viết các StringBuilder, sử dụng StringBuilder.Append(), Insert(), Replace(), Remove() vv ...

  1. khả năng sử dụng StringWriterStringReader, mà không thể được thực hiện bằng StringBuilder là gì chinh no?
  2. Cách sử dụng thực tế của chúng là gì?
  3. Điều gì có thể là lý do có thể khiến họ không tham gia Stream làm đầu vào (Vì bất kỳ nhà văn và người đọc nào khác đang lấy luồng làm tham số Constructor hoạt động) nhưng StringBuilder?
+1

có thể trùng lặp của [StringWriter hoặc StringBuilder] (http://stackoverflow.com/questions/602279/stringwriter-or-stringbuilder) –

Trả lời

31

Việc sử dụng StringWriter và StringReader có thể thực hiện được điều gì không thể được thực hiện bởi chính StringBuilder?

StringReaderStringWriter xuất phát từ TextReaderTextWriter tương ứng. Vì vậy, những gì họ có thể hoạt động như một ví dụ TextReader hoặc TextWriter, trong đó string hoặc StringBuilder không thể vì chúng không lấy được một trong các loại đó.

Cách sử dụng thực tế của chúng là gì?

Chúng cho phép bạn gọi API đang mong đợi một TextReader hoặc TextWriter, khi những gì bạn phải/muốn là một string hoặc StringBuilder.

Điều gì có thể là nguyên nhân có thể khiến họ không tham gia Luồng làm đầu vào (Vì bất kỳ nhà văn và người đọc nào đang lấy luồng như tham số Constructor hoạt động) nhưng StringBuilder?

Vì chúng không hoạt động trên luồng; chúng hoạt động trên string s hoặc StringBuilder s. Chúng chỉ là các lớp trình bao bọc đơn giản, thích ứng với các loại API này với một giao diện khác. Xem: adapter pattern.

1

Tôi không chắc ai đã nói với bạn rằng mục đích của họ là để sử dụng với StringBuilder, nhưng điều đó hoàn toàn không chính xác. Như bạn đã lưu ý, StringBuilder có thể được đọc và ghi vào mà không cần sử dụng lớp khác. Các lớp StringWriter và StringReader mở rộng các lớp cơ sở TextReader và TextWriter .Net Framework và cung cấp các tính năng giống như luồng để làm việc với dữ liệu văn bản. Ví dụ, nếu bạn cần làm việc với một số lớp XmlDocument, một số phương thức cho phép bạn tải dữ liệu Xml qua TextReader, vì vậy nếu bạn có văn bản Xml dưới dạng biến chuỗi, bạn có thể tải nó vào một StringReader và sau đó cung cấp nó cho XmlDocument.

+0

Hi, cảm ơn bạn cho bạn câu trả lời. Tôi đồng ý với điểm xuất phát từ TextWriter/TextReader. Tôi đã lấy StringWriter ví dụ và tìm thấy cả hai khởi tạo sau đây không hoạt động. FileStream fs = new FileStream (@ "C: \ Users \ Saravanan \ Documents \ something.bin", FileMode.OpenOrCreate); StringWriter sw1 = File.CreateText (@ "C: \ Users \ Saravanan \ Documents \ something.bin"); StringWriter sw2 = new StringWriter (fs); Chỉ mất Stringbuilder để ghi. – SaravananArumugam

+1

@Saravanandss - Nếu bạn đang cố gắng để đọc/ghi từ/đến suối, sau đó sử dụng 'StreamReader' và' StreamWriter' ... đó là những gì họ đang có cho. 'StringReader' và' StringWriter' không được thiết kế để làm việc với các tệp; chúng được thiết kế để làm việc với các chuỗi. Tại sao bạn đang cố gắng sử dụng chúng? –

5

Những người khác đã nói rồi, nhưng đó là vì chúng lấy được từ TextReader/TextWriter và có thể được sử dụng thay cho chúng.Đối với một điều nó chỉ có ý nghĩa hơn để sử dụng cùng một phương pháp để xuất ra dòng mà bạn sử dụng cho một tập tin nếu bạn chỉ muốn nội dung như là một chuỗi. Nếu bạn muốn đầu ra sẽ kéo dài nhiều dòng trong bộ nhớ, tại sao phải nhớ đặt "\ r \ n" ở cuối mỗi dòng bằng một StringBuilder? Điều gì sẽ xảy ra nếu bạn muốn mã chạy trên hoặc định dạng dữ liệu cho hệ thống chỉ sử dụng "\ n" cho ngắt dòng?

StringBuilder sb = new StringBuilder(); 
// will be invalid on systems that only use \n 
sb.AppendFormat("{0:yyyy-MM-dd HH:mm:ss} - Start\r\n", DateTime.Now); 
// still have to add an extra parameter 
sb.AppendFormat("The current time is {0:yyyy-MM-dd HH:mm:ss}{1}", DateTime.Now, 
    Environment.NewLine); 

StringWriter sw = new StringWriter(); 
// Don't have to worry about it, method name tells you there's a line break 
sw.WriteLine("{0:yyyy-MM-dd HH:mm:ss} - Start", DateTime.Now); 
// no extra parameters 
sw.WriteLine("The current time is {0:yyyy-MM-dd HH:mm:ss}", DateTime.Now); 

Giả sử bạn muốn xử lý một dòng tập tin bằng cách dòng, bạn có lẽ sẽ sử dụng một StreamReader thay vì tải toàn bộ tập tin vào một StringBuilder và tách nó bằng ký tự xuống dòng vào một mảng, phải không? Với StringReader bạn có thể sử dụng chính xác cùng một phương thức (miễn là nó có một TextReader chung) bằng cách tạo StringReader từ một chuỗi từ một TextBox hoặc biểu mẫu web.

LINQ2Sql DataContexts có thuộc tính Nhật ký bạn có thể đặt thành TextWriter để có kết quả truy vấn của bạn trước khi chúng được thực hiện để xem chính xác những gì đang được chạy. Bạn có thể đặt điều này thành một TextWriter gắn liền với một tệp, nhưng bạn có thể đính kèm một StringWriter vào nó và xuất nội dung ở dưới cùng của trang web của bạn khi thử nghiệm ...

1

Bạn có thể sử dụng StringReader để đọc tất cả các số nguyên từ một chuỗi.

private static void Main() 
{ 
    var str = @" 
       13 
       13 
       0 6 
       0 5 
       0 1 
       0 2 
       5 3 
       6 4 
       5 4 
       3 4 
       7 8 
       9 10 
       11 12 
       9 11 
       9 12"; 


    using (StandardInput input = new StandardInput(new StringReader(str))) 
    { 
     List<int> integers = new List<int>(); 
     int n; 
     while ((n = input.ReadInt32()) != -1) 
     { 
      integers.Add(n); 
     } 
    } 
} 

StandardInput Class:

class StandardInput : IDisposable 
{ 
    private readonly TextReader reader; 

    public StandardInput(TextReader reader) 
    { 
     this.reader = reader; 
    } 

    public int ReadInt32() 
    { 
     while (!char.IsDigit((char)reader.Peek()) && reader.Peek() != -1) 
     { 
      reader.Read(); 
     } 
     var builder = new StringBuilder(); 
     while (char.IsDigit((char) reader.Peek())) 
      builder.Append((char) reader.Read()); 

     return builder.Length == 0 ? -1 : int.Parse(builder.ToString()); 
    } 

    public double ReadDouble() 
    { 
     while (!char.IsDigit((char)reader.Peek()) && reader.Peek() != '.' 
                && reader.Peek() != -1) 
     { 
      reader.Read(); 
     } 
     var builder = new StringBuilder(); 
     if (reader.Peek() == '.') 
      builder.Append((char) reader.Read()); 
     while (char.IsDigit((char)reader.Peek())) 
      builder.Append((char)reader.Read()); 
     if (reader.Peek() == '.' && !builder.ToString().Contains(".")) 
     { 
      builder.Append((char)reader.Read()); 
      while (char.IsDigit((char)reader.Peek())) 
       builder.Append((char)reader.Read()); 
     } 
     return builder.Length == 0 ? -1 : double.Parse(builder.ToString()); 
    } 

    public void Dispose() 
    { 
     reader.Dispose(); 
    } 
} 
Các vấn đề liên quan