Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added read and write support for v4 mat files #186

Merged
merged 10 commits into from
Jun 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 13 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

### Read and write MATLAB files in Julia

This library can read MATLAB `.mat` files, both in the older v5/v6/v7 format, as well as the newer v7.3 format.
This library can read MATLAB `.mat` files, both in the older v4/v5/v6/v7 format, as well as the newer v7.3 format.

## Installation

Expand Down Expand Up @@ -56,6 +56,15 @@ matwrite("matfile.mat", Dict(
); compress = true)
```

To write in MATLAB v4 format:

```julia
matwrite("matfile.mat", Dict(
"myvar1" => 0,
"myvar2" => 1
);version="v4")
```

To get a list of variable names in a MAT file:

```julia
Expand All @@ -76,9 +85,9 @@ close(file)

## Caveats

* All files are written in MATLAB v7.3 format.
* MATLAB v4 files are not currently supported.
* All files are written in MATLAB v7.3 format by default.
* Writing in MATLAB v4 format is provided by the matwrite function with keyword argument.

## Credits

The MAT_HDF5 module, which provides read/write support for MATLAB v7.3 files, was written primarily by [Tim Holy](https://github.com/timholy/). The MAT_v5 module, which provides read support for MATLAB v5/v6/v7 files, was written primarily by [Simon Kornblith](https://github.com/simonster/).
The MAT_HDF5 module, which provides read/write support for MATLAB v7.3 files, was written primarily by [Tim Holy](https://github.com/timholy/). The MAT_v5 module, which provides read support for MATLAB v5/v6/v7 files, was written primarily by [Simon Kornblith](https://github.com/simonster/). The MAT_v4 module, which provides read and write support for MATLAB v4 files, was written primarily by [Victor Saase](https://github.com/vsaase/).
74 changes: 48 additions & 26 deletions src/MAT.jl
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,9 @@ using HDF5, SparseArrays

include("MAT_HDF5.jl")
include("MAT_v5.jl")
include("MAT_v4.jl")

using .MAT_HDF5, .MAT_v5
using .MAT_HDF5, .MAT_v5, .MAT_v4

export matopen, matread, matwrite, @read, @write

Expand All @@ -44,19 +45,18 @@ function matopen(filename::AbstractString, rd::Bool, wr::Bool, cr::Bool, tr::Boo
error("File \"$filename\" does not exist and create was not specified")
end

# Test whether this is a MAT file
if fs < 128
error("File \"$filename\" is too small to be a supported MAT file")
end
rawfid = open(filename, "r")

# Check for MAT v4 file
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")
end
(isv4, swap_bytes) = MAT_v4.checkv4(rawfid)
if isv4
return MAT_v4.matopen(rawfid, swap_bytes)
end

# Test whether this is a MAT file
if fs < 128
close(rawfid)
error("File \"$filename\" is too small to be a supported MAT file")
end

# Check for MAT v5 file
Expand Down Expand Up @@ -139,25 +139,47 @@ end

# Write a dict to a MATLAB file
"""
matwrite(filename, d::Dict; compress::Bool = false)
matwrite(filename, d::Dict; compress::Bool = false, version::String)

Write a dictionary containing variable names as keys and values as values
to a Matlab file, opening and closing it automatically.
"""
function matwrite(filename::AbstractString, dict::AbstractDict{S, T}; compress::Bool = false) where {S, T}
file = matopen(filename, "w"; compress = compress)
try
for (k, v) in dict
local kstring
try
kstring = ascii(convert(String, k))
catch x
error("matwrite requires a Dict with ASCII keys")
function matwrite(filename::AbstractString, dict::AbstractDict{S, T}; compress::Bool = false, version::String ="") where {S, T}

if version == "v4"
file = open(filename, "w")
m = MAT_v4.Matlabv4File(file, false)
try
for (k, v) in dict
local kstring
try
kstring = ascii(convert(String, k))
catch x
error("matwrite requires a Dict with ASCII keys")
end
write(m, kstring, v)
end
write(file, kstring, v)
finally
close(file)
end
finally
close(file)

else

file = matopen(filename, "w"; compress = compress)
try
for (k, v) in dict
local kstring
try
kstring = ascii(convert(String, k))
catch x
error("matwrite requires a Dict with ASCII keys")
end
write(file, kstring, v)
end
finally
close(file)
end

end
end

Expand All @@ -166,11 +188,11 @@ end
###

export exists
@noinline function exists(matfile::Union{MAT_v5.Matlabv5File,MAT_HDF5.MatlabHDF5File}, varname::String)
@noinline function exists(matfile::Union{MAT_v4.Matlabv4File,MAT_v5.Matlabv5File,MAT_HDF5.MatlabHDF5File}, varname::String)
Base.depwarn("`exists(matfile, varname)` is deprecated, use `haskey(matfile, varname)` instead.", :exists)
return haskey(matfile, varname)
end
@noinline function Base.names(matfile::Union{MAT_v5.Matlabv5File,MAT_HDF5.MatlabHDF5File})
@noinline function Base.names(matfile::Union{MAT_v4.Matlabv4File,MAT_v5.Matlabv5File,MAT_HDF5.MatlabHDF5File})
Base.depwarn("`names(matfile)` is deprecated, use `keys(matfile)` instead.", :names)
return keys(matfile)
end
Expand Down
Loading