2012-02-18 5 views
2

GPS 좌표 (GPX)의 모음 인 Java를 사용하여 XML 파일을 만들려고합니다. 내 안드로이드 장치 (약 1 초마다)에서 좌표를받을 때마다 결과를 기존 XML 파일에 추가해야합니다. 찾고있는 출력은 trkpt 요소를 반복 항목으로 사용하여 아래에 표시됩니다. 문제는 trkseg 상위 요소 내부에 있어야하기 때문에 새 trkpt를 파일 끝에 추가 할 수 없다는 것입니다.Java를 사용하여 큰 XML 파일에 하위 요소를 추가하는 방법은 무엇입니까?

지금까지 두 가지 다른 API, SIMPLEXML 및 JDOM을 사용해 보았습니다. SIMPLEXML을 사용하면 자식 요소를 기존 파일에 추가하는 방법을 알 수 없으므로 JDOM으로 전환했습니다. JDOM에서는 아래에 표시된 것처럼 trkpt 요소를 추가 할 수있었습니다. 그러나 파일이 커지면서 빠르게 프로그램의 사용자 인터페이스가 느려졌습니다. JDOM을 사용하여 SAXBuilder를 사용하여 파일을 다시 열고 추가했습니다. 이 문제는 새로운 요소를 추가하고 파일을 다시 작성하기 전에 전체 파일을 메모리에 복제해야한다는 것이 었습니다. 따라서 파일이 커질수록 장치에 작업이 더 많이 요구됩니다. 새 데이터를 작성하기 전에 전체 파일을 검사/복사하지 않는 솔루션이 필요합니다. Java 또는 Java 용 API로이를 수행하는보다 효율적인 방법이 있습니까? 어떤 도움을 주셔서 감사합니다!

<?xml version="1.0" encoding="UTF-8"?> 
<gpx xmlns="http://www.topografix.com/GPX/1/1"> 
     <trk> 
      <trkseg> 
       <trkpt lon="9.860624216140083" lat="54.9328621088893"> 
        <ele>228.0</ele> 
       </trkpt> 
       <trkpt lon="9.860624216140100" lat="54.9328621088754"> 
        <ele>234.0</ele> 
       </trkpt> 
       <trkpt lon="9.860624216140343" lat="54.9328621088678"> 
        <ele>227.0</ele> 
       </trkpt> 
      </trkseg> 
     </trk> 
</gpx> 
+0

항상 같은 방식으로 데이터를 추가하나요? 그런 다음 줄 단위로 파일을 읽은 다음 XML을 인식하지 못하는 방식으로 줄을 추가하십시오. 결과가 유효한 XML 인 한. –

+1

대신에 일반 파일에 데이터를 추가하고 나중에 전체 파일을 XML로 변환 할 수 있습니까? 또는 배치로 변환 할 수 있습니까? XML을 지속적으로 업데이트하려고 시도하는 것은 불필요하게 어려운 일입니다. ;-) – DNA

+0

귀하의 질문에 클라이언트 측 처리 (안드로이드) 및 서버 쪽 처리, 올바른 관련이 있다고 가정합니까? – home

답변

0

반복적 인 방식으로 파일을 열거 나 닫거나 다시 여는 경우 항상 입/출력에 병목 현상이 있습니다.

DOM 처리기는 파일을 열 때마다 전체 트리 구조를 만들지 만 해당 트리를 변경하면 매우 효과적입니다.

우선, 모든 틱에서 파일을 열고 변경하고 저장해야합니까? 그렇지 않은 경우 파일의 DOM을 메모리에 유지하고 XML에 대한 참조를 변경하십시오. 사용자가 앱을 종료하거나보기를 떠나면 저장합니다.

각 틱에서 파일을 저장해야하는 경우 DOM을 메모리에 유지하고 각 틱에서 디스크에 저장하면됩니다.

각 틱에서 파일을 열거 나 저장/다시 열어야하는 경우 XML 라이브러리를 사용하지 마십시오. 표준 FileWriter 등을 사용하면 내용을 수동으로 변경할 수 있습니다. 파일이 너무 커지면 성능을 유지하기 어렵습니다.

+0

모든 틱마다 파일에 저장할 필요는 없습니다. 쓰여지기를 기다리는 동안 데이터를 잃을 가능성이 더 크지 않는 한. 나는 데이터의 양이 GB 범위에 들어갈 수있어서 앱을 종료 할 때 저장하는 것이 문제가 될 수 있다고 언급해야한다고 생각합니다. – Ferrari692

+0

@ Ferrari692 그래, 그리고 그 크기의 DOM 객체도 메모리에 보관하면 안된다. 해당 크기의 전체 파일 (청크 또는 비 XML)을 구문 분석하는 것 이외의 다른 방법을 사용해보십시오. –

0

이것은 SAX에 대한 완벽한 응용 프로그램처럼 들리지만 (패키지 org.xml.sax에서 찾으십시오.); XML 액세스 및 조작을위한 스트리밍 API입니다. SAX는 발견하는 모든 요소에 대한 이벤트를 생성하므로 파일을 큰 메모리 트리로 구문 분석하지 않고 새 파일로 파일을 복사 할 수 있습니다. 입력 파일의 끝에 도달하면 <trkseg> 끝 태그를 처리하기 전에 새 요소를 적절하게 추가하십시오.

물론이 파일을 매초 다시 작성하는 방법은 의심스러운 것으로 들립니다. 정보를 더 큰 세그먼트에 묶을 수 있습니까? 정보를 단일 파일로 덤프하고 특정 간격 (10/30/60 초마다)으로 단일 파일로 수집 할 수 있습니다.

+0

나는 정보를 번들로 묶고 더 큰 간격을 사용하는 데 문제가 없을 것이다. SAX 사용 방법을 살펴 보겠습니다. – Ferrari692

0

여기에 설명 된 것처럼 간단하면 RandomAccessFile을 사용하고 파일 길이에서 몇 바이트 (루트 닫기 태그 바로 앞에)를 찾아 파일을 덮어 쓰기 시작할 수 있습니다.

+0

흥미 롭습니다. 나는 그것을 시험해야 할 것이다. – Ferrari692

0

xml 파일을 3 부분으로 나누는 것이 좋습니다.

head.xml

<?xml version="1.0" encoding="UTF-8"?> 
<gpx xmlns="http://www.topografix.com/GPX/1/1"> 
    <trk> 
     <trkseg> 

몸.XML

<trkpt lon="9.860624216140083" lat="54.9328621088893"> 
    <ele>228.0</ele> 
</trkpt> 
<trkpt lon="9.860624216140100" lat="54.9328621088754"> 
    <ele>234.0</ele> 
</trkpt> 
<trkpt lon="9.860624216140343" lat="54.9328621088678"> 
    <ele>227.0</ele> 
</trkpt> 

tail.xml

 </trkseg> 
    </trk> 
</gpx> 
지금

새로운 데이터를 얻을 때마다, 단순히 다음과 같이 XML 파일 사용을 SequenceInputStream 읽을

을 body.xml하는 데 추가 :

List<InputStream> list = new ArrayList<InputStream>(3); 
list.add(new FileInputStream("head.xml")); 
list.add(new FileInputStream("body.xml")); 
list.add(new FileInputStream("tail.xml")); 
InputStream xmlStream = new SequentialInputStream(Collections.enumeration(list)); 
관련 문제