read()

问题描述 投票:0回答:1

我尝试读取作为 zip 存档一部分的二进制文件。因此我用 Poco::Zip 打开了 zip 存档。然后我逐块读取二进制文件

struct Header
{
    uint64_t tag;
    uint32_t payloadLength;
} __attribute__((packed));

std::ifstream inp("my.zip", std::ios::binary);
Poco::Zip::ZipArchive arch(inp);
Poco::Zip::ZipArchive::FileHeaders::const_iterator it = arch.findHeader("file.dat");
if (it != arch.headerEnd()) {
    Poco::Zip::ZipInputStream inStream(inp, it ->second);
    Header hdr;
    inStream.read(reinterpret_cast<char*>(&hdr), sizeof(hdr));
    
    char buffer[hdr.payloadLength];
    inStream.read(reinterpret_cast<char*>(buffer), sizeof(hdr.payloadLength));
    
    ...
}

从 ZipInputStream 读取时,我得到了垃圾数据。

当我使用时

std::string str((std::istreambuf_iterator<char>(inStream)), std::istreambuf_iterator<char>());

它有效,但我想避免这种解决方案,因为它将整个文件缓冲在一个可能的大缓冲区中。

read()
这里出了什么问题?

zip c++17 poco-libraries
1个回答
0
投票

有两件事是错误的。

首先,您忽略了一个重要的文档内容

ZipArchive(
    std::istream & in,
    ParseCallback & callback
);

从文件或网络流创建 ZipArchive。 注意,构造函数完成后,in 流将处于失败状态

[我的重点]

或者也许你没有意识到它的重要性。这意味着您需要先清除

inp
的失败状态,然后才能对其进行进一步的访问操作, 在你的情况下意味着之前:

Poco::Zip::ZipInputStream inStream(inp, it->second);

第二,这个:

inStream.read(reinterpret_cast<char*>(buffer), sizeof(hdr.payloadLength));

请求

inStream
将 4 个字节的数据读入
buffer
,因为
sizeof(hdr.payloadLength)
==
sizeof(unint32_t)
== 4。你的意思是 读取
hdr.payloadLength
字节数据。
hdr.payloadLength
-
buffer
中会有 4 个字节的尾随垃圾。

您可能还注意到:

char buffer[hdr.payloadLength];

是一个变长数组,这在标准 C++ 中是非法的。你会被警告这一点 与

pedantic
。在 C++ 中,您应该使用
std::vector
来表示 VLA。

您更有可能阅读存档的

file.dat
,代码如下:

#include <fstream>
#include <vector>
#include <Poco/Zip/ZipArchive.h>
#include <Poco/Zip/ZipStream.h>

struct Header
{
    uint64_t tag;
    uint32_t payloadLength;
} __attribute__((packed));

int main()
{
    std::ifstream inp("my.zip", std::ios::binary);
    Poco::Zip::ZipArchive arch(inp);
    Poco::Zip::ZipArchive::FileHeaders::const_iterator it = arch.findHeader("file.dat");
    if (it != arch.headerEnd()) {
        inp.clear();
        Poco::Zip::ZipInputStream inStream(inp, it->second);
        Header hdr;
        inStream.read(reinterpret_cast<char*>(&hdr), sizeof(hdr));
        std::vector<char>::size_type datlen = hdr.payloadLength;
        std::vector<char> buffer(datlen);
        inStream.read(buffer.data(), datlen);
        // ...
    }
    return 0;
}

虽然你发布的代码不完整,我不知道如何

file.dat
已写,我不能确定。

© www.soinside.com 2019 - 2024. All rights reserved.