java-文件切割合并_对象的序列化
一 文件的操作
1.1 概况
1,切割文件的原理:一个源对应多个目的;切割文件的两种方式。
2,碎片文件的命名和编号。
3,程序代码体现。
4,如何记录源文件的类型以及碎片的个数(建立配置信息文件)(其实也可以将这些信息记录碎片文件中)
5,通过Properties属性集建立配置文件。
常见方法:load(InputStream) load(Reader)
store(OutputStream,conmments),store(Writer,conmments)
6,Properties的作为配置在应用程序很常见,主要用于将配置信息持久化。
建立的配置文件扩展名规范: .properties.
代码 SplitFileTest.java
public static void main(String[] args) throws IOException { /* * 练习:将一个媒体文件切割成多个文件 * 思路: * 1.读取源文件,将源文件的数据分别复制到多个文件中 * 2.切割方式有两种:按照碎片个数切.要么按照指定大小切 * 3.一个输入流对应多个输出流 * 4.每个碎片都需要编号,顺序不要错 * */ // 定义源文件 File srcFile = new File("tempFile//50.avi"); // 定义目标文件 File partDir = new File("tempFile//partFile"); // 切割方法 splitFile(srcFile,partDir); } public static void splitFile(File srcFile, File partDir) throws IOException { //如果提供的源文件不存在,则异常 if(!(srcFile.exists() && srcFile.isFile())){ throw new RuntimeException("源文件不是正确文件或者不存在"); } // 如果提供的目标文件不存在,则创建 if(!(partDir.exists())){ partDir.mkdir(); } // 定义文件编号 int count=1; //源输入流 FileInputStream fis = new FileInputStream(srcFile); // 输出流,由于是多个输出流.因此要定义为空 FileOutputStream fos = null; // 缓存区,定义你要拿多少 byte [] buf = new byte [1024*1024]; int len = 0 ; while((len=fis.read(buf)) != -1){ // 输出流对象 fos = new FileOutputStream(new File(partDir,(count++)+".part")); //写入目标文件 fos.write(buf, 0, len); } }
1.2 加入配置文件
/* * 将源文件以及切割文件的一些信息也保存起来随着碎片文件一起发送 * 信息: * 1.源文件的名称 * 2.切割的碎片的个数 * 将这些信息单独封装到一个文件中 * 还要一个输出流完成此动作 * * */ String filename = srcFile.getName(); int partCount = count; fos = new FileOutputStream(new File(partDir,count+".partconfig")); fos.write(("filename="+filename+line_separator).getBytes() ); fos.write(("filecount="+Integer.toString(count)).getBytes());
1.3 分析配置文件
/* * 配置文件规律,只读一行文本,按照 = 对文本进行分割即可 * * */ BufferedReader buf = new BufferedReader(new FileReader(configFile)); String line = null; while((line = buf.readLine())!=null) { String [] arr = line.split("="); System.out.println(arr[0]+"======"+arr[1]); }
1.4 配置文件存储
Properties的使用 还有其他代码 /* * 将源文件以及切割文件的一些信息也保存起来随着碎片文件一起发送 * 信息: * 1.源文件的名称 * 2.切割的碎片的个数 * 将这些信息单独封装到一个文件中 * 还要一个输出流完成此动作 * * */ String filename = srcFile.getName(); int partCount = count; fos = new FileOutputStream(new File(partDir,count+".properties")); Properties prop = new Properties(); prop.setProperty("filename", srcFile.getName()); prop.setProperty("patcount", Integer.toString(partCount)); prop.store(fos, "part file info");
1.5 合并
恐怖方式
public static void main(String[] args) throws IOException { //合并碎片文件 // 多个源去的一个目的地 FileInputStream fis1 = new FileInputStream("tempFile//partFile//1.part"); FileInputStream fis2 = new FileInputStream("tempFile//partFile//2.part"); FileInputStream fis3 = new FileInputStream("tempFile//partFile//3.part"); FileInputStream fis4 = new FileInputStream("tempFile//partFile//4.part"); FileInputStream fis5 = new FileInputStream("tempFile//partFile//5.part"); FileOutputStream fos = new FileOutputStream("5.avi"); byte [] buf = new byte[1024*1024]; int len1 = fis1.read(buf); fos.write(buf, 0, len1); int len2 = fis2.read(buf); fos.write(buf, 0, len2); int len3 = fis3.read(buf); fos.write(buf, 0, len3); int len4 = fis4.read(buf); fos.write(buf, 0, len4); int len5 = fis5.read(buf); fos.write(buf, 0, len5); fos.close(); fis1.close(); fis2.close(); fis3.close(); fis4.close(); fis5.close(); }
序列流
/* * 如上代码的问题, * 当流对象多时,应该先存储起来,面的流对象的容器操作更容易 * 1.需要容器, * 2.将流对象和文件关联后存储到容器中 * 3.遍历容器获取其中的流对象,在进行频繁的读写操作 * 4.即使关流也是遍历容器对每个流对象进行close的调用 * */ List<FileInputStream> list = new ArrayList<FileInputStream>(); // 读 for (int i = 1; i < 6; i++) { list.add(new FileInputStream("tempFile//partFile//" + i + ".part")); } FileOutputStream fos = new FileOutputStream("5.avi"); // 缓存区 byte[] buf = new byte[1024 * 1024]; // 写入 for (FileInputStream fis : list) { int len = fis.read(buf); fos.write(buf,0,len); } // 关闭流 for (FileInputStream fis : list) { fis.close(); } 对上面代码进行封装,序列流 public static void mergerFile(File partDir) throws IOException { List<FileInputStream> list = new ArrayList<FileInputStream>(); // 读 for (int i = 1; i < 6; i++) { list.add(new FileInputStream("tempFile//partFile//" + i + ".part")); } // 怎么获取枚举对象呢?考虑到collection里面去找找 Enumeration<FileInputStream> en = Collections.enumeration(list); // 序列流 SequenceInputStream sis = new SequenceInputStream(en); // 输出流 FileOutputStream fos = new FileOutputStream("5.avi"); // 缓存区 byte[] buf = new byte[1024]; int len=0 ; while((len = sis.read(buf))!=-1){ fos.write(buf,0,len); System.out.println(11); } fos.close(); sis.close(); }
配置文件的读取
虽然合并成功.但是也有一些问题
- 如何明确碎片的个数,来确定循环的次数,以明确多少个输入流对象
- 如何知道合并的文件的类型,
解决的方案是:应该先读取配置文件.
public static void main(String[] args) throws IOException { File partDir = new File("tempFile//partFile"); // 1.获取配置文件 File configFile = getConfigFile(partDir); System.out.println(configFile); //2.先获取配置文件信息容器,获取配置文件信息的属性集 Properties prop = getProperties(configFile); System.out.println(prop); // 获取属性信息,并传到合并方法里面去 mergerFile(partDir, prop); } // 根据配置文件获取配置文件信息的属性集 private static Properties getProperties(File configFile) throws IOException { FileInputStream fis = null; Properties prop = new Properties(); try { // 读取流和配置文件相关联 fis = new FileInputStream(configFile); // 将流的数据加载到集合中去 prop.load(fis); } finally { if (fis != null) fis.close(); } // 将集合返回 return prop; } // 根据碎片目录获取配置文件对象 private static File getConfigFile(File partDir) { if (!(partDir.isDirectory() && partDir.exists())) { throw new RuntimeException("不是有效的目录"); } // 判断碎片文件目录中是否存在properties文件 // 过滤器 File[] files = partDir.listFiles(new FileFilter() { @Override public boolean accept(File pathname) { return pathname.getName().endsWith(".properties"); } }); if (files.length != 1) { throw new RuntimeException("properties扩展名的文件不存在,或不唯一"); } File configFile = files[0]; return configFile; } // 合并 public static void mergerFile(File partDir , Properties prop) throws IOException { // 获取属性集中的信息 String filename = prop.getProperty("filename"); int partCount = Integer.parseInt(prop.getProperty("patcount")); // 使用io包中的SeqenceInputStream 对碎片文件进行合并,将多个文件合并一个读取流 List<FileInputStream> list = new ArrayList<FileInputStream>(); // 读 for (int i = 1; i < partCount; i++) { list.add(new FileInputStream("tempFile//partFile//" + i + ".part")); } // 怎么获取枚举对象呢?考虑到collection里面去找找 Enumeration<FileInputStream> en = Collections.enumeration(list); // 序列流 SequenceInputStream sis = new SequenceInputStream(en); // 输出流 FileOutputStream fos = new FileOutputStream(filename); // 缓存区 byte[] buf = new byte[1024]; int len = 0; while ((len = sis.read(buf)) != -1) { fos.write(buf, 0, len); } fos.close(); sis.close(); }
1.6 记录程序运行次数
public static void main(String[] args) throws IOException { /* * 练习:定义一个功能程序运行次数,满足试用次数后给出提示,试用次数到了 * 思路: * 1.需要计数器, * 2.需要一个拷久的计数器, * 3.并且给这个计数器取个名字 * 4.properties集合下好满足这个要求 * * */ if (isStop()){ System.out.println("试用次数到了.不能在用了"); return; } runcode(); } private static boolean isStop() throws IOException { // 配置文件 File configFile = new File("tempFile\\app.properties"); if (!(configFile.exists())){ configFile.createNewFile(); } int count = 0; // 创建属性集 Properties prop = new Properties(); // 定义读取流和配置文件关联 FileInputStream fis = new FileInputStream(configFile); prop.load(fis); String value = prop.getProperty("count"); // 对value进行判断,如果存在就对其自增 if(value != null ){ count=Integer.parseInt(value); if(count>5){ return true; } } count++;// 对其值进行自增 // 将处增后的值和指定的键重新存储到属性集中,键相同,值覆盖 prop.setProperty("count", Integer.toString(count)); FileOutputStream fos = new FileOutputStream(configFile); prop.store(fos, "app run count"); fos.close(); fis.close(); return false; } // 程序文体 public static void runcode() { System.out.println("程序运行了::::::play "); }
二 对象
序列化
写 ObjectOutputStream
// 应该先有对象,Person Person p1 = new Person("LISHI",20); // FileOutputStream fos = new FileOutputStream("tempFile\\obj.object"); ObjectOutputStream obs = new ObjectOutputStream(fos); obs.writeObject(p1); obs.close();
反序列化
读 ObjectInputStream
//需求:读取已有的对象文件,并获取对象中的数据。 //通过阅读ObjectOutputStream对象的文档,发现有一个对应的对象ObjectInputStream可以用于读区存储对象的文件 //对象的反序列化。 FileInputStream fis = new FileInputStream("tempfile\\obj.object"); ObjectInputStream ois = new ObjectInputStream(fis); Object obj = ois.readObject(); System.out.println(obj.toString());
注意:
1.一定要在你的类里面加这个private static final long serialVersionUID = 1L
2.对于一个非静态的数据也不想序列化怎么办?需要一个关键字来修饰 transient
作者:8亩田
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接.
本文如对您有帮助,还请多帮 【推荐】 下此文。
如果喜欢我的文章,请关注我的公众号
如果有疑问,请下面留言