2016-07-22 3 views
1

Ich möchte in der Lage sein, eine XML-formale Datei einzulesen, die einen Abschnitt enthält, der binäre Daten enthält.Wie lese ich XML-Dateien mit binären Daten in Matlab? (VTK/VTU-Datei)

<?xml version="1.0"?> 
<VTKFile type="UnstructuredGrid" version="0.1" byte_order="LittleEndian"> 
    <UnstructuredGrid> 
    <Piece NumberOfPoints="1941" NumberOfCells="11339"> 
     <PointData> 
     <DataArray type="Float64" Name="magnetic field strength" NumberOfComponents="3" format="appended" offset="0"/> 
     <DataArray type="Float64" Name="magnetic flux density" NumberOfComponents="3" format="appended" offset="46588"/> 
     <DataArray type="Float64" Name="magnetic vector potential" NumberOfComponents="3" format="appended" offset="93176"/> 
     </PointData> 
     <CellData> 
     <DataArray type="Int32" Name="GeometryIds" format="appended" offset="139764"/> 
     </CellData> 
     <Points> 
     <DataArray type="Float64" NumberOfComponents="3" format="appended" offset="185124"/> 
     </Points> 
     <Cells> 
     <DataArray type="Int32" Name="connectivity" format="appended" offset="231712"/> 
     <DataArray type="Int32" Name="offsets" format="appended" offset="403396"/> 
     <DataArray type="Int32" Name="types" format="appended" offset="448756"/> 
     </Cells> 
    </Piece> 
    </UnstructuredGrid> 
<AppendedData encoding="raw"> 
_�[email protected]�Loû[email protected]�`@!?�V7^[email protected]�D�C�[email protected]�b�[email protected]���Y�[email protected]�r <snip> 
</AppendedData> 
</VTKFile> 

Dies ist eine VTK Datendatei, insbesondere der unstrukturierte GID-Typ, für die die .vtu Erweiterung verwendet wird: eine Beispieldatei ist unten gezeigt. Das Format hierfür ist normales xml, aber mit einem Abschnitt 'Apedendedata', wo es einen Unterstrich gibt, gefolgt von binären Daten, beschreibt das XML, wo jede der Datensequenzen in diesen Daten beginnt und endet.

Matlab xmlread kann diese Datei nicht lesen, nehme ich wegen des binären Anteils an. Ich erhalte den Fehler unten:

[Fatal Error] elmer_3d_magnet_mesh.dat0001.vtu:24:1: Invalid byte 1 of 1-byte UTF-8 sequence. 
Error using xmlread (line 97) 
Java exception occurred: 
org.xml.sax.SAXParseException; systemId: file:/home/rcrozier/Sync/cad_models/elmer_3D_magnet/elmer_3d_magnet_mesh/elmer_3d_magnet_mesh.dat0001.vtu; lineNumber: 24; 
columnNumber: 1; Invalid byte 1 of 1-byte UTF-8 sequence. 
    at org.apache.xerces.parsers.DOMParser.parse(Unknown Source) 
    at org.apache.xerces.jaxp.DocumentBuilderImpl.parse(Unknown Source) 
    at javax.xml.parsers.DocumentBuilder.parse(Unknown Source) 

Allerdings habe ich erfolgreich in dem XML-Teil der Datei lesen kann (fgetl mit zum AppendedData Tag lesen). Ich kann dann eine temporäre XML-Ebene erstellen, indem ich die fehlenden schließenden Tags hinzufüge und diese unter Verwendung von xmlread lese. Ich kann dann das XML analysieren, um die Datenstruktur zu bestimmen. Dies lässt nur den Lesevorgang in dem Binärabschnittsteil. Am Ende des Lesens der XML-Daten fgetl lässt mich an der Dateiposition entsprechend dem Anfang der Zeile mit dem Unterstrich.

Wie kann ich den Unterstrich ignorieren und dann die Binärdaten einlesen?

Tatsächlich ist es der Teil, der den Unterstrich ignoriert, der sich als schwierig erweist, da ich nicht herausfinden kann, wie man das macht, ohne die Zeichencodierung der Datei zu kennen ( UTF-8 in diesem Fall I kenne die Codierung nicht, file -bi gibt application/xml; charset=binary an einem Beispiel zurück).

Falls es von Interesse ist, kann die tatsächliche VTK Dateiformatspezifikation here (pdf)

EDIT zu finden: Der Code der XML-Teil mit fgetl

% open the file 
fid = fopen(filename, 'r'); 

% close file when we're done 
CC = onCleanup (@() fclose(fid)); 

xmlstrs = {fgetl(fid)}; 

find = 1; 

while ischar (xmlstrs{find}) 

    find = find + 1; 

    xmlstrs{find,1} = fgetl(fid); 

    if ~isempty(strfind (xmlstrs{find,1}, 'AppendedData')) 

     xmlstrs = [ xmlstrs; {'</AppendedData>'; '</VTKFile>'} ]; 

     % could get file position like this? how many bytes? 
     datapos = ftell (fid) + 4; 

     break; 
    end 

end 
+0

könnten Sie bitte den Code mit dem fgetl fügen Sie schrieb – Finn

+0

@Finn, ich habe es hinzugefügt – crobar

Antwort

0

Die Antwort auf die Bestimmung der Position zu bekommen sollte die Zeichenbitlänge von der ersten eingelesenen Zeile wie folgt berechnen:

% open the file 
fid = fopen(filename, 'r'); 

% close file when we're done 
CC = onCleanup (@() fclose(fid)); 

xmlstrs = {fgetl(fid)}; 

firstlinebytes = ftell (fid) - 1; 

bytesperchar = round (firstlinebytes/numel (xmlstrs{1})); 

dann wird die Position des ersten Bytes im Datenteil ist

datapos = ftell (fid) + bytesperchar; 

Beachten Sie, dass dies zu lesen ‚raw‘ Typdaten im AppendedData Abschnitt nicht die ganze Antwort ist, die schlecht dokumentiert ist. Sie werden weitere Informationen über das Format von ‚raw‘ (statt ‚base64‘) Daten here, finden aber die kurze Antwort ist es codiert wie folgt aus:

_NNNN<data>NNNN<data>NNNN<data> 
^  ^  ^
1   2   3 

where each "NNNN" is an unsigned 32-bit integer, and <data> consists of 
a number of bytes equal to the preceding NNNN value. The corresponding 
DataArray elements must have format="appended" and offset attributes 
equal to the following: 

1.) offset="0" 
2.) offset="(4+NNNN1)" 
3.) offset="(4+NNNN1+4+NNNN2)"