2009-01-28 33 views
8

Tôi đã nhận thấy hai cách tiếp cận khác nhau để ghi dữ liệu ra một tệp XML (xử lý lỗi bị bỏ qua cho ngắn gọn).Sử dụng MemoryStream để ghi ra XML

Phương pháp đầu tiên có bạn xây dựng các tài liệu XML và sau đó chỉ cần lưu XML vào một tệp:

using (XmlWriter writer = XmlWriter.Create(fileName)) 
{ 
    writer.WriteStartDocument(true); 
    writer.WriteStartElement("parentelement"); 
    writer.WriteEndElement(); 
    writer.WriteEndDocument(); 
} 

Phương pháp thứ hai có bạn tạo một MemoryStream, và sau đó lưu MemoryStream vào một tệp:

XmlWriterSettings settings = new XmlWriterSettings(); 
settings.Indent = true; 
MemoryStream ms = new MemoryStream(); 
using (XmlWriter writer = XmlWriter.Create(ms, settings)) 
{ 
    writer.WriteStartDocument(true); 
    writer.WriteStartElement("parentelement"); 
    writer.WriteEndElement(); 
    writer.WriteEndDocument(); 
} 

using (FileStream fs = File.Open(fileName, FileMode.Create, FileAccess.Write)) 
{ 
    ms.WriteTo(fs); 
    ms.Dispose(); 
} 

Tôi đoán logic để sử dụng MemoryStream là để đảm bảo tệp XML có thể được tạo trước khi cố gắng lưu tệp. Liệu phương thức MemoryStream có cung cấp cho một sự kiện viết Atomic và/hoặc bảo vệ chống lại các vấn đề viết trong khi bạn đang thêm các mục vào tệp XML?

Bất cứ ai có thể giải thích nếu điều này thực sự cần thiết hay chỉ là một cách quá mức để thêm các dòng mã không cần thiết vào dự án của tôi?

Trả lời

15

Phiên bản MemoryStream là lãng phí trong dịp này. MemoryStream hữu ích nếu bạn muốn thực hiện công việc giống như Stream nhưng không muốn tệp thực sự. Nếu bạn viết một tệp, sau đó chỉ cần ghi vào tệp. Điều này tránh sự cần thiết phải đệm tất cả dữ liệu trong bộ nhớ.

0

Bạn không phải sử dụng MemoryStream để sử dụng XmlWriter. XmlWriter có thể ghi trực tiếp vào một tập tin; bạn có thể sử dụng quá tải khác của phương thức XmlWriter.Create, lấy tên tệp làm đối số hoặc thay vì ghi vào MemoryStream, bạn cũng có thể ghi vào XmlTextWriter hoặc FileStream.

Vì vậy, bạn 2 codesnippet có thể được viết như sau:

using(FileStream fs = ...) 
{ 
    XmlWriter writer = XmlWriter.Create (fs); 
} 

AFAIK, các XmlWriter sẽ không bảo vệ bạn khỏi tạo ra một Xml phi wellformed.

+0

Cảm ơn câu trả lời ... Cả hai phương pháp trong câu hỏi của tôi đều hoạt động, không nghi ngờ gì nữa ... Tôi chỉ muốn thử và làm rõ một số việc liệu tôi có nên sử dụng MemoryStream hay không. – Dscoduc

+0

XmlWriter sẽ bảo vệ bạn và thực thi tốt xml được hình thành ngoại trừ: 1) nếu bạn sử dụng WriteDocType hoặc WriteRaw 2) nếu bạn dừng sớm - tức là không đóng tất cả các phần tử vào phần tử gốc ở cuối – ShuggyCoUk

+0

Cảm ơn bạn đã làm rõ ... – Dscoduc

2

Đây là quá mức cần thiết và lãng phí.

Hai phương pháp chính được dựa trên

  1. Bạn không biết cấu trúc đầy đủ các tài liệu cho đến khi kết thúc.
  2. Khi bạn tạo 'các phần của tài liệu bạn biết rằng chúng là hình thức cuối cùng của phần này của tài liệu.

đầu tiên yêu cầu tạo mô hình bộ nhớ của tài liệu (mà DOM là mô hình được thiết kế). Một khi bạn đã hoàn thành với nó chỉ đơn giản là viết trực tiếp vào dòng tập tin là tốt.

Thứ hai cho phép bạn tiết kiệm bộ nhớ và độ phức tạp đáng kể và chỉ cần sử dụng XmlWriter có thể trỏ trực tiếp đến luồng cuối (trong trường hợp này là luồng tệp).

Tại không có giai đoạn là nó cần thiết để sử dụng một MemoryStream

1

Nếu bạn (vì một lý do) muốn đảm bảo succeedes XmlWriter (ví dụ:nếu không thì tập tin có thể được rút ngắn, nhưng trong hầu hết các trường hợp này sẽ do - như đã đề cập - thẻ không đóng), bạn có thể sử dụng một dòng tập tin tạm thời, fx một cái gì đó tương tự như sau:

public class TempFileStream : FileStream 
{ 

    public TempFileStream(Action<string> onClose) 
     : base(Path.GetTempFileName(), FileMode.OpenOrCreate, FileAccess.ReadWrite) 
    { 
     this.CloseDelegate = onClose; 
    } 

    protected Action<string> CloseDelegate 
    { 
     get; 
     set; 
    } 

    public override void Close() 
    { 
     base.Close(); 
     if (File.Exists(this.Name)) 
     { 
      this.CloseDelegate(this.Name); 
     } 
    } 

} 

Các sử dụng như:

XmlWriterSettings settings = new XmlWriterSettings(); 
settings.Indent = true; 

using (TempFileStream tfs = new TempFileStream(f => File.Move(f, filename)) 
using (XmlWriter writer = XmlWriter.Create(tfs, settings)) 
{ 
    writer.WriteStartDocument(true); 
    writer.WriteStartElement("parentelement"); 
    writer.WriteEndElement(); 
    writer.WriteEndDocument(); 
} 

này sẽ không tiêu tốn nhiều bộ nhớ (tất nhiên nó chỉ làm cho/ý nghĩa hơn khi XML kết quả là lớn)

+0

Tự hỏi tại sao câu trả lời này chưa có điểm số tốt. AFAIK nó trả lời câu hỏi với các lợi ích được yêu cầu (đảm bảo rằng "một tệp XML có thể được xây dựng", cung cấp một số loại nguyên tử) theo cách dễ sử dụng. –

+0

Wow, ngoại trừ nó không. Là di chuyển nguyên tử và ghi đè lên một chủ nghĩa Unix? Xem http://stackoverflow.com/a/10305475/1429390 để giải quyết sự cố. –

3

đúng là cách tiếp cận dòng bộ nhớ là lãng phí cho các hoạt động đơn giản nhưng nó rất hữu ích cho các trường hợp như lưu xml dưới dạng mã hóa d tệp, dưới dạng tệp nén, v.v.

1

Tôi nghĩ rằng việc sử dụng luồng bộ nhớ sẽ hữu ích nếu tạo tài liệu trong ứng dụng web hoặc dịch vụ web. Vị trí tệp có thể xung đột với một quy trình khác có thể đang chạy cùng một quá trình xử lý có thể gây ra kết quả không hợp lệ. Trong luồng bộ nhớ, việc xử lý phải được tách biệt.

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