学习Java小结-3

来源:互联网 发布:软件机器人 编辑:程序博客网 时间:2024/06/05 15:32

学习Java也有近一个月了,基础语法、常用类也有所了解。上周把文件相关操作进行了一个总结,制作了一个简单的文件常用操作的工具类。

此处详解文件的打包与解包

工具类包含了容下功能的实现:
1、 拷贝文件
2、 移动文件
3、 遍历文件夹
4、 获取文件夹内所有文件
5、 文件打包与解包

5-1 文件的打包

思路:要将文件进行打包,首先需要拿到文件当中的所有文件对象,然后将所有的文件安装一定的组织关系存入一个文件当中。
既然是打包,那么就应该有一个打包后的文件类型,在这里我将包文件类型定义为pakge类型的文件

public static String PACKAGE_TYPE = ".pakge";

在上面已经实现了获取文件中的所有文件,现在需要将所有的文件存入一个文件当中。这个就简单了,只需要遍历获取了所有的文件对象的List集合对象,将每一个文件依次写入一个文件当中即可。

    /**     * 打包一个文件(夹)     * @param srcDir 要打包的目标文件(夹)绝对路径字符串     * @param dir 打包文件的存贮绝对路径字符串     * @return boolean TRUE表示成功打包     */    public static boolean packageFile(String srcDir, String dir) {        //创建文件对象        File srcFile = new File(srcDir);        File destFile = new File(dir + PACKAGE_TYPE);        //通过文件对象获取源文件的绝对路径,避免参数字符差异        String srcFilePath = srcFile.getAbsolutePath();        //如果源文件存在,则进行打包操作        if (srcFile.exists()) {            //通过已有方法获取所有文件            ArrayList<File> fileList = new ArrayList<File>();            FileControls.getAllFiles(srcFilePath, fileList);            try {                //以追加方式创建文件输出流,绑定打包文件                FileOutputStream fs = new FileOutputStream(destFile, true);                for (Filef : fileList) {                    if (!f.getFilePath().isDirectory()) {                        FileInputStream fi = new FileInputStream(f.getFilePath());                        //创建缓冲字节数组                        byte[] buffer = new byte[4096];                        //获取当前文件总长(字节数)                        long size = f.length();                        while (true) {                            //如果未写入的字节数比缓冲数组长,则读取并写入4096字节                         if (size > 4096) {                                fi.read(buffer);                                fs.write(buffer);                                //未写入字节数减少4096                                size -= 4096;                            } else {                            //读取并写入剩余字节,关闭输入流                                fi.read(buffer, 0, (int) size);                                fs.write(buffer, 0, (int) size);                                fi.close();                                break;                            }                        }                    }                }                //刷新输出流,关闭输出流                fs.flush();                fs.close();                return true;            } catch (IOException e) {                e.printStackTrace();            }        } else {            System.out.println("源文件\"" + srcFile.getAbsolutePath() + "\"不存在");        }        return false;    }

这里可以看到,打包功能已经完成。接下来看解包的实现。

5-2 文件的解包

思路:在这里突然发现,上面实现的打包功能无法解包。为啥呢?因为包中的文件名、文件大小信息均没有进行保留。因此需要对上面的打包功能进行优化。在打包的时候要将文件名、文件大小写入到打包文件中。这样在解包的时候才可以将包文件中的文件正常的完整的解包出来。
因此,增加了一个功能类Filesize

    public static class Filesize implements Serializable {        private static final long serialVersionUID = -1035346214239079079L;        private File filePath;        private long fileSize;        public File getFilePath() {            return filePath;        }        public long getFileSize() {            return fileSize;        }        public void setFilePath(String filePath) {            this.filePath = new File(filePath);            this.fileSize = this.filePath.length();        }    }

该功能类Filesize有两个属性:1、文件对象。2、文件对象的大小。另外可以看到该功能类实现了Serializable接口,这是为了能够该类对象能够序列化到文件中。以便于将文件的名称、大小的信息保存下来。
因为要将文件信息保存到该功能类中,因此重载获取所有文件对象的方法。重载时发现,目录文件不需要进行获取

    public static void getAllFiles(String srcPath, ArrayList<FileControls.Filesize> files) {        File file = new File(srcPath);        if (file.exists()) {            File[] fileList = file.listFiles();            if (fileList != null && fileList.length > 0) {                for (File src : fileList) {                    getAllFiles(src.getAbsolutePath(), files);                }            }            if (!file.isDirectory()) {                //构建功能类对象                FileControls.Filesize fileSize = new FileControls.Filesize();                fileSize.setFilePath(file.getAbsolutePath());                files.add(fileSize);            }        }    }

打包方法优化后的代码如下

    /**     * 对打包文件进行解包,默认解包路径为打包文件同级路径,解包的后的文件对象的父目录为     * 包文件父目录/包文件名     *     * @param packageFilePath 包文件绝对路径字符串     * @return 成功解包则返回TRUE     */    public static boolean upPackges(String packageFilePath) {        File packageFile = new File(packageFilePath);        FileInputStream fin = null;        ObjectInputStream oin = null;        if (packageFile.exists()) {            try {                fin = new FileInputStream(packageFile);                oin = new ObjectInputStream(fin);                ArrayList<FileControls.Filesize> list = new ArrayList<FileControls.Filesize>();                //反序列化出文件详细信息集合对象                //如果强转失败,则会抛出ClassCastException异常,说明这不是一个大包文件                list = (ArrayList<FileControls.Filesize>) oin.readObject();                if (list.size() != 0) {                    for (int i = 0; i < list.size(); i++) {                        File file = list.get(i).getFilePath();                        //如果该文件是目录,则直接创建目录                        if (!file.isDirectory()) {                            //构建包文件的绝对路径字符串                            String dir = packageFile.getParent() + "\\" + file.getName();                            //创建解包文件                            File destfile = new File(dir);                            //创建父级目录                            destfile.getParentFile().mkdirs();                            FileOutputStream fout = new FileOutputStream(destfile);                            //获取文件大小                            long filesize = list.get(i).getFileSize();                            //通过缓冲法将文件类容读取并写入解包的对应文件中                            byte[] buffer = new byte[4096];                            while (true && filesize > 0) {                                if (filesize > 4096) {                                    fin.read(buffer);                                    fout.write(buffer);                                    filesize -= 4096;                                } else {                                    fin.read(buffer, 0, (int) filesize);                                    fout.write(buffer, 0, (int) filesize);                                    break;                                }                            }                            fout.flush();                            fout.close();                        } else {                            file.mkdirs();                        }                    }                    //关闭输入流                    oin.close();                    return true;                }            } catch (ClassCastException ce) {                System.out.println("这不是一个包文件");                try {                    oin.close();                    fin.close();                } catch (IOException e) {                    e.printStackTrace();                }            } catch (Exception e) {                e.printStackTrace();            }        }        return false;    }

到这里,所以的功能已经完整的实现。代码已经上传到GitHub中,这是GitHub的链接

原创粉丝点击