2009-05-16 5 views
13

여러분,C#에서 파일에 (큰) XML을 쓰는 방법은 무엇입니까?

C# .NET 3.5에서 정말 큰 XML 문서 (최대 500MB까지)를 작성하는 좋은 방법은 무엇입니까? 주변에서 약간의 검색을했는데이 특정 질문을 해결하는 항목을 찾을 수 없습니다.

내 이전 스레드 (What is the best way to parse (big) XML in C# Code?)는 비슷한 크기의 XML 문서를 읽을 수 있습니다 ... 해결 된 문제로 "update.xml"문서에 업데이트 된 기능 (http://www.opengeospatial.org/standards/sfa)을 쓰는 방법에 대해 생각해 볼 필요가 있습니다.

내 아이디어 : 분명히 문서의 최대 크기를 고려하여 하나의 큰 DOM이 나왔습니다. XSD.EXE를 사용하여 바인딩 클래스를 생성합니다 ... XmlSerializer 클래스와 잘 작동하지만 DOM을 "밑"으로 작성한다고 생각합니다. 이 올바른지?. 나는 한 번에 메모리에 모든 기능 (최대 50,000 가지)을 보유 할 수 없습니다. 데이터베이스의 기능을 읽고 직렬화하고 파일에 써야합니다. 그래서 XmlSerializer를 사용하여 각각의 개별 기능에 대한 "도크 렛"을 파일에 작성해야한다고 생각합니다. 이것이 가능한지/실현 가능한지 전혀 알 수 없습니다.

당신은 어떻게 생각하십니까?

배경 : 나는 C 번호에 오래된 VB6 맵 인포의 "클라이언트 플러그인"을 포팅하고 있습니다. 이 프로그램 (다른 것들 중에서)과 함께 작동해야하는 기존 J2EE "업데이트 서비스"(실제로는 단지 웹 응용 프로그램)가 있습니다. 나는 서버를 바꿀 수 없다. absapositively 필요한 경우가 아니면; 특히 그 중 다른 클라이언트를 변경하는 것이 포함됩니다. 서버는 어떤 네임 스페이스도 구체화하지 않는 스키마를 가진 XML 문서를 받아들입니다. 즉, 기본 네임 스페이스 만 있고 그 안에 모든 것이 들어 있습니다.

내 경험 : 저는 C# 및 .NET 초보자입니다. 저는 Java, VB, C, C++ 등 다양한 언어로 약 10 년 동안 프로그래밍을 해왔습니다.

건배 모두. 키이스.

추신 : 저녁 식사 시간이므로 30 분 정도 비켜 볼게요.

답변

16

큰 xml을 작성하는 경우 XmlWriter (직접)은 귀하의 친구입니다.하지만 사용하기가 더 어렵습니다. 다른 옵션은 ... 당신이 XmlWriterSettings의 통제권을 장악하고 XML 마커를 사용하지 않도록하고, 네임 스페이스 선언을 제거 경우 아마도 행할 수있는, 그들을 DOM/객체 모델 접근 방법을 사용하고 결합하는 것입니다

using System; 
using System.Collections.Generic; 
using System.Xml; 
using System.Xml.Serialization;  
public class Foo { 
    [XmlAttribute] 
    public int Id { get; set; } 
    public string Bar { get; set; } 
} 
static class Program { 
    [STAThread] 
    static void Main() { 
     using (XmlWriter xw = XmlWriter.Create("out.xml")) { 
      xw.WriteStartElement("xml"); 
      XmlSerializer ser = new XmlSerializer(typeof(Foo)); 
      XmlSerializerNamespaces ns = new XmlSerializerNamespaces(); 
      ns.Add("",""); 
      foreach (Foo foo in FooGenerator()) { 
       ser.Serialize(xw, foo, ns); 
      } 
      xw.WriteEndElement(); 
     } 
    }  
    // streaming approach; only have the smallest amount of program 
    // data in memory at once - in this case, only a single `Foo` is 
    // ever in use at a time 
    static IEnumerable<Foo> FooGenerator() { 
     for (int i = 0; i < 40; i++) { 
      yield return new Foo { Id = i, Bar = "Foo " + i }; 
     } 
    } 
} 
+0

마크, Merci. (데이빗 슈미트 (David Schmitt)의 답변에 대한 제 의견대로) 나는 두 가지 방법으로 시도하고 성능 테스트를 수행 할 것입니다. 신중한 답변과 해당 예제 코드에 대해 감사드립니다. 굉장해. 고마워. ;-) 언젠가는 내가 갚을 수 있기를 희망합니다. 건배. 키이스. – corlettk

-1

단순히 XML을 작성하기 위해 TextWriter를 사용하지 않는 이유는 무엇입니까?

+0

XML이 텍스트가 아니기 때문에. –

+5

"...* 단순히 텍스트가 아닙니다. ";-) – Cerebrus

+0

XML Infoset (http://www.w3.org/TR/xml-infoset/)을 참조하십시오. 데이터와 표현을 혼동하지 마십시오. –

9

사용에게 XmlWriter :

[...]는 빠르고, 캐시되지 않은, 전진 전용 XML 데이터를 포함 생성 스트림 또는 파일을 의미합니다 제공하는 작가.

+0

대상에 스팟이 있습니다! +1 – Cerebrus

+0

OK 프로토 타입에 두 가지 방법 (시간을 절약하기 위해 키 요소 만 사용)을 시도합니다 .XmlWriter는 " 올바른 대답은 "하지만 내 초기 XmlSerializer 솔루션보다 더 많은 코드가 포함될 것이라고 추측하고 또한 th를 무효로합니다. 생성 된 바인딩 클래스를 사용하는 "유연성"이점 ... 수작업 작성 코드는 정확한 스키마에 대해 모두 알고 있어야하기 때문입니다. 시간 내 주셔서 감사합니다 ... 건배. 키이스. – corlettk

1

디스크에 쓰기 전에 압축하는 것을 고려 했습니까? XML을 사용하면 10 배 이상 압축 할 수 있습니다. 파일을 압축하고 전체 500Mb 버전을 읽는 것보다 압축 된 버전을 쓰는 데 더 적은 시간이 걸릴 것입니다.

+1

더 큰 문제는 메모리 내 DOM 표현이 보통 실제 XML의 x10보다 크다는 것입니다. 5Gb는 너무 커서 감지 할 수 없습니다. 그리고 기존의 API/압축되지 않은 파일에 대한 기대가 있다면 다시는 도움이되지 않습니다. –

+0

좋은 생각입니다. 고맙습니다. 나는 디스크를 치기 전에 그것을 압축 할 수도있다. 그것을 다시 읽고 HttpWebRequest로 보내는 시간 (및 메모리)을 절약합니다. 이 XML에 대한 우리의 경험은 압축 된 크기의 약 4 분의 1로 압축됩니다. 저장 (3/4) * 500 = 375MB의 RAM. – corlettk

관련 문제