Android 打造自己的个性化应用(五):仿墨迹天气实现续--> 使用Ant实现zip/tar的压缩与解压

时间:2023-03-08 20:04:16
Android 打造自己的个性化应用(五):仿墨迹天气实现续--> 使用Ant实现zip/tar的压缩与解压

上一篇中提到对于Zip包的解压和压缩需要借助Ant 实现,我经过参考了其他的资料,整理后并加上了一些自己的看法:

这里就具体地讲下如何使用Ant进行解压缩及其原因:

java中实际是提供了对  zip等压缩格式的支持,但是为什么这里会用到ant呢?

 

原因主要有两个

1. java提供的类对于包括有中文字符的路径,文件名支持不够好,你用其它第三方软件解压的时候就会存在乱码。而ant.jar就支持文件名或者路径包括中文字符。

2. ant.jar提供了强大的工具类,更加方便于我们对压缩与解压的操作。

注意事项:

1. 首先说明一下,关于皮肤或者类似于皮肤的Zip包,实际上公司可能会根据自己的规定或需求,自定义压缩包文件的结尾,实际上大多还是Zip包的格式. 具体部分的处理大致上是一样的,因此不再复述, 本文给出的例子已经有Zip包和Tar包的解压缩.

2. 还有要注意的是,此处为提升理解,因此加入zip/tar压缩,解压的界面,实际应用中此部分无需单独的界面展示(解压缩需要一定时间的话,则为加强用户体验,加入提示框与进度条),请自行编写解压缩管理类进行逻辑判断分别处理.

3. 测试时需要讲要解压缩的包导入sdcard目录下(若为其他目录,请修改代码中路径)

首先看一下工程目录:

Android 打造自己的个性化应用(五):仿墨迹天气实现续--> 使用Ant实现zip/tar的压缩与解压

程序主界面及解压缩的界面:

Android 打造自己的个性化应用(五):仿墨迹天气实现续--> 使用Ant实现zip/tar的压缩与解压Android 打造自己的个性化应用(五):仿墨迹天气实现续--> 使用Ant实现zip/tar的压缩与解压

接下来是解压缩核心的代码:

布局文件: antzip.xml:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:layout_width="fill_parent"
  4. android:layout_height="fill_parent">
  5. <LinearLayout
  6. android:orientation="vertical" android:layout_width="fill_parent"
  7. android:layout_height="wrap_content"
  8. android:gravity="center"
  9. android:padding="20dip"
  10. android:layout_centerInParent="true">
  11. <RadioGroup
  12. android:layout_width="wrap_content"
  13. android:layout_height="wrap_content"
  14. android:orientation="horizontal">
  15. <RadioButton android:layout_width="wrap_content"
  16. android:layout_height="wrap_content"
  17. android:id="@+id/radioZip"
  18. android:checked="true"
  19. android:text="ZIP"/>
  20. <RadioButton android:layout_width="wrap_content"
  21. android:layout_height="wrap_content"
  22. android:id="@+id/radioTar"
  23. android:text="TAR"
  24. android:layout_marginLeft="10dip"/>
  25. </RadioGroup>
  26. <Button android:text="压缩" android:id="@+id/button1"
  27. android:layout_width="fill_parent" android:layout_height="wrap_content"
  28. android:paddingLeft="30dip" android:paddingRight="30dip"></Button>
  29. <Button android:text="解压" android:id="@+id/button2"
  30. android:layout_width="fill_parent" android:layout_height="wrap_content"
  31. android:paddingLeft="30dip" android:paddingRight="30dip"
  32. android:layout_marginTop="20dip"></Button>
  33. </LinearLayout>
  34. </RelativeLayout>

AntZipActivity:

  1. public class AntZipActivity extends Activity {
  2. public static final String  TYPE = "type";
  3. public static final int     TYPE_ZIP = -1;
  4. public static final int     TYPE_TAR = 1;
  5. public static final String  SUFFIX_ZIP = ".zip";
  6. public static final String  SUFFIX_TAR = ".tar";
  7. /** Called when the activity is first created. */
  8. private Button      btnDoCompress;
  9. private Button      btnDecompress;
  10. private RadioButton radioZip;
  11. private RadioButton radioTar;
  12. private boolean isZip = true;
  13. @Override
  14. public void onCreate(Bundle savedInstanceState) {
  15. super.onCreate(savedInstanceState);
  16. setContentView(R.layout.antzip);
  17. radioZip = (RadioButton)findViewById(R.id.radioZip);
  18. isZip = true;
  19. radioZip.setChecked(true);
  20. radioZip.setOnCheckedChangeListener(new OnCheckedChangeListener() {
  21. @Override
  22. public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
  23. System.out.println("radioZip:"+isChecked);
  24. if(isChecked)
  25. {
  26. isZip = true;
  27. }
  28. }
  29. });
  30. radioTar = (RadioButton)findViewById(R.id.radioTar);
  31. radioTar.setOnCheckedChangeListener(new OnCheckedChangeListener() {
  32. @Override
  33. public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
  34. System.out.println("radioTar:"+isChecked);
  35. if(isChecked)
  36. {
  37. isZip = false;
  38. }
  39. }
  40. });
  41. btnDoCompress = (Button)findViewById(R.id.button1);
  42. btnDoCompress.setOnClickListener(new OnClickListener() {
  43. @Override
  44. public void onClick(View v) {
  45. //进入压缩界面 
  46. Intent i = new Intent(AntZipActivity.this,DozipActivity.class);
  47. i.putExtra(TYPE, isZip?TYPE_ZIP:TYPE_TAR);
  48. AntZipActivity.this.startActivity(i);
  49. }
  50. });
  51. btnDecompress = (Button)findViewById(R.id.button2);
  52. btnDecompress.setOnClickListener(new OnClickListener() {
  53. @Override
  54. public void onClick(View v) {
  55. //进入解压界面 
  56. Intent i = new Intent(AntZipActivity.this,UnzipActivity.class);
  57. i.putExtra(TYPE, isZip?TYPE_ZIP:TYPE_TAR);
  58. AntZipActivity.this.startActivity(i);
  59. }
  60. });
  61. }
  62. }

DozipActivity:

  1. public class DozipActivity extends Activity implements OnClickListener{
  2. private EditText etPath;
  3. private EditText etDest;
  4. private Button  btnDozip;
  5. private TextView    tvTip;
  6. private String  srcPath;
  7. private String  zipDest;
  8. private int     type;
  9. private String  suffix;
  10. @Override
  11. public void onCreate(Bundle savedInstanceState) {
  12. super.onCreate(savedInstanceState);
  13. setTitle("Ant-压缩");
  14. type = getIntent().getIntExtra(AntZipActivity.TYPE, AntZipActivity.TYPE_ZIP);
  15. suffix = type==AntZipActivity.TYPE_ZIP ? AntZipActivity.SUFFIX_ZIP:AntZipActivity.SUFFIX_TAR;
  16. setContentView(R.layout.dozip);
  17. //
  18. etPath = (EditText)findViewById(R.id.editText1);
  19. etDest = (EditText)findViewById(R.id.editText2);
  20. //设置一些默认的函数
  21. etPath.setText("/sdcard/antzip");
  22. etDest.setText("/sdcard/antzip"+suffix);
  23. btnDozip = (Button)findViewById(R.id.button);
  24. tvTip   = (TextView)findViewById(R.id.tv_tip);
  25. btnDozip.setOnClickListener(this);
  26. }
  27. @Override
  28. public void onClick(View v) {
  29. srcPath = etPath.getEditableText().toString();
  30. if(TextUtils.isEmpty(srcPath))
  31. {
  32. Toast.makeText(this, "请指定一个路径", Toast.LENGTH_SHORT).show();
  33. return;
  34. }
  35. File srcFile = new File(srcPath);
  36. if(!srcFile.exists())
  37. {
  38. Toast.makeText(this, "指定的压缩包不存在", Toast.LENGTH_SHORT).show();
  39. return;
  40. }
  41. zipDest = etDest.getEditableText().toString();
  42. if(TextUtils.isEmpty(zipDest))
  43. {
  44. //如果用户没有输入目标文件,则生成一个默认的
  45. zipDest = srcFile.getParent();
  46. }
  47. System.out.println("zip name:"+zipDest);
  48. //如果是以/结尾的,则证明用户输入的是一个目录 ,需要在后面加上文件名
  49. if(zipDest.endsWith(File.separator))
  50. {
  51. zipDest+=srcFile.getName()+suffix;
  52. }
  53. else
  54. {
  55. //如果压缩文件名不是以zip/tar结尾,则加上后缀后
  56. if(!zipDest.endsWith(suffix))
  57. {
  58. zipDest +=suffix;
  59. }
  60. }
  61. //如果用户选择的是zip,则用 zipUtil进行压缩
  62. if(type == AntZipActivity.TYPE_ZIP)
  63. {
  64. ZipUtil zipp = new ZipUtil();
  65. zipp.doZip(srcPath, zipDest);
  66. }
  67. //如果用户选择的是tar,则用 tarUtil进行压缩
  68. else
  69. {
  70. TarUtil tarr = new TarUtil();
  71. tarr.doTar(srcPath, zipDest);
  72. }
  73. //压缩完成后还是提示用户
  74. tvTip.setText("压缩文件路径:"+zipDest);
  75. Toast.makeText(this, "压缩完成", Toast.LENGTH_SHORT).show();
  76. }
  77. }

解压缩工具类ZipUtil:

    1. public class ZipUtil {
    2. private ZipFile         zipFile;
    3. private ZipOutputStream zipOut;     //压缩Zip
    4. private  int            bufSize;    //size of bytes
    5. private byte[]          buf;
    6. public ZipUtil(){
    7. //要构造函数中去初始化我们的缓冲区
    8. this.bufSize = 1024*4;
    9. this.buf = new byte[this.bufSize];
    10. }
    11. /**
    12. * 对传入的目录或者是文件进行压缩
    13. * @param srcFile  需要 压缩的目录或者文件
    14. * @param destFile 压缩文件的路径
    15. */
    16. public void doZip(String srcFile, String destFile) {// zipDirectoryPath:需要压缩的文件夹名
    17. File zipFile = new File(srcFile);
    18. try {
    19. //生成ZipOutputStream,会把压缩的内容全都通过这个输出流输出,最后写到压缩文件中去
    20. this.zipOut = new ZipOutputStream(new BufferedOutputStream(
    21. new FileOutputStream(destFile)));
    22. //设置压缩的注释
    23. zipOut.setComment("comment");
    24. //设置压缩的编码,如果要压缩的路径中有中文,就用下面的编码
    25. zipOut.setEncoding("GBK");
    26. //启用压缩
    27. zipOut.setMethod(ZipOutputStream.DEFLATED);
    28. //压缩级别为最强压缩,但时间要花得多一点
    29. zipOut.setLevel(Deflater.BEST_COMPRESSION);
    30. handleFile(zipFile, this.zipOut,"");
    31. //处理完成后关闭我们的输出流
    32. this.zipOut.close();
    33. } catch (IOException ioe) {
    34. ioe.printStackTrace();
    35. }
    36. }
    37. /**
    38. *  由doZip调用,递归完成目录文件读取
    39. * @param zipFile
    40. * @param zipOut
    41. * @param dirName  这个主要是用来记录压缩文件的一个目录层次结构的
    42. * @throws IOException
    43. */
    44. private void handleFile(File zipFile, ZipOutputStream zipOut,String dirName) throws IOException {
    45. System.out.println("遍历文件:"+zipFile.getName());
    46. //如果是一个目录,则遍历
    47. if(zipFile.isDirectory())
    48. {
    49. File[] files = zipFile.listFiles();
    50. if (files.length == 0) {// 如果目录为空,则单独创建之.
    51. //只是放入了空目录的名字
    52. this.zipOut.putNextEntry(new ZipEntry(dirName+zipFile.getName()+File.separator));
    53. this.zipOut.closeEntry();
    54. } else {// 如果目录不为空,则进入递归,处理下一级文件
    55. for (File file : files) {
    56. // 进入递归,处理下一级的文件
    57. handleFile(file, zipOut, dirName+zipFile.getName()+File.separator);
    58. }
    59. }
    60. }
    61. //如果是文件,则直接压缩
    62. else
    63. {
    64. FileInputStream fileIn  = new FileInputStream(zipFile);
    65. //放入一个ZipEntry
    66. this.zipOut.putNextEntry(new ZipEntry(dirName+zipFile.getName()));
    67. int length = 0;
    68. //放入压缩文件的流
    69. while ((length = fileIn.read(this.buf)) > 0) {
    70. this.zipOut.write(this.buf, 0, length);
    71. }
    72. //关闭ZipEntry,完成一个文件的压缩
    73. this.zipOut.closeEntry();
    74. }
    75. }
    76. /**
    77. * 解压指定zip文件
    78. * @param unZipfile 压缩文件的路径
    79. * @param destFile   解压到的目录 
    80. */
    81. public void unZip(String unZipfile, String destFile) {// unZipfileName需要解压的zip文件名
    82. FileOutputStream fileOut;
    83. File file;
    84. InputStream inputStream;
    85. try {
    86. //生成一个zip的文件
    87. this.zipFile = new ZipFile(unZipfile);
    88. //遍历zipFile中所有的实体,并把他们解压出来
    89. for (@SuppressWarnings("unchecked")
    90. Enumeration<ZipEntry> entries = this.zipFile.getEntries(); entries
    91. .hasMoreElements();) {
    92. ZipEntry entry =  entries.nextElement();
    93. //生成他们解压后的一个文件
    94. file = new File(destFile+File.separator+entry.getName());
    95. if (entry.isDirectory()) {
    96. file.mkdirs();
    97. } else {
    98. // 如果指定文件的目录不存在,则创建之.
    99. File parent = file.getParentFile();
    100. if (!parent.exists()) {
    101. parent.mkdirs();
    102. }
    103. //获取出该压缩实体的输入流
    104. inputStream = zipFile.getInputStream(entry);
    105. fileOut = new FileOutputStream(file);
    106. int length = 0;
    107. //将实体写到本地文件中去
    108. while ((length = inputStream.read(this.buf)) > 0) {
    109. fileOut.write(this.buf, 0, length);
    110. }
    111. fileOut.close();
    112. inputStream.close();
    113. }
    114. }
    115. this.zipFile.close();
    116. } catch (IOException ioe) {
    117. ioe.printStackTrace();
    118. }
    119. }
    120. }