2016-07-22 396 views
1

我希望能夠讀取具有包含二進制數據的部分的xml格式文件。一個例子文件如下所示:如何將帶有二進制數據的xml文件讀入Matlab? (VTK/VTU文件)

<?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> 

這是一個VTK數據文件,特別是非結構化GID類型,使用的量,.vtu擴展。這種格式是正常的xml,但是有一段'AppendedData',其中有一個下劃線,後面跟着二進制數據,xml描述了每個數據序列在這個數據中開始和結束的位置。

Matlab的xmlread無法讀取此文件,我推測是因爲二進制部分。我得到的錯誤如下:

[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) 

不過,我可以在文件的XML部分成功讀取(使用fgetl閱讀到AppendedData標籤)。然後,我可以通過添加缺少的結束標籤並使用xmlread來讀取它,從而創建一個臨時xml文件。然後我可以解析xml以確定數據結構。這只是在二進制部分留下讀數。在讀取xml數據的末尾fgetl將我留在與下劃線對應的行起始位置的文件位置。

如何忽略下劃線字符,然後讀取二進制數據?

其實這是證明困難,因爲我無法弄清楚如何做到這一點不知道有關文件的字符編碼在這種情況下我的「忽略了下劃線」部分( UTF-8不知道編碼,file -bi返回application/xml; charset=binary在一個例子)。

在情況下,它的利益,實際VTK文件格式規範,可以發現here (pdf)

編輯:該代碼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

請你與fgetl添加代碼你寫 – Finn

+0

@Finn,我添加了它 – crobar

回答

0

答案獲取XML部分確定位置從第一行讀入的字符位長度計算如下:

% 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})); 

然後在數據部分的第一個字節的位置是

datapos = ftell (fid) + bytesperchar; 

請注意,這不是全部答案閱讀在AppendedData部,其不良記錄「原始」類型的數據。你會發現在「原始」(而不是「的base64」)數據here格式的更多信息,但簡短的回答是它的編碼如下所示:

_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)"