2011-09-22 1 views
1

레거시 앱이 파일을 처리 할 수 ​​있도록 XML 파일 (~ 400MB)을 2 개로 분할해야합니다. 현재는 파일이 약 300MB를 초과 할 때 예외가 발생합니다.C# 콘솔 앱을 사용하여 두 개의 큰 XML 파일 분할하기

처리를 수행하는 앱을 변경할 수 없기 때문에 콘솔 앱을 작성하여 파일을 두 개로 분할 할 수 있다고 생각했습니다. 이 일을하는 가장 좋은 방법은 무엇입니까? 자동화해야 텍스트 편집기를 사용할 수 없으며 C#을 사용하고 있습니다.

나는 고려 사항은 가정 :

  • 태그를 닫는
  • (안 '객체'의 중간에) 분할 좋은 장소를 찾는 분할
  • 후 새 파일에 헤더를 작성 첫 번째 파일에 제대로 파일을 두 번째 파일에 올바르게 태그를여십시오.

어떤 제안이 있습니까?

답변

2

"최고"방법은 XmlReaderXmlWriter 기반으로 할 가능성이 높습니다. 이러한 "스트리밍"API를 사용하면 전체 XML 객체 모델을 메모리 (및 DOM - XmlDocument - 텍스트 데이터보다 훨씬 더 많은 메모리가 필요할 수 있음)에로드 할 필요가 없습니다.

이러한 API를 사용하는 것은 문서를로드하는 것보다 어렵습니다. 구현시 컨텍스트 (예 : 현재 노드 및 상위 목록)를 추적해야하지만,이 경우 복잡하지는 않습니다 (요소를 열 수있을 정도로). 각 출력 문서를 열 때의 현재 상태).

+0

그래, 덕분에 스트림이 좋은 옵션이 될거라고 생각 했어. 내가 문서에서 있었던 부분의 오버 헤드를 가볍게 두드리며, 다른 옵션이 있는지 확인하는 것뿐입니다. – finoutlook

+0

XmlTextWriter가 정상적으로 작동되었습니다. – finoutlook

0

순수한 C# 인 경우 64 비트 프로세스로 실행하면 아무런 노력 없이도 문제가 해결 될 수 있습니다 (64 비트 Windows가 있다고 가정).

+0

문제를 일으키는 그의 레거시 응용 프로그램 –

+0

레거시 응용 프로그램을 C#으로 작성할 수 없습니까? –

+0

네가 맞다. 레거시 앱이 C#이지만, 나는 그걸 전혀 바꿀 수 없으며, 32 비트도 바꿀 수 없다. – finoutlook

2

파일의 전체 복사본을 만든 다음 각 파일에서 요소를 삭제하는 것이 좋습니다. 삭제가 발생할 수있는 레벨을 결정해야합니다.

FileB에서 삭제해야하는 요소의 수를 식별하기 위해 FileA에서 삭제 된 요소의 수로부터 상당히 간단해야합니다.

상황에 따라 적절합니까?

나는 다음과 같이 내 생각을 설명했다. 그것은 테스트되지 않았지만 그룹의 의견을 존중합니다. 당신이 원한다면 나를 downvote하지만 나는 건설적인 비판을 선호합니다.

using System.Xml; 
using System.Xml.Schema; 

namespace ConsoleApplication1 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      SplitXML(args[0], args[1]); 
     } 

     private static void SplitXML(string fileNameA, string fileNameB) 
     { 
      int deleteCount; 
      XmlNodeList childNodes; 
      XmlReader reader; 
      XmlTextWriter writer; 
      XmlDocument doc; 

      // ------------- Process FileA 
      reader = XmlReader.Create(fileNameA); 
      doc = new XmlDocument(); 
      doc.Load(reader); 

      childNodes = doc.DocumentElement.ChildNodes; 
      deleteCount = childNodes.Count/2; 

      for (int i = 0; i < deleteCount; i++) 
      { 
       doc.DocumentElement.RemoveChild(childNodes.Item(0)); 
      } 
      writer = new XmlTextWriter("FileC", null); 
      doc.Save(writer); 

      // ------------- Process FileB 
      reader = XmlReader.Create(fileNameB); 
      doc = new XmlDocument(); 
      doc.Load(reader); 

      childNodes = doc.DocumentElement.ChildNodes; 

      for (int i = deleteCount + 1; i < childNodes.Count; i++) 
      { 
       doc.DocumentElement.RemoveChild(childNodes.Item(deleteCount +1)); 
      } 
      writer = new XmlTextWriter("FileD", null); 
      doc.Save(writer); 

     } 
    } 
} 
+0

이것은 구현이 쉬운 것 같습니다. 잘린 태그를 열고 닫는 번거 로움을 덜어줍니다. – xbonez

+0

포스터/그룹의 코드 샘플 게시 권한을 가질 수 있습니까? 내가 묻는 이유는 내가 C# 전문가가 아니기 때문에 가혹한 비판을 정말로 가치있게 여기기 때문이다. –

+0

코드 샘플을 보내 주셔서 감사합니다. 내가 파일의 복사본을 만들지 않고 XmlTextWriter를 사용하여 끝났다. 흥미로운 제안 이었지만 파일이 정말 거대하면 복사가 처리를 시작하기 전에 많은 공간을 사용할 수 있습니다. – finoutlook