如何用二进制数据读取xml文件到Matlab? (VTK / VTU文件)

时间:2016-07-22 08:53:04

标签: xml matlab file-io binaryfiles

我希望能够读入一个包含二进制数据的xml正式文件。示例文件如下所示:

<?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">
_�XF@�Loû1q@�`@!?�V7^W@9�D�C�z@�b�d@���Y�b@�r <snip>
</AppendedData>
</VTKFile>

这是一个VTK数据文件,特别是非结构化gid类型,使用.vtu扩展名。这种格式是正常的xml,但有一个部分&#39; AppendedData&#39;如果有下划线后跟二进制数据,则xml描述每个数据序列在此数据中的开始和结束位置。

Matlab&#39; 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 flie。然后我可以解析xml来确定数据结构。这只是将读数留在二进制部分中。在读取结束时,xml数据fgetl将我留在与带有下划线的行的开头相对应的文件位置。

如何忽略下划线字符,然后读入二进制数据?

实际上它是忽略了下划线的角色&#39;我不知道如何在不知道文件的字符编码的情况下弄清楚如何做到这一点( UTF-8在这种情况下我不知道编码,file -bi在一个示例中返回application/xml; charset=binary

如果感兴趣,可以找到实际的vtk文件格式规范here (pdf)

编辑:使用fgetl获取xml部分的代码

% 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

1 个答案:

答案 0 :(得分:0)

确定位置的答案是从读入的第一行计算字符位长度,如下所示:

node_modules

然后数据部分中第一个字节的位置是

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

请注意,这并不是在AppendedData部分中读取“原始”类型数据的完整答案,而这些数据的记录很少。您将找到有关'raw'(而不是'base64')数据here格式的更多信息,但简短的答案是它的编码如下:

datapos = ftell (fid) + bytesperchar;