package org.signalml.util.matfiles; import java.io.DataOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; import java.util.zip.DeflaterOutputStream; import org.signalml.util.matfiles.types.DataType; /** * This class can be used to write some data to Matlab MAT files. * The written data is compressed - if you want it to be uncompressed, * please use {@link MatlabFileWriter} instead. * * @author Piotr Szachewicz */ public class CompressedMatlabFileWriter extends MatlabFileWriter { public CompressedMatlabFileWriter(File file) { super(file); } @Override public void write() throws IOException { FileOutputStream fileOutputStream = new FileOutputStream(file); writeHeader(fileOutputStream); //create compressed output stream DeflaterOutputStream deflaterOutputStream = new DeflaterOutputStream(fileOutputStream); DataOutputStream compressedDataOutputStream = new DataOutputStream(deflaterOutputStream); //write compressed data writeData(compressedDataOutputStream); deflaterOutputStream.finish(); //flushes data out, but doesn't close the outputStream //correct the compressed size writeCompressedSize(fileOutputStream); compressedDataOutputStream.close(); } /** * Writes the header for compressed data. * * It consists of the header used for uncompressed data plus * a MI_COMPRESSED file and compressed data size. * * The compressed data size is set to 0 in the beginning, * this value is updated in the {@link CompressedMatlabFileWriter#writeCompressedSize(FileOutputStream)} * method. * * @param fileOutputStream * @throws IOException */ protected void writeHeader(FileOutputStream fileOutputStream) throws IOException { DataOutputStream uncompressedDataOutputStream = new DataOutputStream(fileOutputStream); header.write(uncompressedDataOutputStream); DataType.MI_COMPRESSED.write(uncompressedDataOutputStream); uncompressedDataOutputStream.writeInt(0); //this value is corrected in the writeCompressedSize method } /** * Corrects the compressed data size which was written * in the {@link CompressedMatlabFileWriter#writeHeader(FileOutputStream)} method. * * @param fileOutputStream * @throws IOException */ protected void writeCompressedSize(FileOutputStream fileOutputStream) throws IOException { /* * This method checks how much data was written to the file * and finds the place where the compressed size * should be written (it is set to 0 by now) and appropriately * changes the value which was written there. */ FileChannel channel = fileOutputStream.getChannel(); ByteBuffer byteBuffer = ByteBuffer.allocate(4); int size = (int) channel.size(); size -= header.getTotalSizeInBytes() - DataType.MI_COMPRESSED.getTotalSizeInBytes() - 4 /*compressed size*/; byteBuffer.putInt(size); long previousPosition = channel.position(); channel.position(header.getTotalSizeInBytes() + DataType.MI_COMPRESSED.getTotalSizeInBytes()); byteBuffer.flip(); channel.write(byteBuffer); channel.position(previousPosition); } }