All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.jmatio.io.stream.MatFileInputStream Maven / Gradle / Ivy

There is a newer version: 3.1.1
Show newest version
/*
 * 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);
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy