Senin, 12 Oktober 2015
Compressi LZ78 Source Code
package lz78ok;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Path;
import java.nio.file.Paths;
public class LZ78OK {
public static void main(String[] args) {
LZ78 lz78 = new LZ78();
InputStream is, isDecompress;
OutputStream os, osDecompress;
String filename = "file3MB.txt";
Path currentRelativePath = Paths.get("");
String s = currentRelativePath.toAbsolutePath().toString();
System.out.println("Current relative path is: " + s);
String filePath = s+"/doc/"+filename;
try {
is = new FileInputStream(filePath);
os = new FileOutputStream(new String(filePath + ".lz78"));
lz78.compress(is, os);
isDecompress = new FileInputStream(new String(filePath + ".lz78"));
osDecompress = new FileOutputStream(new String(filePath + ".lz78.decompressed.txt"));
lz78.decompress(isDecompress, osDecompress);
System.out.println("Done");
System.out.println(new String(filePath));
} catch (Exception e) {
}
}
}
======================
package lz78ok;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
public class LZ78 implements Compression {
boolean stopped = false;
public class Code {
Code(int code, int ch) {
this.ch = ch;
this.code = code;
}
int ch;
int code;
};
Dictionary dict;
byte[] buf;
public final ByteArray emptyBA = new ByteArray();
ByteArray w = emptyBA;
public LZ78() {
int numOfBits = 12;
buf = new byte[numOfBits];
dict = new LimitedSizeDictionary(1 << numOfBits);
dict.add(emptyBA);
}
public int encodeOneChar(int n) {
byte c = (byte) n;
ByteArray nw = w.conc(c);
int code = dict.numFromStr(nw);
if (code != -1) {
w = nw;
return -1;
} else {
dict.add(nw);
nw = w;
w = emptyBA;
return dict.numFromStr(nw);
}
}
public Code encodeLast() {
if (w.size() == 0)
return null;
byte bt = w.getLast();
w = w.dropLast();
return new Code(dict.numFromStr(w), (int) bt);
}
public final void writeCode(OutputStream os, Code c) throws IOException {
writeCode(os, c.ch, 8);
writeCode(os, c.code, 12);
}
public final void writeCode(OutputStream os, int num, int bits) throws IOException {
for (int i = 0; i < bits; ++i) {
os.write(num & 1);
num = num / 2;
}
}
public final Code readCode(InputStream is) throws IOException {
int ch = readInt(is, 8);
if (ch < 0)
return null;
int cd = readInt(is, 12);
if (cd < 0)
return null;
return new Code(cd, ch);
}
public final int readInt(InputStream is, int bits) throws IOException {
int num = 0;
for (int i = 0; i < bits; ++i) {
int next = is.read();
if (next < 0)
return -1;
num += next << i;
}
return num;
}
public void compress(InputStream is, OutputStream os) throws IOException {
os = new BitOutputStream(os);
int next;
int code;
while ((next = is.read()) >= 0) {
if (stopped) {
break;
}
code = encodeOneChar(next);
if (code >= 0) {
writeCode(os, new Code(code, next));
}
}
Code c = encodeLast();
if (c != null) {
writeCode(os, c);
}
os.flush();
}
public ByteArray decodeOne(Code c) {
ByteArray str = dict.strFromNum(c.code);
dict.add(str.conc((byte) c.ch));
return str;
}
@SuppressWarnings("unused")
public void decompress(InputStream is, OutputStream os) throws IOException {
is = new BitInputStream(is);
ByteArray str;
Code c;
while ((c = readCode(is)) != null) {
if (stopped) {
break;
}
if (c == null) {
break;
}
str = decodeOne(c);
os.write(str.getBytes());
os.write(c.ch);
}
}
public void stop() {
stopped = true;
}
}
=================
package lz78ok;
public class ByteArray {
final byte[] arr;
ByteArray(byte[] b) {
arr = (byte[]) b.clone();
}
ByteArray() {
arr = new byte[0];
}
ByteArray(byte b) {
arr = new byte[] { b };
}
public boolean equals(Object o) {
ByteArray ba = (ByteArray) o;
return java.util.Arrays.equals(arr, ba.arr);
}
public int hashCode() {
int code = 0;
for (int i = 0; i < arr.length; ++i)
code = code * 2 + arr[i];
return code;
}
public int size() {
return arr.length;
}
byte getAt(int i) {
return arr[i];
}
public ByteArray conc(ByteArray b2) {
int sz = size() + b2.size();
byte[] b = new byte[sz];
for (int i = 0; i < size(); ++i)
b[i] = getAt(i);
for (int i = 0; i < b2.size(); ++i)
b[i + size()] = b2.getAt(i);
return new ByteArray(b);
}
public ByteArray conc(byte b2) {
return conc(new ByteArray(b2));
}
public byte[] getBytes() {
return (byte[]) arr.clone();
}
public boolean isEmpty() {
return size() == 0;
}
public byte getLast() {
return arr[size() - 1];
}
public ByteArray dropLast() {
byte[] newarr = new byte[size() - 1];
for (int i = 0; i < newarr.length; ++i)
newarr[i] = arr[i];
return new ByteArray(newarr);
}
public String toString() {
return new String(arr);
}
}
=======================
package lz78ok;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
public interface Compression {
public void compress(InputStream inp, OutputStream out) throws IOException;
public void decompress(InputStream inp, OutputStream out) throws IOException;
}
=======================
package lz78ok;
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
public class BitInputStream extends FilterInputStream {
/**
* Constructor creates a new instance of BitInputStream, A decarotor to
* InputStream, via FilterInputStream
*/
public BitInputStream(InputStream is) {
super(is);
}
class BitManager {
// Buffer to keep max of 7 bits (one byte)
private int[] buf = new int[8];
// Counter showing the bit number we are reading now
private int cnt = -1;
// If we are at the end of the stream
boolean atTheEnd() {
return ((buf[7] == 1) && (cnt < 0));
}
// Set the flag for the end of stream
void setTheEnd() {
buf[7] = 1;
cnt = -1;
}
// No more buffer, means we need to read the next byte
boolean noMoreBuffer() {
return cnt < 0;
}
// set the buffer
void setNext(int next) { // put the bits of the byte into the array
for (cnt = 0; cnt < 8; ++cnt) {
buf[cnt] = next % 2;
next /= 2;
}
// if this was the last byte
if (buf[7] == 1) {
for (cnt = 7; cnt >= 0; cnt--)
if (buf[cnt] == 0)
break;
cnt--;
} else {
cnt = 6;
}
}
// get the next bit
int getNext() {
return buf[cnt--];
}
// how many left
int left() {
return cnt + 1;
}
};
BitManager bitManager = new BitManager();
byte[] tempBuf = null;
int tempBufPtr = 0;
int tempBufLen = 0;
private int readNextByte() throws IOException {
int val = -1;
if (tempBufPtr == tempBufLen)
val = super.read();
else {
byte b = tempBuf[tempBufPtr++];
if ((b & 0x80) > 0)
val = ((int) (b & 0x7F)) | 0x80;
else
val = b;
}
return val;
}
/**
* Reads a single bit from the included stream. Returns either 1 or 0, and
* at the end of stream returns -1.
*/
public int read() throws IOException {
// If we are already at the end, return -1
if (bitManager.atTheEnd())
return -1;
// If we are in the last bit, then refill the buffer
if (bitManager.noMoreBuffer()) {
int i = readNextByte();
if (i < 0)
bitManager.setTheEnd();
else
bitManager.setNext(i);
return read();
}
// Return the specific bit
return bitManager.getNext();
}
/** Reads a list of bits given in the byte array as 0's and 1's */
public int read(byte[] arr) throws IOException {
return read(arr, 0, arr.length);
}
public int read(byte[] arr, int off, int len) throws IOException {
int bytelen = ((len - bitManager.left()) / 7);
tempBuf = new byte[bytelen];
tempBufLen = in.read(tempBuf);
tempBufPtr = 0;
for (int i = 0; i < len; ++i) {
int next = read();
if (next < 0)
return i;
arr[off + i] = (byte) next;
}
return len;
}
}
============================
package lz78ok;
import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.OutputStream;
public class BitOutputStream extends FilterOutputStream {
class BitManager {
int buf = 0;
int cnt = 0;
int writeOne(int next) {
int ret = -1;
buf = buf * 2 + next;
cnt++;
if (cnt == 7) {
cnt = 0;
ret = buf;
buf = 0;
} else {
ret = -1;
}
return ret;
}
//
int writeLast() {
int x = 0;
for (int i = 0; i < 7 - cnt; ++i)
x = x * 2 + 1;
for (int i = 7 - cnt; i < 8; ++i)
x = x * 2;
return buf | x;
}
}
BitManager bitManager = new BitManager();
public BitOutputStream(OutputStream os) {
super(os);
}
public void write(int i) throws IOException {
int x = bitManager.writeOne(i >= 1 ? 1 : 0);
if (x >= 0)
out.write(x);
}
public void write(byte[] arr) throws IOException {
write(arr, 0, arr.length);
}
public void write(byte[] arr, int off, int len) throws IOException {
int clen = 0;
for (int i = 0; i < len; ++i) {
int x = bitManager.writeOne(arr[off + i]);
if (x >= 0)
arr[off + (clen++)] = (byte) x;
}
out.write(arr, off, clen);
}
public void flush() throws IOException {
out.write(bitManager.writeLast());
super.flush();
}
}
==================================
Langganan:
Posting Komentar (Atom)
Tidak ada komentar:
Posting Komentar