java 压缩和解压缩

BZip2CompressorOutputStream类用于压缩
BZip2CompressorInputStream类用于解压缩


先说压缩实现,BZip2CompressorOutputStream只有一个方法用于压缩,就是带定长的write方法。简单调用如下文所示:
Java代码
  1. /**  
  2.  * 数据压缩  
  3.  *   
  4.  * @param is  
  5.  * @param os  
  6.  * @throws Exception  
  7.  */  
  8. public static void compress(InputStream is, OutputStream os)   
  9.         throws Exception {   
  10.   
  11.     BZip2CompressorOutputStream gos = new BZip2CompressorOutputStream(os);   
  12.   
  13.     int count;   
  14.     byte data[] = new byte[BUFFER];   
  15.     while ((count = is.read(data, 0, BUFFER)) != -1) {   
  16.         gos.write(data, 0, count);   
  17.     }   
  18.   
  19.     gos.finish();   
  20.   
  21.     gos.flush();   
  22.     gos.close();   
  23. }  
	/**
	 * 数据压缩
	 * 
	 * @param is
	 * @param os
	 * @throws Exception
	 */
	public static void compress(InputStream is, OutputStream os)
			throws Exception {

		BZip2CompressorOutputStream gos = new BZip2CompressorOutputStream(os);

		int count;
		byte data[] = new byte[BUFFER];
		while ((count = is.read(data, 0, BUFFER)) != -1) {
			gos.write(data, 0, count);
		}

		gos.finish();

		gos.flush();
		gos.close();
	}

与GZip实现有何差别?除了换掉了GZIPOutputStream没有任何差别。

解压缩就更不用说了,BZip2CompressorInputStream提供了一个带定长的read方法。简单调用如下文所示:
Java代码
  1. /**  
  2.  * 数据解压缩  
  3.  *   
  4.  * @param is  
  5.  * @param os  
  6.  * @throws Exception  
  7.  */  
  8. public static void decompress(InputStream is, OutputStream os)   
  9.         throws Exception {   
  10.   
  11.     BZip2CompressorInputStream gis = new BZip2CompressorInputStream(is);   
  12.   
  13.     int count;   
  14.     byte data[] = new byte[BUFFER];   
  15.     while ((count = gis.read(data, 0, BUFFER)) != -1) {   
  16.         os.write(data, 0, count);   
  17.     }   
  18.   
  19.     gis.close();   
  20. }  
	/**
	 * 数据解压缩
	 * 
	 * @param is
	 * @param os
	 * @throws Exception
	 */
	public static void decompress(InputStream is, OutputStream os)
			throws Exception {

		BZip2CompressorInputStream gis = new BZip2CompressorInputStream(is);

		int count;
		byte data[] = new byte[BUFFER];
		while ((count = gis.read(data, 0, BUFFER)) != -1) {
			os.write(data, 0, count);
		}

		gis.close();
	}

嗯,没什么难度!
IT这行就是这样,只要你肯用心,能触类旁通,就能融会贯通!
给一个完整实现:
Java代码
  1. /**  
  2.  * 2010-4-15  
  3.  */  
  4. package org.zlex.commons.compress.compress;   
  5.   
  6. import java.io.ByteArrayInputStream;   
  7. import java.io.ByteArrayOutputStream;   
  8. import java.io.File;   
  9. import java.io.FileInputStream;   
  10. import java.io.FileOutputStream;   
  11. import java.io.InputStream;   
  12. import java.io.OutputStream;   
  13.   
  14. import org.apache.commons.compress.compressors.bzip2.BZip2CompressorInputStream;   
  15. import org.apache.commons.compress.compressors.bzip2.BZip2CompressorOutputStream;   
  16.   
  17. /**  
  18.  * BZip2工具  
  19.  *   
  20.  * @author  <a href="mailto:zlex.dongliang@gmail.com">梁栋</a>  
  21.  * @since 1.0  
  22.  */  
  23. public abstract class BZip2Utils {   
  24.   
  25.     public static final int BUFFER = 1024;   
  26.     public static final CharSequence EXT = ".bz2";   
  27.   
  28.     /**  
  29.      * 数据压缩  
  30.      *   
  31.      * @param data  
  32.      * @return  
  33.      * @throws Exception  
  34.      */  
  35.     public static byte[] compress(byte[] data) throws Exception {   
  36.         ByteArrayInputStream bais = new ByteArrayInputStream(data);   
  37.         ByteArrayOutputStream baos = new ByteArrayOutputStream();   
  38.   
  39.         // 压缩   
  40.         compress(bais, baos);   
  41.   
  42.         byte[] output = baos.toByteArray();   
  43.   
  44.         baos.flush();   
  45.         baos.close();   
  46.   
  47.         bais.close();   
  48.   
  49.         return output;   
  50.     }   
  51.   
  52.     /**  
  53.      * 文件压缩  
  54.      *   
  55.      * @param file  
  56.      * @throws Exception  
  57.      */  
  58.     public static void compress(File file) throws Exception {   
  59.         compress(file, true);   
  60.     }   
  61.   
  62.     /**  
  63.      * 文件压缩  
  64.      *   
  65.      * @param file  
  66.      * @param delete  
  67.      *            是否删除原始文件  
  68.      * @throws Exception  
  69.      */  
  70.     public static void compress(File file, boolean delete) throws Exception {   
  71.         FileInputStream fis = new FileInputStream(file);   
  72.         FileOutputStream fos = new FileOutputStream(file.getPath() + EXT);   
  73.   
  74.         compress(fis, fos);   
  75.   
  76.         fis.close();   
  77.         fos.flush();   
  78.         fos.close();   
  79.   
  80.         if (delete) {   
  81.             file.delete();   
  82.         }   
  83.     }   
  84.   
  85.     /**  
  86.      * 数据压缩  
  87.      *   
  88.      * @param is  
  89.      * @param os  
  90.      * @throws Exception  
  91.      */  
  92.     public static void compress(InputStream is, OutputStream os)   
  93.             throws Exception {   
  94.   
  95.         BZip2CompressorOutputStream gos = new BZip2CompressorOutputStream(os);   
  96.   
  97.         int count;   
  98.         byte data[] = new byte[BUFFER];   
  99.         while ((count = is.read(data, 0, BUFFER)) != -1) {   
  100.             gos.write(data, 0, count);   
  101.         }   
  102.   
  103.         gos.finish();   
  104.   
  105.         gos.flush();   
  106.         gos.close();   
  107.     }   
  108.   
  109.     /**  
  110.      * 文件压缩  
  111.      *   
  112.      * @param path  
  113.      * @throws Exception  
  114.      */  
  115.     public static void compress(String path) throws Exception {   
  116.         compress(path, true);   
  117.     }   
  118.   
  119.     /**  
  120.      * 文件压缩  
  121.      *   
  122.      * @param path  
  123.      * @param delete  
  124.      *            是否删除原始文件  
  125.      * @throws Exception  
  126.      */  
  127.     public static void compress(String path, boolean delete) throws Exception {   
  128.         File file = new File(path);   
  129.         compress(file, delete);   
  130.     }   
  131.   
  132.     /**  
  133.      * 数据解压缩  
  134.      *   
  135.      * @param data  
  136.      * @return  
  137.      * @throws Exception  
  138.      */  
  139.     public static byte[] decompress(byte[] data) throws Exception {   
  140.         ByteArrayInputStream bais = new ByteArrayInputStream(data);   
  141.         ByteArrayOutputStream baos = new ByteArrayOutputStream();   
  142.   
  143.         // 解压缩   
  144.   
  145.         decompress(bais, baos);   
  146.   
  147.         data = baos.toByteArray();   
  148.   
  149.         baos.flush();   
  150.         baos.close();   
  151.   
  152.         bais.close();   
  153.   
  154.         return data;   
  155.     }   
  156.   
  157.     /**  
  158.      * 文件解压缩  
  159.      *   
  160.      * @param file  
  161.      * @throws Exception  
  162.      */  
  163.     public static void decompress(File file) throws Exception {   
  164.         decompress(file, true);   
  165.     }   
  166.   
  167.     /**  
  168.      * 文件解压缩  
  169.      *   
  170.      * @param file  
  171.      * @param delete  
  172.      *            是否删除原始文件  
  173.      * @throws Exception  
  174.      */  
  175.     public static void decompress(File file, boolean delete) throws Exception {   
  176.         FileInputStream fis = new FileInputStream(file);   
  177.         FileOutputStream fos = new FileOutputStream(file.getPath().replace(EXT,   
  178.                 ""));   
  179.         decompress(fis, fos);   
  180.         fis.close();   
  181.         fos.flush();   
  182.         fos.close();   
  183.   
  184.         if (delete) {   
  185.             file.delete();   
  186.         }   
  187.     }   
  188.   
  189.     /**  
  190.      * 数据解压缩  
  191.      *   
  192.      * @param is  
  193.      * @param os  
  194.      * @throws Exception  
  195.      */  
  196.     public static void decompress(InputStream is, OutputStream os)   
  197.             throws Exception {   
  198.   
  199.         BZip2CompressorInputStream gis = new BZip2CompressorInputStream(is);   
  200.   
  201.         int count;   
  202.         byte data[] = new byte[BUFFER];   
  203.         while ((count = gis.read(data, 0, BUFFER)) != -1) {   
  204.             os.write(data, 0, count);   
  205.         }   
  206.   
  207.         gis.close();   
  208.     }   
  209.   
  210.     /**  
  211.      * 文件解压缩  
  212.      *   
  213.      * @param path  
  214.      * @throws Exception  
  215.      */  
  216.     public static void decompress(String path) throws Exception {   
  217.         decompress(path, true);   
  218.     }   
  219.   
  220.     /**  
  221.      * 文件解压缩  
  222.      *   
  223.      * @param path  
  224.      * @param delete  
  225.      *            是否删除原始文件  
  226.      * @throws Exception  
  227.      */  
  228.     public static void decompress(String path, boolean delete) throws Exception {   
  229.         File file = new File(path);   
  230.         decompress(file, delete);   
  231.     }   
  232.   
  233. }  
/**
 * 2010-4-15
 */
package org.zlex.commons.compress.compress;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;

import org.apache.commons.compress.compressors.bzip2.BZip2CompressorInputStream;
import org.apache.commons.compress.compressors.bzip2.BZip2CompressorOutputStream;

/**
 * BZip2工具
 * 
 * @author  <a href="mailto:zlex.dongliang@gmail.com">梁栋</a>
 * @since 1.0
 */
public abstract class BZip2Utils {

	public static final int BUFFER = 1024;
	public static final CharSequence EXT = ".bz2";

	/**
	 * 数据压缩
	 * 
	 * @param data
	 * @return
	 * @throws Exception
	 */
	public static byte[] compress(byte[] data) throws Exception {
		ByteArrayInputStream bais = new ByteArrayInputStream(data);
		ByteArrayOutputStream baos = new ByteArrayOutputStream();

		// 压缩
		compress(bais, baos);

		byte[] output = baos.toByteArray();

		baos.flush();
		baos.close();

		bais.close();

		return output;
	}

	/**
	 * 文件压缩
	 * 
	 * @param file
	 * @throws Exception
	 */
	public static void compress(File file) throws Exception {
		compress(file, true);
	}

	/**
	 * 文件压缩
	 * 
	 * @param file
	 * @param delete
	 *            是否删除原始文件
	 * @throws Exception
	 */
	public static void compress(File file, boolean delete) throws Exception {
		FileInputStream fis = new FileInputStream(file);
		FileOutputStream fos = new FileOutputStream(file.getPath() + EXT);

		compress(fis, fos);

		fis.close();
		fos.flush();
		fos.close();

		if (delete) {
			file.delete();
		}
	}

	/**
	 * 数据压缩
	 * 
	 * @param is
	 * @param os
	 * @throws Exception
	 */
	public static void compress(InputStream is, OutputStream os)
			throws Exception {

		BZip2CompressorOutputStream gos = new BZip2CompressorOutputStream(os);

		int count;
		byte data[] = new byte[BUFFER];
		while ((count = is.read(data, 0, BUFFER)) != -1) {
			gos.write(data, 0, count);
		}

		gos.finish();

		gos.flush();
		gos.close();
	}

	/**
	 * 文件压缩
	 * 
	 * @param path
	 * @throws Exception
	 */
	public static void compress(String path) throws Exception {
		compress(path, true);
	}

	/**
	 * 文件压缩
	 * 
	 * @param path
	 * @param delete
	 *            是否删除原始文件
	 * @throws Exception
	 */
	public static void compress(String path, boolean delete) throws Exception {
		File file = new File(path);
		compress(file, delete);
	}

	/**
	 * 数据解压缩
	 * 
	 * @param data
	 * @return
	 * @throws Exception
	 */
	public static byte[] decompress(byte[] data) throws Exception {
		ByteArrayInputStream bais = new ByteArrayInputStream(data);
		ByteArrayOutputStream baos = new ByteArrayOutputStream();

		// 解压缩

		decompress(bais, baos);

		data = baos.toByteArray();

		baos.flush();
		baos.close();

		bais.close();

		return data;
	}

	/**
	 * 文件解压缩
	 * 
	 * @param file
	 * @throws Exception
	 */
	public static void decompress(File file) throws Exception {
		decompress(file, true);
	}

	/**
	 * 文件解压缩
	 * 
	 * @param file
	 * @param delete
	 *            是否删除原始文件
	 * @throws Exception
	 */
	public static void decompress(File file, boolean delete) throws Exception {
		FileInputStream fis = new FileInputStream(file);
		FileOutputStream fos = new FileOutputStream(file.getPath().replace(EXT,
				""));
		decompress(fis, fos);
		fis.close();
		fos.flush();
		fos.close();

		if (delete) {
			file.delete();
		}
	}

	/**
	 * 数据解压缩
	 * 
	 * @param is
	 * @param os
	 * @throws Exception
	 */
	public static void decompress(InputStream is, OutputStream os)
			throws Exception {

		BZip2CompressorInputStream gis = new BZip2CompressorInputStream(is);

		int count;
		byte data[] = new byte[BUFFER];
		while ((count = gis.read(data, 0, BUFFER)) != -1) {
			os.write(data, 0, count);
		}

		gis.close();
	}

	/**
	 * 文件解压缩
	 * 
	 * @param path
	 * @throws Exception
	 */
	public static void decompress(String path) throws Exception {
		decompress(path, true);
	}

	/**
	 * 文件解压缩
	 * 
	 * @param path
	 * @param delete
	 *            是否删除原始文件
	 * @throws Exception
	 */
	public static void decompress(String path, boolean delete) throws Exception {
		File file = new File(path);
		decompress(file, delete);
	}

}

对应再来个测试用例,测试用例如下所示:
Java代码
  1. /**  
  2.  * 2010-4-13  
  3.  */  
  4. package org.zlex.commons.compress.compress;   
  5.   
  6. import static org.junit.Assert.assertEquals;   
  7.   
  8. import java.io.DataInputStream;   
  9. import java.io.File;   
  10. import java.io.FileInputStream;   
  11. import java.io.FileOutputStream;   
  12.   
  13. import org.junit.Test;   
  14.   
  15. /**  
  16.  * BZip2  
  17.  *   
  18.  * @author <a href="mailto:zlex.dongliang@gmail.com">梁栋</a>  
  19.  * @since 1.0  
  20.  */  
  21. public class BZip2UtilsTest {   
  22.   
  23.     private String inputStr = "zlex@zlex.org,snowolf@zlex.org,zlex.snowolf@zlex.org,zlex@zlex.org,snowolf@zlex.org,zlex.snowolf@zlex.org,zlex@zlex.org,snowolf@zlex.org,zlex.snowolf@zlex.org,zlex@zlex.org,snowolf@zlex.org,zlex.snowolf@zlex.org,zlex@zlex.org,snowolf@zlex.org,zlex.snowolf@zlex.org,zlex@zlex.org,snowolf@zlex.org,zlex.snowolf@zlex.org,zlex@zlex.org,snowolf@zlex.org,zlex.snowolf@zlex.org,zlex@zlex.org,snowolf@zlex.org,zlex.snowolf@zlex.org,zlex@zlex.org,snowolf@zlex.org,zlex.snowolf@zlex.org,zlex@zlex.org,snowolf@zlex.org,zlex.snowolf@zlex.org";   
  24.   
  25.     @Test  
  26.     public final void testDataCompress() throws Exception {   
  27.   
  28.         byte[] input = inputStr.getBytes();   
  29.         System.err.println("原文:\t" + inputStr);   
  30.         System.err.println("长度:\t" + input.length);   
  31.   
  32.         byte[] data = BZip2Utils.compress(input);   
  33.         System.err.println("压缩后:\t");   
  34.         System.err.println("长度:\t" + data.length);   
  35.   
  36.         byte[] output = BZip2Utils.decompress(data);   
  37.         String outputStr = new String(output);   
  38.         System.err.println("解压缩后:\t" + outputStr);   
  39.         System.err.println("长度:\t" + output.length);   
  40.   
  41.         assertEquals(inputStr, outputStr);   
  42.   
  43.     }   
  44.   
  45.     @Test  
  46.     public final void testFileCompress() throws Exception {   
  47.   
  48.         FileOutputStream fos = new FileOutputStream("d:/f.txt");   
  49.   
  50.         fos.write(inputStr.getBytes());   
  51.         fos.flush();   
  52.         fos.close();   
  53.   
  54.         BZip2Utils.compress("d:/f.txt");   
  55.   
  56.         BZip2Utils.decompress("d:/f.txt.bz2");   
  57.   
  58.         File file = new File("d:/f.txt");   
  59.   
  60.         FileInputStream fis = new FileInputStream(file);   
  61.   
  62.         DataInputStream dis = new DataInputStream(fis);   
  63.   
  64.         byte[] data = new byte[(int) file.length()];   
  65.         dis.readFully(data);   
  66.   
  67.         fis.close();   
  68.   
  69.         String outputStr = new String(data);   
  70.         assertEquals(inputStr, outputStr);   
  71.     }   
  72. }  
/**
 * 2010-4-13
 */
package org.zlex.commons.compress.compress;

import static org.junit.Assert.assertEquals;

import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;

import org.junit.Test;

/**
 * BZip2
 * 
 * @author <a href="mailto:zlex.dongliang@gmail.com">梁栋</a>
 * @since 1.0
 */
public class BZip2UtilsTest {

	private String inputStr = "zlex@zlex.org,snowolf@zlex.org,zlex.snowolf@zlex.org,zlex@zlex.org,snowolf@zlex.org,zlex.snowolf@zlex.org,zlex@zlex.org,snowolf@zlex.org,zlex.snowolf@zlex.org,zlex@zlex.org,snowolf@zlex.org,zlex.snowolf@zlex.org,zlex@zlex.org,snowolf@zlex.org,zlex.snowolf@zlex.org,zlex@zlex.org,snowolf@zlex.org,zlex.snowolf@zlex.org,zlex@zlex.org,snowolf@zlex.org,zlex.snowolf@zlex.org,zlex@zlex.org,snowolf@zlex.org,zlex.snowolf@zlex.org,zlex@zlex.org,snowolf@zlex.org,zlex.snowolf@zlex.org,zlex@zlex.org,snowolf@zlex.org,zlex.snowolf@zlex.org";

	@Test
	public final void testDataCompress() throws Exception {

		byte[] input = inputStr.getBytes();
		System.err.println("原文:\t" + inputStr);
		System.err.println("长度:\t" + input.length);

		byte[] data = BZip2Utils.compress(input);
		System.err.println("压缩后:\t");
		System.err.println("长度:\t" + data.length);

		byte[] output = BZip2Utils.decompress(data);
		String outputStr = new String(output);
		System.err.println("解压缩后:\t" + outputStr);
		System.err.println("长度:\t" + output.length);

		assertEquals(inputStr, outputStr);

	}

	@Test
	public final void testFileCompress() throws Exception {

		FileOutputStream fos = new FileOutputStream("d:/f.txt");

		fos.write(inputStr.getBytes());
		fos.flush();
		fos.close();

		BZip2Utils.compress("d:/f.txt");

		BZip2Utils.decompress("d:/f.txt.bz2");

		File file = new File("d:/f.txt");

		FileInputStream fis = new FileInputStream(file);

		DataInputStream dis = new DataInputStream(fis);

		byte[] data = new byte[(int) file.length()];
		dis.readFully(data);

		fis.close();

		String outputStr = new String(data);
		assertEquals(inputStr, outputStr);
	}
}

虽然,两种算法在代码实现上几乎没有什么差别,但在压缩上想要看到效果,还真让我费了点事!
控制台输出如下所示:
引用

原文: zlex@zlex.org,snowolf@zlex.org,zlex.snowolf@zlex.org,zlex@zlex.org,snowolf@zlex.org,zlex.snowolf@zlex.org,zlex@zlex.org,snowolf@zlex.org,zlex.snowolf@zlex.org,zlex@zlex.org,snowolf@zlex.org,zlex.snowolf@zlex.org,zlex@zlex.org,snowolf@zlex.org,zlex.snowolf@zlex.org,zlex@zlex.org,snowolf@zlex.org,zlex.snowolf@zlex.org,zlex@zlex.org,snowolf@zlex.org,zlex.snowolf@zlex.org,zlex@zlex.org,snowolf@zlex.org,zlex.snowolf@zlex.org,zlex@zlex.org,snowolf@zlex.org,zlex.snowolf@zlex.org,zlex@zlex.org,snowolf@zlex.org,zlex.snowolf@zlex.org
长度: 529
压缩后:
长度: 76
解压缩后: zlex@zlex.org,snowolf@zlex.org,zlex.snowolf@zlex.org,zlex@zlex.org,snowolf@zlex.org,zlex.snowolf@zlex.org,zlex@zlex.org,snowolf@zlex.org,zlex.snowolf@zlex.org,zlex@zlex.org,snowolf@zlex.org,zlex.snowolf@zlex.org,zlex@zlex.org,snowolf@zlex.org,zlex.snowolf@zlex.org,zlex@zlex.org,snowolf@zlex.org,zlex.snowolf@zlex.org,zlex@zlex.org,snowolf@zlex.org,zlex.snowolf@zlex.org,zlex@zlex.org,snowolf@zlex.org,zlex.snowolf@zlex.org,zlex@zlex.org,snowolf@zlex.org,zlex.snowolf@zlex.org,zlex@zlex.org,snowolf@zlex.org,zlex.snowolf@zlex.org
长度: 529

529字节-->76字节!
GZIP本身不需要太长的内容,经过压缩就能体现出压缩效果,而BZip2则需要压缩很长的内容时,才能体现其压缩效果,这说明BZip2更适合大数据压缩?!

Commons Compress不仅支持BZip2算法实现,同时也支持GZip算法实现。对于GZip算法实现,与Java原生实现基本上没有什么差别。其源代码分析,仅仅是做了简单的包装。
不过有必要提及的一点是,Commons Compress为压缩(GZip和BZip2)构建了压缩算法工厂类 CompressorStreamFactory。通过这个类可以方便的构建GZip和BZip2的输入输出流,关键字分别为“gz”和“bzip2”。
GZip
Java代码
  1. // GzipCompressorInputStream         
  2. CompressorInputStream gzipIn = new CompressorStreamFactory()   
  3.         .createCompressorInputStream("gz", is);   
  4.   
  5. // GzipCompressorOutputStream   
  6. CompressorOutputStream gzipOut = new CompressorStreamFactory()   
  7.         .createCompressorOutputStream("gz", os);  
		// GzipCompressorInputStream      
		CompressorInputStream gzipIn = new CompressorStreamFactory()
				.createCompressorInputStream("gz", is);

		// GzipCompressorOutputStream
		CompressorOutputStream gzipOut = new CompressorStreamFactory()
				.createCompressorOutputStream("gz", os);

BZip2
Java代码
  // BZip2CompressorInputStream   
  1. CompressorInputStream bzip2In = new CompressorStreamFactory()   
  2.         .createCompressorInputStream("bzip2", is);   
  3.   
  4. // BZip2CompressorOutputStream   
  5. CompressorOutputStream bzip2Out = new CompressorStreamFactory()   
  6.         .createCompressorOutputStream("bzip2", os);  
		// BZip2CompressorInputStream
		CompressorInputStream bzip2In = new CompressorStreamFactory()
				.createCompressorInputStream("bzip2", is);

		// BZip2CompressorOutputStream
		CompressorOutputStream bzip2Out = new CompressorStreamFactory()
				.createCompressorOutputStream("bzip2", os);

GZip和BZip2在算法实现步骤上基本上没有什么差别,如果有必要统一,可按上述代码实现!
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值