這篇文章介紹了
Net實現合並文件的具體方法
有需要的朋友可以參考一下
以上列表中的文件並不是來自於某個文件夾中的所有jpg文件而是來自於
這個文件
將多個文件合並為一個文件在許多應用領域都十分有用親自實現這樣一個程序一定不但過瘾且在許多時候可以幫助我們構建更高效的程序這裡我做了一個方案例分享給大家
由於合並後的文件就像一個包裹所以下文中都把這樣的文件稱為“包文件”
主構思
要把多個文件合並成一個包文件還要可以區分其中的某個文件並提取出來我們需要知道文件的名稱和這個文件在包文件中的位置及長度也就是所謂的地址偏移
由於包文件常常會比較大所以不應該讓它的內容常駐於內存只應該需要某部分的時候再從包文件中提取
我是這樣做的
一個管理器類提供一些外圍的方法
_pathList用於存放要添加到包文件的文件路徑通過調用AddSourceFile()方法添加
_pf 是具體的包文件通過LoadPackFile() 生成實例通過CurrentPackFile屬性返回
Build方法用於生成包文件
PackFile類作為PackFileManager的嵌套類它提供包文件的屬性和施工細節
好了我們先來看看PackFileManagerBuild()方法
復制代碼 代碼如下:
public void Build(string path)
{
using (FileStream fs = new FileStream(path
FileMode
Create
FileAccess
Write))
{
BinaryWriter bw = new BinaryWriter(fs);
bw
Write("PackFile");
bw
Write(this
_pathList
Count);
foreach (string f in this
_pathList)
{
FileInfo fi = new FileInfo(f);
bw
Write(fi
Length);
fi = null;
}
foreach (string f in this
_pathList)
{
bw
Write(Path
GetFileName(f));
}
foreach (string f in this
_pathList)
{
bw
Write(File
ReadAllBytes(f));
bw
Flush();
}
}
}
. 先寫個“PackFile”字符串到文件頭
. 把以Int為類型的要輸出到包文件中的文件數量寫入
. 把以long為類型的要輸出到包文件中的每個文件的長度寫入
. 再把每個文件名寫入
. 最後寫入每個文件的實體內容
由於在寫或讀時不頻繁在Write方法或ReadXXX方法的不同版本間頻繁切換所以我想這樣組織文件結構可以更高效一些
疑問來了在寫入文件名的時候我們使用bwWrite(PathGetFileName(f));
調用了 BinaryWriterWrite(string value)傳入的是字符串那麼在讀取的時候要調用BinaryReaderReadString()這時它是如何區分兩個字符串邊界的還 好Write方法會先將字符串長度作為一個四字節無符號整數寫入於是在用BinaryReaderReadString()的時候它會根據這個值來 讀取特定長度的值並理解為字符串
這裡列出幾個重要方法
復制代碼 代碼如下:
PackFileManager的LoadPackFile方法
public void LoadPackFile(string path)
{
if (!File
Exists(path))
{
throw new FileNotFoundException(path);
}
if (_pf != null)
{
_pf
Close();
_pf = null;
}
FileStream fs = new FileStream(path
FileMode
Open
FileAccess
Read);
BinaryReader br = new BinaryReader(fs);
if (br
ReadString() != "PackFile")
{
throw new InvalidCoalescentFileException("該文件不是有效的包文件");
}
this
_pf = new PackFile(fs
br);
}
此時我們在生成時寫入的字符串"PackFile" 就有了明確的功能
PackFile的構造函數
復制代碼 代碼如下:
internal PackFile(FileStream srcFile
BinaryReader br)
{
this
_sourceFile = srcFile;
_br = br;
this
_fileCount = _br
ReadInt
();//取文件數
for (int i =
; i <= _fileCount; i++)
{
this
_fileLengthList
Add(_br
ReadInt
());
}
for (int i =
; i <= _fileCount; i++)
{
this
_shortNameList
Add(_br
ReadString());
}
this
_contentStartPos = _sourceFile
Position;//設置實體文件總起始位置
}
PackFileGetBytes()
復制代碼 代碼如下:
public byte[] GetBytes(int index)
{
long startPos = this
_contentStartPos;
for (int i =
; i < index; i++)
{
startPos += this
_fileLengthList[i];
}
_sourceFile
Position = startPos; //設置某文件內容的起始位置
return _br
ReadBytes((int)_fileLengthList[index]);
}
這只是一個草案我們還可以加入壓縮或是像ZIP文件那樣的嵌套文件夾功能改進後的代碼別忘與我分享哦
From:http://tw.wingwit.com/Article/program/net/201311/14444.html