com.jmatio.io.stream.MatFileInputStream Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of matfilerw Show documentation
Show all versions of matfilerw Show documentation
MatFileRW - Read and write .mat files
/*
* Code licensed under new-style BSD (see LICENSE).
* All code up to tags/original: Copyright (c) 2006, Wojciech Gradkowski
* All code after tags/original: Copyright (c) 2015, DiffPlug
*/
package com.jmatio.io.stream;
import java.io.IOException;
import java.nio.ByteBuffer;
import com.jmatio.common.MatDataTypes;
import com.jmatio.types.ByteStorageSupport;
/**
* MAT-file input stream class.
*
* @author Wojciech Gradkowski
*/
public class MatFileInputStream {
private final int type;
private final ByteBuffer buf;
/**
* Attach MAT-file input stream to InputStream
*
* @param is - input stream
* @param type - type of data in the stream
* @see com.jmatio.common.MatDataTypes
*/
public MatFileInputStream(ByteBuffer buf, int type) {
this.type = type;
this.buf = buf;
}
/**
* Reads data (number of bytes red is determined by data type)
* from the stream to int
.
*
* @return
* @throws IOException
*/
public int readInt() throws IOException {
switch (type) {
case MatDataTypes.miUINT8:
return (int) (buf.get() & 0xFF);
case MatDataTypes.miINT8:
return (int) buf.get();
case MatDataTypes.miUINT16:
return (int) (buf.getShort() & 0xFFFF);
case MatDataTypes.miINT16:
return (int) buf.getShort();
case MatDataTypes.miUINT32:
return (int) buf.getInt();
case MatDataTypes.miINT32:
return (int) buf.getInt();
case MatDataTypes.miUINT64:
return (int) buf.getLong();
case MatDataTypes.miINT64:
return (int) buf.getLong();
case MatDataTypes.miDOUBLE:
return (int) buf.getDouble();
default:
throw new IllegalArgumentException("Unknown data type: " + type);
}
}
/**
* Reads data (number of bytes red is determined by data type)
* from the stream to char
.
*
* @return - char
* @throws IOException
*/
public char readChar() throws IOException {
switch (type) {
case MatDataTypes.miUINT8:
return (char) (buf.get() & 0xFF);
case MatDataTypes.miINT8:
return (char) buf.get();
case MatDataTypes.miUINT16:
return (char) (buf.getShort() & 0xFFFF);
case MatDataTypes.miINT16:
return (char) buf.getShort();
case MatDataTypes.miUINT32:
return (char) buf.getInt();
case MatDataTypes.miINT32:
return (char) buf.getInt();
case MatDataTypes.miDOUBLE:
return (char) buf.getDouble();
case MatDataTypes.miUTF8:
return (char) buf.get();
default:
throw new IllegalArgumentException("Unknown data type: " + type);
}
}
/**
* Reads data (number of bytes red is determined by data type)
* from the stream to double
.
*
* @return - double
* @throws IOException
*/
public double readDouble() throws IOException {
switch (type) {
case MatDataTypes.miUINT8:
return (double) (buf.get() & 0xFF);
case MatDataTypes.miINT8:
return (double) buf.get();
case MatDataTypes.miUINT16:
return (double) (buf.getShort() & 0xFFFF);
case MatDataTypes.miINT16:
return (double) buf.getShort();
case MatDataTypes.miUINT32:
return (double) buf.getInt();
case MatDataTypes.miINT32:
return (double) buf.getInt();
case MatDataTypes.miDOUBLE:
return (double) buf.getDouble();
default:
throw new IllegalArgumentException("Unknown data type: " + type);
}
}
public byte readByte() {
switch (type) {
case MatDataTypes.miUINT8:
return (byte) (buf.get() & 0xFF);
case MatDataTypes.miINT8:
return (byte) buf.get();
case MatDataTypes.miUINT16:
return (byte) (buf.getShort() & 0xFFFF);
case MatDataTypes.miINT16:
return (byte) buf.getShort();
case MatDataTypes.miUINT32:
return (byte) buf.getInt();
case MatDataTypes.miINT32:
return (byte) buf.getInt();
case MatDataTypes.miDOUBLE:
return (byte) buf.getDouble();
case MatDataTypes.miUTF8:
return (byte) buf.get();
default:
throw new IllegalArgumentException("Unknown data type: " + type);
}
}
/**
* Reads the data into a {@link ByteBuffer}
. This method is
* only supported for arrays with backing ByteBuffer ({@link ByteStorageSupport}
).
*
* @param dest
* the destination {@link ByteBuffer}
* @param elements
* the number of elements to read into a buffer
* @param storage
* the backing {@link ByteStorageSupport}
that
* gives information how data should be interpreted
* @return reference to the destination {@link ByteBuffer}
* @throws IOException
* if buffer is under-fed, or another IO problem occurs
*/
public ByteBuffer readToByteBuffer(ByteBuffer dest, int elements,
ByteStorageSupport> storage) throws IOException {
int bytesAllocated = storage.getBytesAllocated();
int size = elements * storage.getBytesAllocated();
//direct buffer copy
if (MatDataTypes.sizeOf(type) == bytesAllocated && buf.order().equals(dest.order())) {
int bufMaxSize = 1024;
int bufSize = Math.min(buf.remaining(), bufMaxSize);
int bufPos = buf.position();
byte[] tmp = new byte[bufSize];
while (dest.remaining() > 0) {
int length = Math.min(dest.remaining(), tmp.length);
buf.get(tmp, 0, length);
dest.put(tmp, 0, length);
}
buf.position(bufPos + size);
} else {
//because Matlab writes data not respectively to the declared
//matrix type, the reading is not straight forward (as above)
Class> clazz = storage.getStorageClazz();
while (dest.remaining() > 0) {
if (clazz.equals(Double.class)) {
dest.putDouble(readDouble());
} else if (clazz.equals(Byte.class)) {
dest.put(readByte());
} else if (clazz.equals(Integer.class)) {
dest.putInt(readInt());
} else if (clazz.equals(Long.class)) {
dest.putLong(readLong());
} else if (clazz.equals(Float.class)) {
dest.putFloat(readFloat());
} else if (clazz.equals(Short.class)) {
dest.putShort(readShort());
} else {
throw new RuntimeException("Not supported buffer reader for " + clazz);
}
}
}
dest.rewind();
return dest;
}
private float readFloat() {
switch (type) {
case MatDataTypes.miUINT8:
return (float) (buf.get() & 0xFF);
case MatDataTypes.miINT8:
return (float) buf.get();
case MatDataTypes.miUINT16:
return (float) (buf.getShort() & 0xFFFF);
case MatDataTypes.miINT16:
return (float) buf.getShort();
case MatDataTypes.miUINT32:
return (float) buf.getInt();
case MatDataTypes.miINT32:
return (float) buf.getInt();
case MatDataTypes.miSINGLE:
return (float) buf.getFloat();
case MatDataTypes.miDOUBLE:
return (float) buf.getDouble();
default:
throw new IllegalArgumentException("Unknown data type: " + type);
}
}
private short readShort() {
switch (type) {
case MatDataTypes.miUINT8:
return (short) (buf.get() & 0xFF);
case MatDataTypes.miINT8:
return (short) buf.get();
case MatDataTypes.miUINT16:
return (short) (buf.getShort() & 0xFFFF);
case MatDataTypes.miINT16:
return (short) buf.getShort();
case MatDataTypes.miUINT32:
return (short) buf.getInt();
case MatDataTypes.miINT32:
return (short) buf.getInt();
case MatDataTypes.miUINT64:
return (short) buf.getLong();
case MatDataTypes.miINT64:
return (short) buf.getLong();
case MatDataTypes.miDOUBLE:
return (short) buf.getDouble();
default:
throw new IllegalArgumentException("Unknown data type: " + type);
}
}
private long readLong() {
switch (type) {
case MatDataTypes.miUINT8:
return (long) (buf.get() & 0xFF);
case MatDataTypes.miINT8:
return (long) buf.get();
case MatDataTypes.miUINT16:
return (long) (buf.getShort() & 0xFFFF);
case MatDataTypes.miINT16:
return (long) buf.getShort();
case MatDataTypes.miUINT32:
return (long) buf.getInt();
case MatDataTypes.miINT32:
return (long) buf.getInt();
case MatDataTypes.miUINT64:
return (long) buf.getLong();
case MatDataTypes.miINT64:
return (long) buf.getLong();
case MatDataTypes.miDOUBLE:
return (long) buf.getDouble();
default:
throw new IllegalArgumentException("Unknown data type: " + type);
}
}
public void skip(int padding) {
buf.position(buf.position() + padding);
}
}