1

我目前正在解压暴雪的 .mpq 文件之一以供阅读。为了访问解压的字符缓冲区,我使用了 boost::interprocess::stream::memorybuffer。因为 .mpq 文件具有始终以版本标头开头的分块结构(通常为 12 个字节,请参阅http://wiki.devklog.net/index.php?title=The_MoPaQ_Archive_Format#2.2_Archive_Header),char* 数组表示似乎被截断在第一个 \0,即使文件大小(大约 1.6mb)保持不变并且(可能)总是分配。结果是一个有效长度为 4 的流缓冲区('REVM' 和字节 nr.5 为 \0)。尝试进一步阅读时,会引发异常。这里有一个例子:

    // (somewhere in the code)
{
    MPQFile curAdt(FilePath);    
    size_t size = curAdt.getSize(); // roughly 1.6 mb
    bufferstream memorybuf((char*)curAdt.getBuffer(), curAdt.getSize());
    // bufferstream.m_buf.m_buffer is now 'REVM\0' (Debugger says so), 
    // but internal length field still at 1.6 mb
}
//////////////////////////////////////////////////////////////////////////////

// wrapper around a file oof the mpq_archive of libmpq
MPQFile::MPQFile(const char* filename)    // I apologize my naming inconsistent convention :P
{
    for(ArchiveSet::iterator i=gOpenArchives.begin(); i!=gOpenArchives.end();++i)
    {
        // gOpenArchives points to MPQArchive, wrapper around the mpq_archive, has mpq_archive * mpq_a as member
        mpq_archive &mpq_a = (*i)->mpq_a; 

        // if file exists in that archive, tested via hash table in file, not important here, scroll down if you want

        mpq_hash hash = (*i)->GetHashEntry(filename);
        uint32 blockindex = hash.blockindex;

        if ((blockindex == 0xFFFFFFFF) || (blockindex == 0)) {
            continue; //file not found
        }

        uint32 fileno = blockindex;

        // Found!
        size = libmpq_file_info(&mpq_a, LIBMPQ_FILE_UNCOMPRESSED_SIZE, fileno);
        // HACK: in patch.mpq some files don't want to open and give 1 for filesize
        if (size<=1) {
            eof = true;
            buffer = 0;
            return;
        }
        buffer = new char[size];  // note: size is 1.6 mb at this time

        // Now here comes the tricky part... if I step over the libmpq_file_getdata
        // function, I'll get my truncated char array, which I absolutely don't want^^
        libmpq_file_getdata(&mpq_a, hash, fileno, (unsigned char*)buffer);
        return;
    }
}

也许有人可以帮助我。我对 STL 和 boost 编程真的很陌生,而且无论如何也没有 C++ 编程经验:P 希望得到一个方便的答案(请不要建议重写 libmpq 和底层的 zlib 架构^^)。MPQFile 类和底层的 uncompress 方法实际上是从一个工作项目中获取的,所以错误要么是在使用 streambuffer 类的缓冲区中的某个地方,要么是我不知道的 char 数组算法内部的东西。顺便说一句,使用有符号/无符号字符作为数据缓冲区有什么区别?与我的问题有什么关系(您可能会看到,在代码中随机 char* unsigned char* 被视为函数参数)如果您需要更多信息,请随时询问:)

4

2 回答 2

1

您如何确定您的 char* 数组被“截断”?如果您正在打印它或在调试器中查看它,它看起来会被截断,因为它会被视为以 \0 结尾的字符串。但是,“缓冲区”中的数据(假设 libmpq_file_getdata() 完成了它应该做的事情)将包含整个文件或数据块或其他任何内容。

于 2010-01-12T15:33:16.543 回答
0

抱歉,这些术语有点搞砸了(实际上不是 memorybuffer,streambuffer 是在代码中的意思)

是的,你在哪里对...我的异常处理有一个错误。就在第一段代码之后:

// check if the file has been open
//if (!mpf.is_open())
        pair<char*, size_t> temp = memorybuf.buffer();
        if(temp.first)
            throw AdtException(ADT_PARSEERR_EFILE);//Can't open the File

注意失踪!在 temp.first 之前。我对抛出的异常感到惊讶,查看了流缓冲区 .. 内部缓冲区,对其长度感到困惑(C# 背景:P)。很抱歉,它现在按预期工作。

于 2010-01-12T16:01:28.250 回答