From 01bbc9c4875a6ddb5aa27342c8646dca75b0c4af Mon Sep 17 00:00:00 2001 From: Dave Kleinschmidt Date: Fri, 6 Aug 2021 22:15:18 +0000 Subject: [PATCH 1/2] initial implementation: matopen and read for dense, real, mats --- src/MAT.jl | 7 +++++-- src/MAT_v4.jl | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+), 2 deletions(-) create mode 100644 src/MAT_v4.jl diff --git a/src/MAT.jl b/src/MAT.jl index e6c5824..a583c96 100644 --- a/src/MAT.jl +++ b/src/MAT.jl @@ -28,6 +28,7 @@ using HDF5, SparseArrays include("MAT_HDF5.jl") include("MAT_v5.jl") +include("MAT_v4.jl") using .MAT_HDF5, .MAT_v5 @@ -54,8 +55,10 @@ function matopen(filename::AbstractString, rd::Bool, wr::Bool, cr::Bool, tr::Boo magic = read!(rawfid, Vector{UInt8}(undef, 4)) for i = 1:length(magic) if magic[i] == 0 - close(rawfid) - error("\"$filename\" is not a MAT file, or is an unsupported (v4) MAT file") + if wr || cr || tr || ff + error("creating or appending to MATLAB v4 files is not supported") + end + return MAT_v4.matopen(rawfid) end end diff --git a/src/MAT_v4.jl b/src/MAT_v4.jl new file mode 100644 index 0000000..e3f0498 --- /dev/null +++ b/src/MAT_v4.jl @@ -0,0 +1,57 @@ +module MAT_v4 + +import Base: read, write, close + +mutable struct Matlabv4File + ios::IOStream + varnames::Dict{String, Int64} + + Matlabv4File(ios) = new(ios) +end + +const V4_ELTYPE = [Float64, Float32, Int32, Int16, UInt16, UInt8] + +matopen(ios::IOStream) = Matlabv4File(ios) + +function unpack_header_type(type::Int32) + T, P, O, M = digits(type; pad=4) + iszero(O) || error("file is not a v4 MAT file (magic digit not 0)") + iszero(M) || error("only little endian v4 MAT currently supported") + iszero(T) || error("only full numeric matrices supported for v4 MAT files") + + P in 0:5 || error("invalid eltype digit in v4 MAT file: $P") + eltype = V4_ELTYPE[P+1] + + return eltype +end + +function read_one_mat!(mat::Matlabv4File) + type, mrows, ncols, imagf, namlen = read!(mat.ios, Vector{Int32}(undef, 5)) + eltype = unpack_header_type(type) + + iszero(imagf) || error("no imaginary matrix support") + + name = String(read!(mat.ios, Vector{UInt8}(undef, namlen-1))) + + # one null byte before start of matrix data + Base.read(mat.ios, UInt8) + + @show mrows, ncols + value = read!(mat.ios, Matrix{eltype}(undef, mrows, ncols)) + + return name => value +end + +function read(mat::Matlabv4File) + seekstart(mat.ios) + + results = Dict{String,Any}() + while !eof(mat.ios) + name, value = read_one_mat!(mat) + results[name] = value + end + + return results +end + +end # module From 41d0630fdd04e4e5900689c91da6401c3d7362b3 Mon Sep 17 00:00:00 2001 From: Dave Kleinschmidt Date: Fri, 6 Aug 2021 22:19:15 +0000 Subject: [PATCH 2/2] need close for matread to work --- src/MAT_v4.jl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/MAT_v4.jl b/src/MAT_v4.jl index e3f0498..ddcfeba 100644 --- a/src/MAT_v4.jl +++ b/src/MAT_v4.jl @@ -54,4 +54,6 @@ function read(mat::Matlabv4File) return results end +close(mat::Matlabv4File) = close(mat.ios) + end # module