黑馬程序員-探究字節流四(應用文件切割合併)

------- <a  target="blank">android培訓</a>、<a  target="blank">java培訓</a>、期待與您交流! -------

package it.heima.mylog;


import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FilenameFilter;
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 FileSpliter {
/*
* 關鍵詞:文件切割器+配置文件

* ObjectOutputStream&&ObjectInputStream對象的序列化和反序列化,Serializable序列化標記接口
*/

/* 文件切割器 */

private static File file;
private static File dir;

public static void main(String[] args) {
file = new File("c:\\1.mp3");
dir = new File("c:\\partfiles");
try {
splitFile(file);
mergeFile(dir);
} catch (IOException e) {
e.printStackTrace();
}
}

// 切割==================================
private static void splitFile(File file) throws IOException {
// 首先要讀取流關聯一個源文件啊
FileInputStream fis = new FileInputStream(file);
// 定義一個1M的緩衝區
byte[] buf = new byte[1024*1024];
// 創建目的地,因爲是切割文件,所以目的地肯定不是一個,不唯一
FileOutputStream fos = null;
int len = 0;
int count = 1;
/*
* 切割文件時,必須記錄住被切割的文件名,以及切割出來的碎片文件的個數,以便於合併。
* 爲了記住這個信息,可以使用鍵值對的形式存儲在配置文件中。用到了Properties對象。
*/
Properties prop = new Properties();

// 健壯性判斷,如果沒有這個目錄就創建
if (!dir.exists())
dir.mkdir();
while ((len = fis.read(buf)) != -1) {
fos = new FileOutputStream(new File(dir, (count++) + ".part"));
// 開始寫數據啦
fos.write(buf, 0, len);
fos.close();
}

// 將被切割文件的信息保存到prop集合中
prop.setProperty("partcount", count + "");
prop.setProperty("filename", file.getName());

fos = new FileOutputStream(new File(dir, count + ".properties"));

// 將prop集合中的數據存儲到文件中來
prop.store(fos, "save file info");
fos.close();
fis.close();
}

// 合併============================================


private static void mergeFile(File dir) throws IOException {

// 合併文件首先到獲取目錄下的配置文件
File[] files = dir.listFiles(new SuffixFilter(".properties"));
if (files.length != 1)
throw new RuntimeException(dir + ",該目錄下沒有properties擴展名文件或不唯一");

// 記錄配置文件對象
File confile = files[0];

// 獲取該文件中的信息
Properties prop = new Properties();
FileInputStream fis = new FileInputStream(confile);
prop.load(fis);
String filename = prop.getProperty("filename");
int count = Integer.parseInt(prop.getProperty("partcount"));

// 獲取該目錄下的所有碎片文件
File[] partFiles = dir.listFiles(new SuffixFilter(".part"));
if (partFiles.length != (count - 1)) {
throw new RuntimeException("碎片文件不符合要求");
}

// 將碎片文件和流對象關聯,並存儲到集合中
ArrayList<FileInputStream> al = new ArrayList<FileInputStream>();
for (int x = 0; x < partFiles.length; x++) {
al.add(new FileInputStream(partFiles[x]));
}

// 將多個流合併成一個序列流
Enumeration<FileInputStream> en = Collections.enumeration(al);
SequenceInputStream sis = new SequenceInputStream(en);
FileOutputStream fos = new FileOutputStream(new File(dir, filename));
byte[] buf = new byte[1024];

int len = 0;
while ((len = sis.read(buf)) != -1) {
fos.write(buf, 0, len);
}

fos.close();
sis.close();

}

/*
* 序列化和反序列化 ObjectOutputStream ObjectInputStream
* 序列化的過程就是講對象的生命週期延長了,有些不想經常new的對象可以通過序列化將對象從 堆內存存儲到硬盤中來。
* 存儲在銀盤上的文件一般後綴名用object表示。 文件不可以用txt解析,因爲不是給用戶看的,只是一個存儲對象信息的數據文件。
* 序列化的對象要實現Serializable接口,Serializable就是一個標記接口,通常要設置一個國定有一個ID。 就這。
*/
}

// 文件過濾器=========================
class SuffixFilter implements FilenameFilter {

private String suffix;

public SuffixFilter(String suffix) {
super();
this.suffix = suffix;
}

public boolean accept(File dir, String name) {
return name.endsWith(suffix);
}

}

------- <a  target="blank">android培訓</a>、<a  target="blank">java培訓</a>、期待與您交流! -------

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章