如何从 RAM 中完全解析压缩文件?

2024-02-04

背景

我需要解析一些各种类型的 zip 文件(出于某种目的获取一些内部文件内容,包括获取它们的名称)。

有些文件无法通过文件路径访问,因为 Android 有 Uri 来访问它们,并且有时 zip 文件位于另一个 zip 文件内。随着使用 SAF 的推动,在某些情况下使用文件路径的可能性甚至更小。

对此,我们主要有2种方式来处理:ZipFile https://developer.android.com/reference/java/util/zip/ZipFile类和Zip输入流 https://developer.android.com/reference/java/util/zip/ZipInputStream class.

问题

当我们有文件路径时,ZipFile 是一个完美的解决方案。在速度方面它也非常有效。

但是,对于其余情况,ZipInputStream 可能会遇到问题,例如this one https://issuetracker.google.com/issues/151990857,它有一个有问题的 zip 文件,并导致此异常:

  java.util.zip.ZipException: only DEFLATED entries can have EXT descriptor
        at java.util.zip.ZipInputStream.readLOC(ZipInputStream.java:321)
        at java.util.zip.ZipInputStream.getNextEntry(ZipInputStream.java:124)

我尝试过的

唯一始终有效的解决方案是将文件复制到其他地方,您可以在其中使用 ZipFile 解析它,但这效率很低,并且需要您有可用存储空间,并在完成文件后删除该文件。

所以,我发现 Apache 有一个很好的、纯 Java 库(here http://commons.apache.org/proper/commons-compress/)来解析 Zip 文件,由于某种原因,它的 InputStream 解决方案(称为“ZipArchiveInputStream”)似乎比本机 ZipInputStream 类更高效。

与我们在本机框架中所拥有的相反,该库提供了更多的灵活性。例如,我可以将整个 zip 文件加载到字节数组中,并让库照常处理它,这甚至适用于我提到的有问题的 Zip 文件:

org.apache.commons.compress.archivers.zip.ZipFile(SeekableInMemoryByteChannel(byteArray)).use { zipFile ->
    for (entry in zipFile.entries) {
      val name = entry.name
      ... // use the zipFile like you do with native framework

梯度依赖:

// http://commons.apache.org/proper/commons-compress/ https://mvnrepository.com/artifact/org.apache.commons/commons-compress
implementation 'org.apache.commons:commons-compress:1.20'

遗憾的是,这并不总是可能的,因为它取决于堆内存保存整个 zip 文件,并且在 Android 上,它变得更加有限,因为堆大小可能相对较小(堆可能是 100MB,而文件是 200MB) )。与 PC 可以设置巨大的堆内存不同,Android 一点也不灵活。

因此,我寻找了一个具有 JNI 的解决方案,将整个 ZIP 文件加载到字节数组中,而不是进入堆(至少不完全)。这可能是一个更好的解决方法,因为如果 ZIP 可以适合设备的 RAM 而不是堆,它可以防止我达到 OOM,同时也不需要额外的文件。

我找到了这个库叫做“larray” https://github.com/xerial/larray这看起来很有希望,但遗憾的是,当我尝试使用它时,它崩溃了,因为它的要求包括拥有完整的 JVM,这意味着不适合 Android。

编辑:看到我找不到任何库和任何内置类,我尝试自己使用 JNI。遗憾的是我对它非常生疏,我查看了很久以前制作的一个旧存储库来对位图执行一些操作(here https://github.com/AndroidDeveloperLB/AndroidJniBitmapOperations)。这就是我想出的:

本机库.cpp

#include <jni.h>
#include <android/log.h>
#include <cstdio>
#include <android/bitmap.h>
#include <cstring>
#include <unistd.h>

class JniBytesArray {
public:
    uint32_t *_storedData;

    JniBytesArray() {
        _storedData = NULL;
    }
};

extern "C" {
JNIEXPORT jobject JNICALL Java_com_lb_myapplication_JniByteArrayHolder_allocate(
        JNIEnv *env, jobject obj, jlong size) {
    auto *jniBytesArray = new JniBytesArray();
    auto *array = new uint32_t[size];
    for (int i = 0; i < size; ++i)
        array[i] = 0;
    jniBytesArray->_storedData = array;
    return env->NewDirectByteBuffer(jniBytesArray, 0);
}
}

JniByteArrayHolder.kt

class JniByteArrayHolder {
    external fun allocate(size: Long): ByteBuffer

    companion object {
        init {
            System.loadLibrary("native-lib")
        }
    }
}
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        thread {
            printMemStats()
            val jniByteArrayHolder = JniByteArrayHolder()
            val byteBuffer = jniByteArrayHolder.allocate(1L * 1024L)
            printMemStats()
        }
    }

    fun printMemStats() {
        val memoryInfo = ActivityManager.MemoryInfo()
        (getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager).getMemoryInfo(memoryInfo)
        val nativeHeapSize = memoryInfo.totalMem
        val nativeHeapFreeSize = memoryInfo.availMem
        val usedMemInBytes = nativeHeapSize - nativeHeapFreeSize
        val usedMemInPercentage = usedMemInBytes * 100 / nativeHeapSize
        Log.d("AppLog", "total:${Formatter.formatFileSize(this, nativeHeapSize)} " +
                "free:${Formatter.formatFileSize(this, nativeHeapFreeSize)} " +
                "used:${Formatter.formatFileSize(this, usedMemInBytes)} ($usedMemInPercentage%)")
    }

这看起来不对,因为如果我尝试使用创建一个 1GB 字节数组jniByteArrayHolder.allocate(1L * 1024L * 1024L * 1024L),它崩溃了,没有任何异常或错误日志。

问题

  1. 是否可以将 JNI 用于 Apache 的库,以便它将处理 JNI 的“世界”中包含的 ZIP 文件内容?

  2. 如果是这样,我该怎么办?有没有关于如何做到这一点的示例?有相关课程吗?还是我必须自己实施?如果是这样,您能展示一下 JNI 中是如何完成的吗?

  3. 如果不可能的话还有什么其他方法可以实现呢?也许可以替代 Apache 的功能?

  4. JNI的解决方案,为什么效果不好呢?我怎样才能有效地将字节从流复制到 JNI 字节数组中(我的猜测是它将通过缓冲区)?


我查看了您发布的 JNI 代码并做了一些更改。主要是定义大小参数NewDirectByteBuffer并使用malloc().

这是分配 800mb 后日志的输出:

D/AppLog:总计:1.57 GB 可用:1.03 GB 已用:541 MB (34%)
D/AppLog:总计:1.57 GB 可用:247 MB​​ 使用:1.32 GB (84%)

以下是分配后缓冲区的样子。正如您所看到的,调试器报告的限制为 800mb,这正是我们所期望的。

enter image description here My C is very rusty, so I am sure that there is some work to be done. I have updated the code to be a little more robust and to allow for the freeing of memory.

本机库.cpp

extern "C" {
static jbyteArray *_holdBuffer = NULL;
static jobject _directBuffer = NULL;
/*
    This routine is not re-entrant and can handle only one buffer at a time. If a buffer is
    allocated then it must be released before the next one is allocated.
 */
JNIEXPORT
jobject JNICALL Java_com_example_zipfileinmemoryjni_JniByteArrayHolder_allocate(
        JNIEnv *env, jobject obj, jlong size) {
    if (_holdBuffer != NULL || _directBuffer != NULL) {
        __android_log_print(ANDROID_LOG_ERROR, "JNI Routine",
                            "Call to JNI allocate() before freeBuffer()");
        return NULL;
    }

    // Max size for a direct buffer is the max of a jint even though NewDirectByteBuffer takes a
    // long. Clamp max size as follows:
    if (size > SIZE_T_MAX || size > INT_MAX || size <= 0) {
        jlong maxSize = SIZE_T_MAX < INT_MAX ? SIZE_T_MAX : INT_MAX;
        __android_log_print(ANDROID_LOG_ERROR, "JNI Routine",
                            "Native memory allocation request must be >0 and <= %lld but was %lld.\n",
                            maxSize, size);
        return NULL;
    }

    jbyteArray *array = (jbyteArray *) malloc(static_cast<size_t>(size));
    if (array == NULL) {
        __android_log_print(ANDROID_LOG_ERROR, "JNI Routine",
                            "Failed to allocate %lld bytes of native memory.\n",
                            size);
        return NULL;
    }

    jobject directBuffer = env->NewDirectByteBuffer(array, size);
    if (directBuffer == NULL) {
        free(array);
        __android_log_print(ANDROID_LOG_ERROR, "JNI Routine",
                            "Failed to create direct buffer of size %lld.\n",
                            size);
        return NULL;
    }
    // memset() is not really needed but we call it here to force Android to count
    // the consumed memory in the stats since it only seems to "count" dirty pages. (?)
    memset(array, 0xFF, static_cast<size_t>(size));
    _holdBuffer = array;

    // Get a global reference to the direct buffer so Java isn't tempted to GC it.
    _directBuffer = env->NewGlobalRef(directBuffer);
    return directBuffer;
}

JNIEXPORT void JNICALL Java_com_example_zipfileinmemoryjni_JniByteArrayHolder_freeBuffer(
        JNIEnv *env, jobject obj, jobject directBuffer) {

    if (_directBuffer == NULL || _holdBuffer == NULL) {
        __android_log_print(ANDROID_LOG_ERROR, "JNI Routine",
                            "Attempt to free unallocated buffer.");
        return;
    }

    jbyteArray *bufferLoc = (jbyteArray *) env->GetDirectBufferAddress(directBuffer);
    if (bufferLoc == NULL) {
        __android_log_print(ANDROID_LOG_ERROR, "JNI Routine",
                            "Failed to retrieve direct buffer location associated with ByteBuffer.");
        return;
    }

    if (bufferLoc != _holdBuffer) {
        __android_log_print(ANDROID_LOG_ERROR, "JNI Routine",
                            "DirectBuffer does not match that allocated.");
        return;
    }

    // Free the malloc'ed buffer and the global reference. Java can not GC the direct buffer.
    free(bufferLoc);
    env->DeleteGlobalRef(_directBuffer);
    _holdBuffer = NULL;
    _directBuffer = NULL;
}
}

我还更新了阵列支架:

class JniByteArrayHolder {
    external fun allocate(size: Long): ByteBuffer
    external fun freeBuffer(byteBuffer: ByteBuffer)

    companion object {
        init {
            System.loadLibrary("native-lib")
        }
    }
}

我可以确认此代码以及ByteBufferChannelBotje 提供的课程here https://stackoverflow.com/a/61680313/6287910适用于 API 24 之前的 Android 版本。SeekableByteChannel接口是在 API 24 中引入的,ZipFile 实用程序需要该接口。

可以分配的最大缓冲区大小是 jint 的大小,这是由于 JNI 的限制。可以容纳更大的数据(如果可用),但需要多个缓冲区和处理它们的方法。

这是示例应用程序的主要活动。早期版本总是假设InputStream读取缓冲区总是被填满并在尝试将其放入ByteBuffer。这是固定的。

MainActivity.kt

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
    }

    fun onClick(view: View) {
        button.isEnabled = false
        status.text = getString(R.string.running)

        thread {
            printMemStats("Before buffer allocation:")
            var bufferSize = 0L
            // testzipfile.zip is not part of the project but any zip can be uploaded through the
            // device file manager or adb to test.
            val fileToRead = "$filesDir/testzipfile.zip"
            val inStream =
                if (File(fileToRead).exists()) {
                    FileInputStream(fileToRead).apply {
                        bufferSize = getFileSize(this)
                        close()
                    }
                    FileInputStream(fileToRead)
                } else {
                    // If testzipfile.zip doesn't exist, we will just look at this one which
                    // is part of the APK.
                    resources.openRawResource(R.raw.appapk).apply {
                        bufferSize = getFileSize(this)
                        close()
                    }
                    resources.openRawResource(R.raw.appapk)
                }
            // Allocate the buffer in native memory (off-heap).
            val jniByteArrayHolder = JniByteArrayHolder()
            val byteBuffer =
                if (bufferSize != 0L) {
                    jniByteArrayHolder.allocate(bufferSize)?.apply {
                        printMemStats("After buffer allocation")
                    }
                } else {
                    null
                }

            if (byteBuffer == null) {
                Log.d("Applog", "Failed to allocate $bufferSize bytes of native memory.")
            } else {
                Log.d("Applog", "Allocated ${Formatter.formatFileSize(this, bufferSize)} buffer.")
                val inBytes = ByteArray(4096)
                Log.d("Applog", "Starting buffered read...")
                while (inStream.available() > 0) {
                    byteBuffer.put(inBytes, 0, inStream.read(inBytes))
                }
                inStream.close()
                byteBuffer.flip()
                ZipFile(ByteBufferChannel(byteBuffer)).use {
                    Log.d("Applog", "Starting Zip file name dump...")
                    for (entry in it.entries) {
                        Log.d("Applog", "Zip name: ${entry.name}")
                        val zis = it.getInputStream(entry)
                        while (zis.available() > 0) {
                            zis.read(inBytes)
                        }
                    }
                }
                printMemStats("Before buffer release:")
                jniByteArrayHolder.freeBuffer(byteBuffer)
                printMemStats("After buffer release:")
            }
            runOnUiThread {
                status.text = getString(R.string.idle)
                button.isEnabled = true
                Log.d("Applog", "Done!")
            }
        }
    }

    /*
        This function is a little misleading since it does not reflect the true status of memory.
        After native buffer allocation, it waits until the memory is used before counting is as
        used. After release, it doesn't seem to count the memory as released until garbage
        collection. (My observations only.) Also, see the comment for memset() in native-lib.cpp
        which is a member of this project.
    */
    private fun printMemStats(desc: String? = null) {
        val memoryInfo = ActivityManager.MemoryInfo()
        (getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager).getMemoryInfo(memoryInfo)
        val nativeHeapSize = memoryInfo.totalMem
        val nativeHeapFreeSize = memoryInfo.availMem
        val usedMemInBytes = nativeHeapSize - nativeHeapFreeSize
        val usedMemInPercentage = usedMemInBytes * 100 / nativeHeapSize
        val sDesc = desc?.run { "$this:\n" }
        Log.d(
            "AppLog", "$sDesc total:${Formatter.formatFileSize(this, nativeHeapSize)} " +
                    "free:${Formatter.formatFileSize(this, nativeHeapFreeSize)} " +
                    "used:${Formatter.formatFileSize(this, usedMemInBytes)} ($usedMemInPercentage%)"
        )
    }

    // Not a great way to do this but not the object of the demo.
    private fun getFileSize(inStream: InputStream): Long {
        var bufferSize = 0L
        while (inStream.available() > 0) {
            val toSkip = inStream.available().toLong()
            inStream.skip(toSkip)
            bufferSize += toSkip
        }
        return bufferSize
    }
}

示例 GitHub 存储库是here https://github.com/Cheticamp/ZipFileInMemoryJNI.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何从 RAM 中完全解析压缩文件? 的相关文章

  • Android中如何使用洪水填充算法?

    我是Android编程新手 最近尝试编写一个简单的应用程序 仅供练习 在这个中 我想在用户点击时为图像着色 但我不知道如何开始 我读过不同的主题 其中提到使用 洪水填充 算法 我在网上找到了它 但我不知道如何将它放入我的简单应用程序中 我找
  • 按回键隐藏软键盘

    我有一个EditText in an Activity我希望当我打开它时它处于活动状态并且软键盘处于打开状态Activity 这是我的xml for EditText
  • Android 上的 Firebase:如何检查 Firebase 身份验证失败原因?

    我在 Android 上使用 Firebase 和 Firebase Auth 功能 I try FirebaseAuth signInWithEmailAndPassword如果失败 我想知道为什么登录过程失败 The signInWit
  • 检索子值 -firebase-

    System out println ref child email protected cdn cgi l email protection child email 我正在尝试获取 child 的值 但我始终获取该值的 URL 当我尝试使
  • Android - 当不在栏顶部时推送通知空白

    我在使用 Android 推送通知时遇到一个小问题 如果有 3 个通知 并且只有其中一个显示标题和消息 位于酒吧顶部的那个 如果有人知道可能是什么问题 请告诉我 请参阅此链接上的图像 这就是我接收通知的方式http postimg org
  • 如何在 Android 上创建 YouTube 的双击手势?

    我在 Android 上有 exoplayer 的应用程序 我已经创建了 youtube双击手势用动画向前或向后跳跃 10 秒 如何在双击时创建具有波纹效果的半圆 像这样 这个怎么做 我也想实现这样的功能 所以我自己编写了它来 复制 You
  • 获取可以共享数据的应用程序列表

    此代码显示默认共享对话框 Intent sharingIntent new Intent Intent ACTION SEND sharingIntent setType text html sharingIntent putExtra a
  • AnalyticsService 未在应用程序清单中注册 - 错误

    我正在尝试使用 sdk 中提供的以下文档向 Android 应用程序实施谷歌分析服务 https developers google com analytics devguides collection android v4 https d
  • Android Web Intent 问题

    G day 免责声明 我不是 Android 开发人员 我正在对我所描述的问题进行质量检查 我用来描述这个问题的技术术语可能是错误的 我正在测试一个 Android 应用程序 该应用程序在其清单中描述它可以使用 type 的地址处理 Web
  • Google 移动广告和 Kindle Fire

    我最近用 Google 移动广告替换了 AdMob 库 对此我有一个疑问 广告会出现在 Amazon Kindle Fire 设备上吗 我问这个是因为我知道 Google 移动广告依赖于 Google Play 服务 所以我有点困惑 Goo
  • 加快 ImageView 中的缩放功能

    我目前正在处理非常大的图像 7 10mb 由于多种原因无法调整大小或压缩 现在 我们的想法是在自定义 ImageView 中显示它们 使用户能够进行双击缩放 捏合缩放等 我使用这个库来完成这项工作 https github com Mike
  • jar 中的 apklib 有什么优点?

    我正在关注这个问题 https stackoverflow com questions 6059502 whats the difference between apklib and jar files但它并没有完全回答我的问题 jar 中
  • 如何在Android Compose中使用otf类型字体文件?

    我正在学习使用 Android Jetpack Compose 现在我有一个正则 otf字体文件在资产 字体 我想在文本中使用它 java lang RuntimeException Font asset not found commonu
  • 使用嵌套的 hashmap 参数发送 volley 请求

    我正在使用 android volley 框架向我的服务器发送 jsonobject 请求 get 请求工作正常 现在我想发送一个带有请求参数的 post 请求 该请求参数是嵌套的 hashmap 我重写 getparams 方法 但它期望
  • 如何获取android手机型号、版本、sdk详细信息?

    如何获取android手机型号 版本 sdk详细信息 首先 看看 android sdk 页面上的这些 Build 类 http developer android com reference android os Build html h
  • 检测 ListView(或 ScrollView)内的滚动位置

    我正在构建一个聊天室应用程序 其中每 X 秒就会轮询一次新事件 每次发生这种情况时 此代码都会使用新数据更新 RoomAdapter ArrayAdapter 的自定义子类 并将其滚动到底部 RoomAdapter adapter Room
  • Android - iphone 风格 tabhost [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • Android 中的 Google Places API - 适用于个人用户的 API_KEY

    我已经浏览了与在 Android 应用程序中使用 Places API 相关的 Android 文档和其他博客 到处都建议使用 API KEY 来调用 REST 服务 API KEY 在整个项目 应用程序中都是相同的 每天的请求数限制为 1
  • [cocos2d-x]当我尝试在 Windows 10 中运行“python android-build.py -p 19 cpp-tests”时出现错误

    当我尝试运行命令时python android build p cpp tests 我收到如图所示的错误 在此之前 我收到了另一条关于 Android SDK Tools 版本兼容性的错误消息 所以 我只是将 sdk 版本从 26 0 0
  • putFragment() - 片段 x 当前不在 FragmentManager 中

    上面的标题被问了很多次 但答案似乎与FragmentStatePagerAdapter这与我的问题无关 我正在使用该方法putFragment Bundle String Fragment 直接地 The 安卓文档 http develop

随机推荐

  • Cassandra:向表中添加新列

    您好 我刚刚在我的表 my table 中添加了一个新列 Business sys ALTER TABLE my table ALTER business sys TYPE set
  • 有没有办法在界面生成器中制作渐变背景色?

    对于我的应用程序 我使用 TableView 并使用自定义的 UITableViewCells 我通过界面生成器而不是以编程方式自定义了我的单元格 有没有办法在界面生成器中将自定义单元格的背景颜色设置为渐变 Thanks 这适用于 Swif
  • 上传多个文件显示错误代码:3

    这个问题和问的一样here https stackoverflow com questions 19275268 phonegap file transfer of picture fails on every other picture
  • NSTimer 一段时间后在后台停止

    当应用程序进入后台时 我使用 NSTimer 在 1 秒后调用一个方法 并在近 17 分钟后计时器停止工作 当它返回前台时 它再次开始工作 所以请告诉我为什么会发生这种情况以及如何解决该问题 我还尝试使用延迟递归的执行选择器来达到相同的目的
  • 调用 QtGui.QFileDialog.getExistingDirectory 时出错

    在 pyqt 代码中 我试图向用户提升一个对话框并让用户选择一个文件夹 看来 QtGui QFileDialog getExistingDirectory 方法应该能够做到这一点 问题是代码运行后有一些错误消息 D Lib debug pr
  • removeObject 是否释放 NSMutableArray 对象中的对象?

    我想知道当您在数组中使用removeObject 删除对象时 是否正确处理了删除的对象 被移除的对象会被释放吗 NSMutableArray 将释放它 如果这是最后一次保留 它将被释放 从文档中 与 NSArray 一样 NSMutable
  • 我的部分视图中的 Jquery 或 Javascript 问题

    我可以在部分视图中使用 jQuery 或 JavaScript 代码吗 我的部分视图中有一个网格 我试图在该部分视图中使用 jQuery 隐藏一个网格元素 我做不到 但如果我在没有部分视图的情况下使用它 相同的代码就可以工作 有人可以帮我吗
  • 委托不在单例中工作[关闭]

    这个问题不太可能对任何未来的访客有帮助 它只与一个较小的地理区域 一个特定的时间点或一个非常狭窄的情况相关 通常不适用于全世界的互联网受众 为了帮助使这个问题更广泛地适用 访问帮助中心 help reopen questions 为了在多个
  • Databricks - 无法从 DataFrame 写入 Delta 位置

    我想更改 Databricks Delta 表的列名称 所以我做了以下事情 Read old table data val old data DF spark read format delta load dbfs mnt main sal
  • 如何重建开发 Pod 变更?

    我有一个开发容器 我使用它在本地连接到我的应用程序 path gt Projects Swift pod 当我在该开发容器中的应用程序代码中进行更改时 构建后不会包含此更改 这就像我正在构建缓存代码 而不是更改我的代码 为了将代码更改包含到
  • 计算网络两个输出之间的 cosine_proximity 损失

    我正在使用 Keras 2 0 2 功能 API Tensorflow 1 0 1 来实现一个接受多个输入并产生两个输出的网络a and b 我需要使用 cosine proximity 损失来训练网络 这样b是标签a 我该怎么做呢 在这里
  • 在 makefile 中指定路径(Windows 上的 GNU make)

    我正在使用 GNU make 来构建一个使用 Microsoft Visual C 的项目 并且我希望能够从任何 CMD 窗口运行它 而不必打开预配置路径 以及各种其他环境变量 的预配置窗口通过批处理文件 理想情况下 我想在 makefil
  • 无法让 pyspark 作业在 hadoop 集群的所有节点上运行

    Summary 我无法运行我的 python spark 作业all我的 hadoop 集群的节点 我已经安装了 hadoop spark 1 5 2 bin hadoop2 6 的 Spark 启动 java Spark 作业时 负载得到
  • 如何检查 Asp.net Core MVC(又名 Asp.Net 5 RC1)中的响应 cookie?

    我正在将 Web 表单应用程序转换为 asp net core mvc 在我的 Web 表单应用程序中 有时在我设置一些响应 cookie 后 其他代码需要查看它们是否已设置 如果是 则访问 cookie 的属性 即值 过期 安全 http
  • 在 Powershell 中删除重复的 XML 节点组

    我有一个 XML 文件 由于重新运行脚本和文件夹结构 该文件可能包含重复的包元素 请参阅示例 XML 中的最后两个包 现在我需要一个 Powershell 函数来删除所有重复的包 在这种情况下 重复项是由制造商 名称 版本 文件名和执行版本
  • 如何从 CPAN 安装“Thread::Pool”?

    我在用着cpanm安装 Perl 模块 但我无法安装Thread Pool因为某些原因 sudo cpanm Thread Pool 失败并且日志文件显示 cpanm App cpanminus 1 0012 on perl 5 01000
  • Bottle.py 错误路由

    Bottle py 附带了一个导入来处理抛出 HTTPError 并路由到函数 首先 文档声称我可以 几个例子也是如此 from bottle import error error 500 def custom500 error retur
  • 您能识别出这个带有复选框的多选下拉列表吗?

    I m looking for this control which is definitely not stock It s on a website that I won t link so people don t think I m
  • 如何使用 parse.com 服务器 iOS 保存对象数组?

    我正在使用 parse com 服务器发送和检索我的 iOS 应用程序数据 我想保存歌曲列表 每首歌曲都有以下属性 标题 艺术家 专辑 我的代码片段在这里 IBAction saveSongsData id sender PFObject
  • 如何从 RAM 中完全解析压缩文件?

    背景 我需要解析一些各种类型的 zip 文件 出于某种目的获取一些内部文件内容 包括获取它们的名称 有些文件无法通过文件路径访问 因为 Android 有 Uri 来访问它们 并且有时 zip 文件位于另一个 zip 文件内 随着使用 SA