1 /*******************************************************************************
2 * Copyright (c) 2007, 2012 Association for Decentralized Information Management
4 * All rights reserved. This program and the accompanying materials
5 * are made available under the terms of the Eclipse Public License v1.0
6 * which accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
10 * VTT Technical Research Centre of Finland - initial API and implementation
11 *******************************************************************************/
12 package org.simantics.compressions.impl;
15 import java.io.FileNotFoundException;
16 import java.io.FileOutputStream;
17 import java.io.IOException;
18 import java.io.OutputStream;
19 import java.nio.ByteBuffer;
20 import java.nio.ByteOrder;
21 import java.nio.IntBuffer;
22 import java.nio.channels.WritableByteChannel;
25 * @author Hannu Niemistö
26 * @author Tuukka Lehtonen
28 public abstract class CompressingOutputStream extends OutputStream {
30 protected static final int BLOCK_SIZE = 1024 * 1024;
32 protected OutputStream stream;
33 protected WritableByteChannel channel;
34 protected ByteBuffer compressed;
35 protected byte[] compressedArray;
36 protected ByteBuffer uncompressed;
37 protected IntBuffer header;
38 protected int bytes = 0;
40 public CompressingOutputStream(File file) throws FileNotFoundException {
41 this(new FileOutputStream(file));
44 public CompressingOutputStream(FileOutputStream stream) {
45 this(stream, stream.getChannel());
48 public CompressingOutputStream(OutputStream stream) {
52 public CompressingOutputStream(OutputStream stream, WritableByteChannel channel) {
54 this.channel = channel;
55 uncompressed = allocateBuffer(BLOCK_SIZE);
59 public void write(int b) throws IOException {
60 if(uncompressed.remaining() == 0)
62 uncompressed.put((byte)b);
67 public void write(byte[] b, int off, int len) throws IOException {
70 int s = Math.min(len, uncompressed.remaining());
71 uncompressed.put(b, off, s);
74 if(uncompressed.remaining() == 0)
80 public void close() throws IOException {
84 if (channel != null) {
88 compressed.position(0);
90 channel.write(compressed);
91 } else if (stream != null) {
92 stream.write(new byte[8]);
94 //System.out.println("Wrote " + bytes + " uncompressed bytes.");
96 if (channel != null) {
100 if (stream != null) {
107 private void flushBuffer() throws IOException {
108 int uncompressedSize = uncompressed.position();
109 uncompressed.position(0);
110 int maxCompressedSize = compressBound(uncompressedSize) + 8;
111 if(compressed == null || compressed.capacity() < maxCompressedSize) {
112 compressed = allocateBuffer(maxCompressedSize);
113 compressed.order(ByteOrder.LITTLE_ENDIAN);
114 header = compressed.asIntBuffer();
116 compressedArray = new byte[maxCompressedSize];
118 int compressedSize = compress(uncompressed, 0, uncompressedSize,
121 header.put(compressedSize);
122 header.put(uncompressedSize);
123 compressed.position(0);
124 compressed.limit(compressedSize+8);
125 if (channel != null) {
126 channel.write(compressed);
128 compressed.get(compressedArray, 0, compressedSize+8);
129 stream.write(compressedArray, 0, compressedSize+8);
133 protected abstract int compressBound(int inputSize);
135 protected abstract int compress(ByteBuffer uncompressed, int uncompressedOffset, int uncompressedSize,
136 ByteBuffer compressed, int compressedOffset) throws IOException;
138 protected abstract ByteBuffer allocateBuffer(int capacity);