javaI/O操作之文件的切割合并

来源:互联网 发布:mac安装win8系统网卡 编辑:程序博客网 时间:2024/06/06 13:05

1. 在一些论坛或者贴吧当我们上传较大的文件时,该文件会被切割为若干个碎片文件。同样我们也会下载一些碎片文件,并将其重新连接使用。下面就通过这三个主要的类和接口模仿这一实现功能。

SequenceInputStream 类

SequenceInputStream 表示其他输入流的逻辑串联。它从输入流的有序集合开始,并从第一个输入流开始读取,直到到达文件末尾,接着从第二个输入流读取,依次类推,直到到达包含的最后一个输入流的文件末尾为止。

Properties类

Properties 类表示了一个持久的属性集。Properties 可保存在流中或从流中加载。属性列表中每个键及其对应值都是一个字符串。

接口 FilenameFilter

实现此接口的类实例可用于过滤器文件名。Abstract Window Toolkit 的文件对话框组件使用这些实例过滤 File 类的 list 方法中的目录清单

  1. 实现FilenameFilter接口的类

            import java.io.File;        import java.io.FilenameFilter;        /**         * 1、实现FilenameFilter接口的类         * 2、该类完成对文件后缀名的过滤         * 3、accept()方法测试指定文件是否应该包含在某一文件列表中。         *   当且仅当该名称应该包含在文件列表中时返回 true;否则返回 false。         * @author lucky         *         */        public class SuffixFilter implements FilenameFilter {            String suffix;            public SuffixFilter(String suffix) {                super();                this.suffix = suffix;            }            @Override            public boolean accept(File dir, String name) {                // TODO Auto-generated method stub                return name.endsWith(suffix);            }
  2. 切割 合并文件的主类

            import java.io.File;        import java.io.FileInputStream;        import java.io.FileOutputStream;        import java.io.IOException;        import java.io.SequenceInputStream;        import java.util.ArrayList;        import java.util.Collections;        import java.util.Enumeration;        import java.util.Properties;        public class Split_Merge_File {            private static final int SIZE = 1048576;            public static void main(String[] args) throws IOException {                // TODO Auto-generated method stub                File file = new File("0.mp3");                File dir = new File("file_parts");                //对数据源文件进行切割                //      splitFile(file);                //对碎片文件进行连接                mergeFile(dir);            }            /**             * 1、在完成了对数据切割的基础上 下面来简单介绍一下对碎片文件的连接             *              * 2、对碎片文件进行连接  就是使多个数据源输出到同一个目标文件             *   这里就使用了SequenceInputStream类 来使多个数据源进行逻辑上的串联              *   它从输入流的有序集合开始,并从第一个输入流开始读取,直到到达文件末尾,             *   接着从第二个输入流读取,依次类推,直到到达包含的最后一个输入流的文件末尾为止             *                * 3、另外为了代码的健壮性 添加对文件数量的判断  这里使用的是FilenameFilter接口             *   在类SuffixFilter(该类实现了FilenameFilter接口)中完成了对特定后缀名             *   文件的判断             *                * @param dir             * @throws IOException             */            private static void mergeFile(File dir) throws IOException {                // TODO Auto-generated method stub                //获取配置文件  这里就是要获取切割文件方法中存储的配置文件                //从而获得数据源的参数信息                File[] files = dir.listFiles(new SuffixFilter(".properties"));                //这里是对配置文件的唯一性要求                if (files.length != 1) {                    throw new RuntimeException("配置文件不正确,请重新操作.");                }                File config = files[0];                Properties properties = new Properties();                properties.load(new FileInputStream(config));                //获取源数据的配置信息                String file_name = properties.getProperty("file_name");                int file_count = Integer.parseInt(properties.getProperty("file_count"));                //获取所有的碎片文件                File[] partFiles = dir.listFiles(new SuffixFilter(".part"));                if (partFiles.length != file_count - 1) {                    throw new RuntimeException("碎片文件缺少被破坏,请重新下载源文件.");                }                ArrayList<FileInputStream> arrayList = new ArrayList<FileInputStream>();                for (int i = 0; i < partFiles.length; i++) {                    arrayList.add(new FileInputStream(partFiles[i]));                }                Enumeration<FileInputStream> enumeration = Collections                        .enumeration(arrayList);                //创建SequenceInputStream 对象  使碎片文件逻辑串联                SequenceInputStream SIStream = new SequenceInputStream(enumeration);                //创建输出流对象 使序列流的所有逻辑串联数据源进行输出连接                FileOutputStream FOStream = new FileOutputStream(new File(dir,                        file_name));                int len = 0;                byte[] buf = new byte[1024];                while ((len = SIStream.read(buf)) != -1) {                    FOStream.write(buf, 0, len);                }                //关闭流对象                FOStream.close();                SIStream.close();            }            /**             * 1、我们知道在一些论坛或者贴吧  当上传一些较大的资料文档时 上传的资料会被切割成若干份             *   这里我们设置每份文件大小为1M 模仿文件切割的实现             * 2、文件切割的实现就是按照单位数据的大小对 要操作的文件进行分别输出存储              *    当我们熟练文件的读写操作后这一点很容易实现             * 3、与普通文件写操作不同的是该方法中使用了Properties类的一些方法             *   Properties 类表示了一个持久的属性集。             *   Properties 可保存在流中或从流中加载。属性列表中每个键及其对应值都是一个字符串             * 4、使用Properties类的原因就是不是为了切割文件  而是为了后面对数据的连接操作             *    我们需要源数据的名称 类型 等一些相关参数。             * @param file             * @throws IOException             */            private static void splitFile(File file) throws IOException {                // TODO Auto-generated method stub                // 创建关联数据源的输入流 注意会抛出文件不存在异常                FileInputStream FIStream = new FileInputStream(file);                FileOutputStream FOStream = null;                //创建存放碎片文件的文件夹  如果不存在则创建                File dir = new File("file_parts");                if (!dir.exists()) {                    dir.mkdirs();                }                //创建字节缓冲区  这里暂且使每个文件碎片大小为1M                byte[] buf = new byte[SIZE];                int len = 0;                //变量  用于根据文件的大小进行更新碎片文件的名称                int count = 1;                while ((len = FIStream.read(buf)) != -1) {                    FOStream = new FileOutputStream(new File(dir, (count++) + ".part"));                    FOStream.write(buf, 0, len);                    FOStream.close();                }                //创建Properties对象  使属性集保持持久化                Properties properties = new Properties();                //将被切割文件的信息保存到prop集合中。                properties.setProperty("file_count", count + "");                properties.setProperty("file_name", file.getName());                FOStream = new FileOutputStream(new File(dir, count + ".properties"));                //将prop集合中的数据存储到文件中                properties.store(FOStream, "Informations of file");                FOStream.close();                FIStream.close();            }        }
0 0