希望你已经听说过的 整的黑客 这可以让你把JPG和一个压缩文件纳入一个单一的文件,这是一个有效(或至少可读)的文件为这两种格式。好了,我意识到,由于JPG允许任意的东西结束时,拉链开始时,你能坚持多一格式在那里-在中间。对于这个问题,假设中的数据是任意的二进制数据保证没有冲突与JPG或邮政编的格式(这意味着它并不包含魔法zip头0x04034b50).说明:

0xFFD8 <- start jpg data end -> 0xFFD9 ... ARBITRARY BINARY DATA ... 0x04034b50 <- start zip file ... EOF

我是裁剪是这样的:

猫"mss_1600.jpg"filea fileb filea fileb filea fileb filea fileb filea fileb filea fileb filea fileb filea fileb filea fileb filea fileb filea fileb filea fileb filea fileb"null。字节" "randomzipfile.zip">temp.zip

这将产生一个6,318KB文件。它的 不不 打开在7-Zip。然而,当我的猫少了一个'双重'(而不是13filea和b、12):

猫"mss_1600.jpg"filea fileb filea fileb filea fileb filea fileb filea fileb filea fileb filea fileb filea fileb filea fileb filea fileb filea fileb filea fileb "null。字节""randomzipfile.zip"> 温度。拉链

它产生一个5,996KB文件, 打开在7-Zip。

所以我知道我的意的二进制数据并不具有神奇的拉链文件的标题给搞砸了我们的参考文件 工作jpg+data+邮编非工作jpg+data+邮编 (保存作为导致的浏览器,认为他们的图像,并添加拉链扩展自己).

我想知道它为什么失败了有13个组合,并没有12.奖励点,我需要得到解决,这种莫名其妙。

有帮助吗?

解决方案

实际上这真是两部分答案:)

首先,无论人们怎么说zip文件都不能技术上在文件的末尾逐字显示。中央目录记录的末尾有一个值,表示从当前磁盘的起始位置开始的字节偏移量(如果只有一个.zip文件,则表示当前文件)。现在很多处理器忽略了这一点,虽然Windows的zip文件夹没有,所以你需要更正该值以使其在Windows资源管理器中工作(不是你可能会关心; P)参见 Zip APPNOTE 获取有关文件格式的信息。基本上你可以在十六进制编辑器(或编写一个工具)中找到<!>“;中心目录的起始偏移量相对于起始磁盘号<!>”;值。然后找到第一个<!>“中央文件头签名<!>”; (十六进制504b0102)并将值设置为该偏移量。

现在唉不修复7zip,但这是由于7zip尝试猜测文件格式的方式。基本上它只搜索第一个~4MiB的二进制序列504b0304,如果它没有找到它,则假定它不是Zip并尝试其他存档格式。这显然是为什么添加一个文件会破坏事物,它会超过搜索限制。

现在要修复它你需要做的是将这个十六进制字符串添加到jpeg而不会破坏它。一种方法是在FFD8 JPEG SOI标头之后添加以下十六进制数据FFEF0005504B030400。这会在您的序列中添加一个自定义块并且是正确的,因此jpeg标题应该忽略它。

其他提示

我下载了7-Zip的源代码,并找出导致这种情况发生的原因。

在CPP / 7zip / UI / Common / OpenArchive.cpp中,您将看到以下内容:

// Static-SFX (for Linux) can be big.
const UInt64 kMaxCheckStartPosition = 1 << 22;

这意味着只搜索文件的前4194304个字节的标题。如果在那里找不到,7-Zip认为它是无效文件。

您可以通过将1 << 22更改为1 << 23来加倍该限制。我通过重建7-Zip来测试这种变化,但它确实有效。

编辑:要解决此问题,您可以下载来源,进行上述更改并构建它。我使用VS 2008构建它。打开VS命令提示符,导航到 extracted-source-location \ CPP \ 7zip \ Bundles并输入'nmake'。然后在Alone目录中运行'7za t nonworking.jpg',你会看到'一切都好'。

因此,对于任何其他人发现这个问题,这里的故事:

是的,安迪是真正正确的,为什么7-Zip是失败的文件,但它并不能帮助我的问题,因为我不能完全让人们使用我的版本的7-Zip。

有非常方便的风格分类但是我的解决方案。

  • 首先,增加一个小小的字节字符串的JPG他建议将让7-Zip打开它。然而,它稍微偏离从一个有效的JPG片段,它需要FFEF00 07 504B030400-长度由2个字节。
  • 这可以让7-Zip打开它,但不能提取的文件,它将失败默默。这是因为本条目的中央目录的内部指针/抵消这一点的条目的文件。因为你把一堆东西在这之前,你需要纠正所有这些指针!
  • 有拉链开着Windows建zip支持,需要,因为有非常方便的风格分类说,正确的"偏移的开始的中央目录相对于启动磁盘数字"。这里是蟒蛇脚本做最后的两个,尽管这是一个片段,不copypasta-使用准备好的

#Now we need to read the file and rewrite all the zip headers.  Fun!
torewrite = open(magicfilename, 'rb')
magicdata = torewrite.read()
torewrite.close()

#Change the Central Repository's Offset
offsetOfCentralRepro = magicdata.find('\x50\x4B\x01\x02') #this is the beginning of the central repo
start = len(magicdata) - 6 #it so happens, that on my files, the point is stored 2 bytes from the end.  so datadatadatdaata OF FS ET !! 00 00 EOF where OFFSET!! is the 4 bytes 00 00 are the last two bytes, then EOF
magicdata = magicdata[:start] + pack('I', offsetOfCentralRepro) + magicdata[start+4:]

#Now change the individual offsets in the central directory files
startOfCentralDirectoryEntry = magicdata.find('\x50\x4B\x01\x02', 0) #find the first central directory entry
startOfFileDirectoryEntry = magicdata.find('\x50\x4B\x03\x04', 10) #find the first file entry (we start at 10 because we have to skip past the first fake entry in the jpg)
while startOfCentralDirectoryEntry > 0:
    #Now I move a magic number of bytes past the entry (really! It's 42!)
    startOfCentralDirectoryEntry = startOfCentralDirectoryEntry + 42

    #get the current offset just to output something to the terminal
    (oldoffset,) = unpack('I', magicdata[startOfCentralDirectoryEntry : startOfCentralDirectoryEntry+4])
    print "Old Offset: ", oldoffset, " New Offset: ", startOfFileDirectoryEntry , " at ", startOfCentralDirectoryEntry
    #now replace it
    magicdata = magicdata[:startOfCentralDirectoryEntry] + pack('I', startOfFileDirectoryEntry) + magicdata[startOfCentralDirectoryEntry+4:]

    #now I move to the next central directory entry, and the next file entry
    startOfCentralDirectoryEntry = magicdata.find('\x50\x4B\x01\x02', startOfCentralDirectoryEntry)
    startOfFileDirectoryEntry = magicdata.find('\x50\x4B\x03\x04', startOfFileDirectoryEntry+1)

#Finally write the rewritten headers' data
towrite = open(magicfilename, 'wb')
towrite.write(magicdata)
towrite.close()

您可以使用 DotNetZip 制作混合JPG + ZIP文件。 DotNetZip可以保存到流中,并且它足够智能,可以在开始将zip内容写入其中之前识别预先存在的流的原始偏移。因此,在伪代码中,您可以通过这种方式获得JPG + ZIP:

 open stream on an existing JPG file for update
 seek to the end of that stream
 open or create a zip file
 call ZipFile.Save to write zip content to the JPG stream
 close

正确计算所有偏移量。相同的技术用于生成自解压存档。您可以在EXE上打开流,然后搜索到最后,并将ZIP内容写入该流。如果以这种方式执行,则可以正确计算所有偏移量。

另一件事 - 关于另一篇文章中的一条评论...... ZIP可以在文件末尾的开头有任意数据。据我所知,zip中心目录需要位于文件的末尾,尽管这是典型的。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top