无法从 Android 上创建的 ZIP 存档中提取文件(特定于设备/操作系统)

2023-12-10

我正在 Android 上使用如下代码创建存档:

    OutputStream os = new FileOutputStream(zipFile);
    ZipOutputStream zos = new ZipOutputStream(new BufferedOutputStream(os));
    try 
    {
        zos.setLevel(8);
        byte[] buffer = new byte[32768];
        for (VFile src : toPack)            
        {
            ZipEntry entry = new ZipEntry(src.name);
            zos.putNextEntry(entry);
            src.pushToStream(zos, buffer);
            src.close();
            zos.closeEntry();
        }
    }
    finally 
    {
        zos.close();
    }       

我发现只有一种压缩方法可用 -DEFLATED(只有STORED可用替代方案)。这意味着存档始终使用一种方法进行压缩。

如果我在 Android 2.3.4 上运行此代码 - 我可以使用 7Zip 在 Windows 中解压缩文件;如果我在 Android 3(或 Samsung Galaxy Tab;不确定是谁弄错了)上运行此程序 - 7Zip 显示存档列表,但无法解压缩文件并显示不支持的压缩方法。同时7Zip显示Deflate作为文件的压缩方法,这意味着它可以正确处理它。

有人遇到这个问题吗?

Thanks.

UDP:找到另一个具有类似问题的主题(但可能不一样)。


@user1269737的答案是正确的;几乎。但它仅适用于单个文件档案。 下面是解析整个档案的代码。

/**
* Replace wrong local file header byte
* http://sourceforge.net/tracker/?func=detail&aid=3477810&group_id=14481&atid=114481
* Applies to Android API 9-13
* @param zip file
* @throws IOException
*/
private static void fixInvalidZipFile(File zip) throws IOException 
{
    RandomAccessFile r = new RandomAccessFile(zip, "rw");
    try
    {
        long eocd_offset = findEOCDRecord(r);

        if (eocd_offset > 0)
        {
            r.seek(eocd_offset + 16);  // offset of first CDE in EOCD               
            long cde_offset = readInt(r);  // read offset of first Central Directory Entry
            long lfh_offset = 0;
            long fskip, dskip;

            while (true)
            {
                r.seek(cde_offset);
                if (readInt(r) != CDE_SIGNATURE)  // got off sync!
                    return;

                r.seek(cde_offset + 20);  // compressed file size offset                
                fskip = readInt(r);

                // fix the header
                //
                r.seek(lfh_offset + 7);
                short localFlagsHi = r.readByte();  // hi-order byte of local header flags (general purpose)
                r.seek(cde_offset + 9);
                short realFlagsHi = r.readByte();  // hi-order byte of central directory flags (general purpose)
                if (localFlagsHi != realFlagsHi)
                { // in latest versions this bug is fixed, so we're checking is bug exists.
                    r.seek(lfh_offset + 7);
                    r.write(realFlagsHi);
                }

                //  calculate offset of next Central Directory Entry
                //
                r.seek(cde_offset + 28);  // offset of variable CDE parts length in CDE
                dskip = 46;  // length of fixed CDE part
                dskip += readShort(r);  // file name
                dskip += readShort(r);  // extra field
                dskip += readShort(r);  // file comment

                cde_offset += dskip;
                if (cde_offset >= eocd_offset)  // finished!
                    break;              

                // calculate offset of next Local File Header
                //
                r.seek(lfh_offset + 26);  // offset of variable LFH parts length in LFH
                fskip += readShort(r);  // file name
                fskip += readShort(r);  // extra field
                fskip += 30;  // length of fixed LFH part
                fskip += 16;  // length of Data Descriptor (written after file data)

                lfh_offset += fskip;
            }
        }
    }
    finally
    {
        r.close();
    }
}

//http://www.pkware.com/documents/casestudies/APPNOTE.TXT
private static final int LFH_SIGNATURE = 0x04034b50;
private static final int DD_SIGNATURE = 0x08074b50;
private static final int CDE_SIGNATURE = 0x02014b50;
private static final int EOCD_SIGNATURE = 0x06054b50;

/** Find an offset of End Of Central Directory record in file */
private static long findEOCDRecord(RandomAccessFile f) throws IOException
{
    long result = f.length() - 22; // 22 is minimal EOCD record length
    while (result > 0)
    {
        f.seek(result);

        if (readInt(f) == EOCD_SIGNATURE) return result;

        result--;
    }
    return -1;
}

/** Read a 4-byte integer from file converting endianness. */
private static int readInt(RandomAccessFile f) throws IOException
{
    int result = 0;
    result |= f.read();
    result |= (f.read() << 8);
    result |= (f.read() << 16);
    result |= (f.read() << 24);
    return result;
}

/** Read a 2-byte integer from file converting endianness. */
private static short readShort(RandomAccessFile f) throws IOException
{
    short result = 0;
    result |= f.read();
    result |= (f.read() << 8);
    return result;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

无法从 Android 上创建的 ZIP 存档中提取文件(特定于设备/操作系统) 的相关文章

随机推荐

  • 如何制作输出目录选择面板?

    您好 我正在尝试制作一个窗格 在我的计算机中显示类似 Windows 资源管理器的内容 当用户完成操作后 当他想要将编辑后的图像保存在磁盘上的特定位置时 他可以轻松地从该窗格中选择目录 我想设计这样的东西 可以做类似的事情吗 我的图片编辑器
  • pandas pytables 附加:性能和文件大小的增加

    我有500多个PyTables每个存储大约包含 300Mb 的数据 我想使用 pandas 将这些文件合并到一个大商店中append如下面的代码所示 def merge hdfs file list merged store for fil
  • 如何将 ruby​​gem 条件要求添加到 gem 规范中?

    仅当用户使用特定版本的 ruby 时才可以添加 gem 依赖项吗 背景 我正在研究一个项目的分支使用 Test Unit Autorunner 等 它们是 ruby 1 8 中标准库的一部分 但不是 1 9 1 中标准库的一部分 而是位于
  • python 列表,向列表添加一些内容会改变整个内容?

    所以我试图在Python中实现选择排序 并且我将每次迭代的结果附加到一个列表中以在最后打印 我的代码正确地对数字列表进行排序 但是当我将它附加到最后的同一个列表中时更改所有其他列表 def s sort numbers alist do a
  • 计算出勤时间差

    我有一个包含以下示例输出的表格 UserID Checktime CheckStatus 3175 2013 12 22 07 02 10 000 I 3175 2013 12 22 13 01 01 000 O 3175 2013 12
  • 针对特定图像的 CSS

    我正在寻找一种使用 CSS 定位特定图像的方法 如果可能的话 我正在运行一个 CMS 用户可以在其中上传图像并将其放在他们的页面上 我想要一种定位具有特定尺寸的图像的方法 所以问题是 你可以让 css 行针对具有特定尺寸规格的图像或对象吗
  • 使用 LocalStorage 保存和加载购物车

    我有以下代码 inames iqtyp iprice function bestel inames push document getElementById artikel innerHTML iqtyp push parseInt doc
  • C - strtok(...) 上出现意外的分段错误

    我正在使用库的 strtok 它似乎工作正常 直到结束条件 它导致分段错误和程序崩溃 API 声称 当找不到更多标记时 strtok 将输出 NULL 这意味着 我认为 您必须捕获此 NULL 才能终止使用 strtok 运行的任何循环 我
  • Android 来电事件

    我想创建一个 onCall 事件 我已经知道没有这样的方法 但基本上我想做的是 当接到来电时 弹出 Toast 或其他任何内容 任何类型的教程或示例代码都会有帮助 多谢 Use PhoneStateListener它已经重写了方法onCal
  • 如何确定 ARM 处理器是运行在通常的锁定“世界”中还是运行在 Secore“世界”中?

    例如 virt what显示您是否在硬件虚拟化 沙箱 内运行 如何检测您是否在 ARM TrustZone 沙箱中运行 信任区也许与你想象的不同 有一系列模式 从 可信功能的简单 API 到在每个世界中运行的 双操作系统 如果该问题有更多背
  • Objective-C:正确保留 3 位小数

    我正在尝试将浮点值降低到小数点后第三位 例如 值 2 56976 应为 2 569 而不是 2 570 我搜索并找到了这样的答案 向下取小数点后两位数 这样的答案并不准确 例如代码 double value double unsigned
  • 序列化静态类?

    如果我们序列化静态类会发生什么 如果我们序列化静态类 是否可以创建多个静态类实例 Serializable public static class MyClass public static MyClass public static bo
  • PHP 用 vars 替换字符串中的通配符(%s、%d)

    我有翻译功能t var function t word return this gt words word where this gt words是数组 this gt words array word1 gt word word2 gt
  • 如何打印一年中的所有星期(或一年中的第一个星期一)

    如何打印从星期一开始到星期日结束的所有周 如下所示 使用 Zend date 1 04 Jan 2010 10 Jan 2010 2 11 Jan 2010 17 Jan 2010 3 18 Jan 2010 24 Jan 2010 首先找
  • MYSQL 选择往复数据?

    我有一张桌子叫Follow 具有三个字段 Id 自动增量整数 用户ID 整数 关注 整数 如果我有这样的数据 ID UserId Following 1 2 3 2 3 2 3 2 5 4 2 6 5 3 5 我如何找到用户 2 的朋友 即
  • Pandas groupby 然后应用 to_dict('records')

    假设我有以下数据框 df pd DataFrame a 1 1 1 2 b a a b c d 1 2 3 4 我想以下面的句子结束 1 b a d 1 b a d 2 b b d 3 2 b c d 4 基本上 我想分组a对于我想应用的每
  • 将 UTC 日期转换为当前时区

    我必须将这种格式 2016 09 25 17 26 12 的 UTC 日期转换为 Android 的当前时区 我这样做了 SimpleDateFormat simpleDateFormat new SimpleDateFormat yyyy
  • 在 Objective C 中读取 .doc (MS Word) 文件?

    是否可以在 ObjC 中读取 doc MSWord 文件 或者 还有其他方法可以读取word文件吗 Thanks 这取决于您的平台 iPhone 的富文本功能与 OS X 截然不同 UIWebView可以打开它们在 iPhone 上 在 M
  • 如何使用带有工具提示的 ChartJs 或 D3 创建 RRG(相对旋转图)?

    我想使用 ChartJS 或 D3Js 使用任何开源创建 RRG 我已经尝试过这个 但无法绘制象限分叉示例https codesandbox io s chart js forked m1zug2 期望应该如下所示 在此输入图像描述 您可以
  • 无法从 Android 上创建的 ZIP 存档中提取文件(特定于设备/操作系统)

    我正在 Android 上使用如下代码创建存档 OutputStream os new FileOutputStream zipFile ZipOutputStream zos new ZipOutputStream new Buffere