【发布时间】:2011-02-03 20:16:00
【问题描述】:
在 Windows 上的 .NET 中,我尝试了几个开源 tar 库来编写 tar 存档(直接从内存中,输入文件实际上从未存在)。
它们生成的 tar 文件可以由 tar 库解析和提取,但 7zip 等程序报告 tar 是一个错误。 Unix 上的 gtar 也会抛出错误。
我在错误消息中没有得到任何具体的反馈,所以我不知道出了什么问题。
我曾尝试使用维基百科上的 tar 规范直接编写 tar 文件:http://en.wikipedia.org/wiki/Tar_(file_format),但这会产生相同的情况。
有没有人知道一个可以验证并具体告诉我我正在生成的 tar 文件有什么问题的好工具?
这是我编写存档的自定义代码。在存档的末尾,我写了 2 512 个长度的 nul 块作为终止符。请注意,此代码会生成一个存档,该存档可以使用此开源库进行精细提取:http://www.icsharpcode.net/opensource/sharpziplib/ 但就像我说的,它对 unix 上的 7zip 和 gtar 似乎无效。
public static void WriteTarEntry(string filename, byte[] data, Stream outputStream)
{
WriteTarEntryHeader(filename, data.Length, outputStream);
WriteTarEntryData(data, outputStream);
}
static void WriteTarEntryHeader(string fileName, int fileSize, Stream outputStream)
{
var header = new byte[512];
WriteStringToByteArray(fileName, header, 0, 100);
WriteStringToByteArray(fileSize.ToString(), header, 124, 12);
var unixTime = Convert.ToInt64((DateTime.Now - new DateTime(1970, 1, 1)).TotalSeconds).ToString();
WriteStringToByteArray(unixTime, header, 136, 12);
WriteStringToByteArray("0", header, 156, 1);
WriteStringToByteArray("ustar ", header, 257, 6);
WriteStringToByteArray(" ", header, 263, 2);
WriteStringToByteArray(Environment.UserName, header, 265, 32);
WriteStringToByteArray(Environment.UserDomainName, header, 297, 32);
WriteStringToByteArray(" ", header, 148, 8);
var checksum = Convert.ToString(header.Sum(b => b), 8).PadLeft(6, Char.Parse("0"));
WriteStringToByteArray(checksum, header, 148, 6);
header[148 + 6] = 0;
header[148 + 7] = 32;
outputStream.Write(header, 0, header.Length);
}
static void WriteStringToByteArray(string value, byte[] array, int start, int maxWidth)
{
var len = Math.Min(maxWidth, value.Length);
var sourceBytes = Encoding.ASCII.GetBytes(value);
Buffer.BlockCopy(sourceBytes, 0, array, start, len);
}
static void WriteTarEntryData(byte[] data, Stream outputStream)
{
int totalBytes = 0;
while (totalBytes < data.Length)
{
totalBytes += 512;
}
var alldata = new byte[totalBytes];
Buffer.BlockCopy(data, 0, alldata, 0, data.Length);
outputStream.Write(alldata, 0, alldata.Length);
}
【问题讨论】:
-
您使用的是哪些开源库?您可以发布一些您尝试过的示例代码吗?
-
我会小心地将
char转换为byte;使用Encoding.ASCII将字符串转换为字节。 -
我相信 GNU tar(可能还有其他人)对原始格式使用了一些扩展,这样 GNU tar 可以读取原始创建的所有文件,但原始可能无法读取创建的文件由 GNU 焦油。我不知道这是否有帮助,但这是一个数据点。
-
好的有道理。我会尝试一下。虽然我事先将 char 数据编码为 ASCII...
-
对 WriteStringToByteArray 进行了更改以使用 ASCII 编码。没有不同。我没有写任何 uid groupid,所以我想知道这是否是一个问题。我会玩 - 如果有人想到其他任何事情,请告诉我 - 谢谢!