📄 cbzip2outputstream.java
字号:
/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *//* * This package is based on the work done by Keiron Liddle, Aftex Software * <keiron@aftexsw.com> to whom the Ant project is very grateful for his * great code. */package org.apache.tools.bzip2;import java.io.OutputStream;import java.io.IOException;/** * An output stream that compresses into the BZip2 format (without the file * header chars) into another stream. * * TODO: Update to BZip2 1.0.1 */public class CBZip2OutputStream extends OutputStream implements BZip2Constants { protected static final int SETMASK = (1 << 21); protected static final int CLEARMASK = (~SETMASK); protected static final int GREATER_ICOST = 15; protected static final int LESSER_ICOST = 0; protected static final int SMALL_THRESH = 20; protected static final int DEPTH_THRESH = 10; /* If you are ever unlucky/improbable enough to get a stack overflow whilst sorting, increase the following constant and try again. In practice I have never seen the stack go above 27 elems, so the following limit seems very generous. */ protected static final int QSORT_STACK_SIZE = 1000; private static void panic() { System.out.println("panic"); //throw new CError(); } private void makeMaps() { int i; nInUse = 0; for (i = 0; i < 256; i++) { if (inUse[i]) { seqToUnseq[nInUse] = (char) i; unseqToSeq[i] = (char) nInUse; nInUse++; } } } protected static void hbMakeCodeLengths(char[] len, int[] freq, int alphaSize, int maxLen) { /* Nodes and heap entries run from 1. Entry 0 for both the heap and nodes is a sentinel. */ int nNodes, nHeap, n1, n2, i, j, k; boolean tooLong; int[] heap = new int[MAX_ALPHA_SIZE + 2]; int[] weight = new int[MAX_ALPHA_SIZE * 2]; int[] parent = new int[MAX_ALPHA_SIZE * 2]; for (i = 0; i < alphaSize; i++) { weight[i + 1] = (freq[i] == 0 ? 1 : freq[i]) << 8; } while (true) { nNodes = alphaSize; nHeap = 0; heap[0] = 0; weight[0] = 0; parent[0] = -2; for (i = 1; i <= alphaSize; i++) { parent[i] = -1; nHeap++; heap[nHeap] = i; { int zz, tmp; zz = nHeap; tmp = heap[zz]; while (weight[tmp] < weight[heap[zz >> 1]]) { heap[zz] = heap[zz >> 1]; zz >>= 1; } heap[zz] = tmp; } } if (!(nHeap < (MAX_ALPHA_SIZE + 2))) { panic(); } while (nHeap > 1) { n1 = heap[1]; heap[1] = heap[nHeap]; nHeap--; { int zz = 0, yy = 0, tmp = 0; zz = 1; tmp = heap[zz]; while (true) { yy = zz << 1; if (yy > nHeap) { break; } if (yy < nHeap && weight[heap[yy + 1]] < weight[heap[yy]]) { yy++; } if (weight[tmp] < weight[heap[yy]]) { break; } heap[zz] = heap[yy]; zz = yy; } heap[zz] = tmp; } n2 = heap[1]; heap[1] = heap[nHeap]; nHeap--; { int zz = 0, yy = 0, tmp = 0; zz = 1; tmp = heap[zz]; while (true) { yy = zz << 1; if (yy > nHeap) { break; } if (yy < nHeap && weight[heap[yy + 1]] < weight[heap[yy]]) { yy++; } if (weight[tmp] < weight[heap[yy]]) { break; } heap[zz] = heap[yy]; zz = yy; } heap[zz] = tmp; } nNodes++; parent[n1] = parent[n2] = nNodes; weight[nNodes] = ((weight[n1] & 0xffffff00) + (weight[n2] & 0xffffff00)) | (1 + (((weight[n1] & 0x000000ff) > (weight[n2] & 0x000000ff)) ? (weight[n1] & 0x000000ff) : (weight[n2] & 0x000000ff))); parent[nNodes] = -1; nHeap++; heap[nHeap] = nNodes; { int zz = 0, tmp = 0; zz = nHeap; tmp = heap[zz]; while (weight[tmp] < weight[heap[zz >> 1]]) { heap[zz] = heap[zz >> 1]; zz >>= 1; } heap[zz] = tmp; } } if (!(nNodes < (MAX_ALPHA_SIZE * 2))) { panic(); } tooLong = false; for (i = 1; i <= alphaSize; i++) { j = 0; k = i; while (parent[k] >= 0) { k = parent[k]; j++; } len[i - 1] = (char) j; if (j > maxLen) { tooLong = true; } } if (!tooLong) { break; } for (i = 1; i < alphaSize; i++) { j = weight[i] >> 8; j = 1 + (j / 2); weight[i] = j << 8; } } } /* index of the last char in the block, so the block size == last + 1. */ int last; /* index in zptr[] of original string after sorting. */ int origPtr; /* always: in the range 0 .. 9. The current block size is 100000 * this number. */ int blockSize100k; boolean blockRandomised; int bytesOut; int bsBuff; int bsLive; CRC mCrc = new CRC(); private boolean[] inUse = new boolean[256]; private int nInUse; private char[] seqToUnseq = new char[256]; private char[] unseqToSeq = new char[256]; private char[] selector = new char[MAX_SELECTORS]; private char[] selectorMtf = new char[MAX_SELECTORS]; private char[] block; private int[] quadrant; private int[] zptr; private short[] szptr; private int[] ftab; private int nMTF; private int[] mtfFreq = new int[MAX_ALPHA_SIZE]; /* * Used when sorting. If too many long comparisons * happen, we stop sorting, randomise the block * slightly, and try again. */ private int workFactor; private int workDone; private int workLimit; private boolean firstAttempt; private int nBlocksRandomised; private int currentChar = -1; private int runLength = 0; public CBZip2OutputStream(OutputStream inStream) throws IOException { this(inStream, 9); } public CBZip2OutputStream(OutputStream inStream, int inBlockSize) throws IOException { block = null; quadrant = null; zptr = null; ftab = null; bsSetStream(inStream); workFactor = 50; if (inBlockSize > 9) { inBlockSize = 9; } if (inBlockSize < 1) { inBlockSize = 1; } blockSize100k = inBlockSize; allocateCompressStructures(); initialize(); initBlock(); } /** * * modified by Oliver Merkel, 010128 * */ public void write(int bv) throws IOException { int b = (256 + bv) % 256; if (currentChar != -1) { if (currentChar == b) { runLength++; if (runLength > 254) { writeRun(); currentChar = -1; runLength = 0; } } else { writeRun(); runLength = 1; currentChar = b; } } else { currentChar = b; runLength++; } } private void writeRun() throws IOException { if (last < allowableBlockSize) { inUse[currentChar] = true; for (int i = 0; i < runLength; i++) { mCrc.updateCRC((char) currentChar); } switch (runLength) { case 1: last++; block[last + 1] = (char) currentChar; break; case 2: last++; block[last + 1] = (char) currentChar; last++; block[last + 1] = (char) currentChar; break; case 3: last++; block[last + 1] = (char) currentChar; last++; block[last + 1] = (char) currentChar; last++; block[last + 1] = (char) currentChar; break; default: inUse[runLength - 4] = true; last++; block[last + 1] = (char) currentChar; last++; block[last + 1] = (char) currentChar; last++; block[last + 1] = (char) currentChar; last++; block[last + 1] = (char) currentChar; last++; block[last + 1] = (char) (runLength - 4); break; } } else { endBlock(); initBlock(); writeRun(); } } boolean closed = false; protected void finalize() throws Throwable { close(); super.finalize(); } public void close() throws IOException { if (closed) { return; } if (runLength > 0) { writeRun(); } currentChar = -1; endBlock(); endCompression(); closed = true; super.close(); bsStream.close(); } public void flush() throws IOException { super.flush(); bsStream.flush(); } private int blockCRC, combinedCRC; private void initialize() throws IOException { bytesOut = 0; nBlocksRandomised = 0; /* Write `magic' bytes h indicating file-format == huffmanised, followed by a digit indicating blockSize100k. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -