/**
  * lzma 解壓縮
  *
  * @param value
  * @return
  */
 public static byte[] unlzma(byte[] value) {
   byte[] result = new byte[0];
   //
   ByteArrayInputStream in = null;
   ByteArrayOutputStream out = null;
   try {
     Decoder decoder = new Decoder();
     byte[] properties = new byte[5];
     System.arraycopy(value, 0, properties, 0, 5);
     if (properties.length != 5) {
       throw new RuntimeException("input .lzma is too short");
     }
     decoder.SetDecoderProperties(properties);
     //
     int length = value.length - properties.length;
     byte[] data = new byte[length];
     System.arraycopy(value, properties.length, data, 0, length);
     //
     in = new ByteArrayInputStream(data);
     out = new ByteArrayOutputStream();
     decoder.Code(in, out, -1);
     result = out.toByteArray();
   } catch (Exception ex) {
     ex.printStackTrace();
   } finally {
     IoHelper.close(in);
     IoHelper.close(out);
   }
   return result;
 }
 /**
  * inflate stream 解壓縮
  *
  * @param value
  * @return
  */
 public static byte[] inflate(byte[] value) {
   byte[] result = new byte[0];
   //
   InflaterInputStream inflater = null;
   ByteArrayInputStream in = null;
   ByteArrayOutputStream out = null;
   try {
     in = new ByteArrayInputStream(value);
     out = new ByteArrayOutputStream();
     inflater = new InflaterInputStream(in);
     //
     byte[] buff = new byte[BUFFER_LENGTH];
     int read = 0;
     while ((read = inflater.read(buff)) > -1) {
       out.write(buff, 0, read);
     }
     //
     result = out.toByteArray();
   } catch (Exception ex) {
     ex.printStackTrace();
   } finally {
     IoHelper.close(in);
     IoHelper.close(inflater);
     IoHelper.close(out);
   }
   return result;
 }
 /**
  * lzma 壓縮
  *
  * <p>MODE_1(1, 0, 16, 64, Encoder.EMatchFinderTypeBT2, 3, 0, 2),
  *
  * <p>MODE_2(2, 0, 20, 64, Encoder.EMatchFinderTypeBT2, 3, 0, 2),
  *
  * <p>MODE_3(3, 1, 19, 64, Encoder.EMatchFinderTypeBT4, 3, 0, 2),
  *
  * <p>MODE_4(4, 2, 20, 64, Encoder.EMatchFinderTypeBT4, 3, 0, 2),
  *
  * <p>MODE_5(5, 2, 21, 128, Encoder.EMatchFinderTypeBT4, 3, 0, 2),
  *
  * <p>MODE_6(6, 2, 22, 128, Encoder.EMatchFinderTypeBT4, 3, 0, 2),
  *
  * <p>MODE_7(7, 2, 23, 128, Encoder.EMatchFinderTypeBT4, 3, 0, 2),
  *
  * <p>MODE_8(8, 2, 24, 255, Encoder.EMatchFinderTypeBT4, 3, 0, 2),
  *
  * <p>MODE_9(9, 2, 25, 255, Encoder.EMatchFinderTypeBT4, 3, 0, 2);
  *
  * @param value
  * @return
  */
 public static byte[] lzma(byte[] value) {
   byte[] result = new byte[0];
   //
   ByteArrayInputStream in = null;
   ByteArrayOutputStream out = null;
   try {
     Encoder encoder = new Encoder();
     in = new ByteArrayInputStream(value);
     out = new ByteArrayOutputStream();
     // fast
     encoder.SetEndMarkerMode(true);
     encoder.SetAlgorithm(0);
     // dictionarysize是主要佔用記憶體的地方(0-30)
     encoder.SetDictionarySize(1 << 20);
     // fb是主要速度的地方(越小越快壓縮率越低,5-273)
     encoder.SetNumFastBytes(64);
     encoder.SetMatchFinder(Encoder.EMatchFinderTypeBT2);
     encoder.SetLcLpPb(3, 0, 2);
     encoder.WriteCoderProperties(out);
     //
     encoder.Code(in, out, -1, -1, null);
     result = out.toByteArray();
   } catch (Exception ex) {
     ex.printStackTrace();
   } finally {
     IoHelper.close(in);
     IoHelper.close(out);
   }
   return result;
 }
 /**
  * inflater 解壓縮
  *
  * @param value
  * @return
  */
 public static byte[] inflater(byte[] value) {
   byte[] result = new byte[0];
   Inflater inflater = null;
   ByteArrayOutputStream out = null;
   try {
     inflater = new Inflater();
     inflater.setInput(value);
     //
     out = new ByteArrayOutputStream();
     byte[] buffer = new byte[1024];
     while (!inflater.finished()) {
       int count = inflater.inflate(buffer);
       out.write(buffer, 0, count);
     }
     //
     result = out.toByteArray();
   } catch (Exception ex) {
     ex.printStackTrace();
   } finally {
     if (inflater != null) {
       inflater.end(); // 不end也不會有oom,不過還是關了吧
     }
     IoHelper.close(out);
   }
   return result;
 }
 /**
  * deflater 壓縮
  *
  * @param value
  * @return
  */
 public static byte[] deflater(byte[] value) {
   byte[] result = new byte[0];
   Deflater deflater = null;
   ByteArrayOutputStream out = null;
   //
   try {
     deflater = new Deflater();
     deflater.setLevel(Deflater.BEST_SPEED); // fast
     deflater.setInput(value);
     deflater.finish();
     //
     out = new ByteArrayOutputStream();
     byte[] buff = new byte[1024];
     while (!deflater.finished()) {
       int count = deflater.deflate(buff);
       out.write(buff, 0, count);
     }
     //
     result = out.toByteArray();
   } catch (Exception ex) {
     ex.printStackTrace();
   } finally {
     if (deflater != null) {
       deflater.end(); // 需end,不然會有oom(約5000次時)
     }
     IoHelper.close(out);
   }
   return result;
 }
 /**
  * deflate stream 壓縮
  *
  * @param value
  * @return
  */
 public static byte[] deflate(byte[] value) {
   byte[] result = new byte[0];
   //
   DeflaterOutputStream deflater = null;
   ByteArrayOutputStream out = null;
   try {
     out = new ByteArrayOutputStream();
     deflater = new DeflaterOutputStream(out);
     deflater.write(value, 0, value.length);
     deflater.finish();
     deflater.flush();
     //
     result = out.toByteArray();
   } catch (Exception ex) {
     ex.printStackTrace();
   } finally {
     IoHelper.close(deflater);
     IoHelper.close(out);
   }
   return result;
 }
 /**
  * gzip 壓縮
  *
  * @param value
  * @return
  */
 public static byte[] gzip(byte[] value) {
   byte[] result = new byte[0];
   GZIPOutputStream gout = null;
   ByteArrayOutputStream out = null;
   //
   try {
     out = new ByteArrayOutputStream();
     gout = new GZIPOutputStream(out, BUFFER_LENGTH);
     gout.write(value);
     gout.finish();
     gout.flush();
     //
     result = out.toByteArray();
   } catch (Exception ex) {
     ex.printStackTrace();
   } finally {
     IoHelper.close(gout);
     IoHelper.close(out);
   }
   return result;
 }