5

我正在开发一个使用 libzip 的项目。我正在使用 c++14 并围绕 libzip 编写了一个小包装器,以使我的生活更轻松。

我有一个std::ostream围绕继承的自定义类构建的对象std::streambuf。此 streambuf 使用 libzip 函数写入存档中的文件。

在我使用std::endl. 当我这样做时,我的所有文本阅读器都将输出文件读取为二进制文件(仅写入字符串)。

我的文本阅读器检测到它的二进制文件,因为在我使用std::endlNUL 字节的地方,任何内部带有 NUL 字节的文件都被视为二进制文件。

所以我的问题是:这正常吗?有没有办法让我使用std::endl

我的代码(已提取,因此可能不完全相同)。

源码.hpp

// my attributes
std::unique_ptr<zip_source_t, std::function<void(zip_source_t*)>> _source;
std::unique_ptr<std::ostream> _stream;
std::unique_ptr<_ZipBuffer> _buffer;

class _ZipBuffer : public std::streambuf {
    private:
        zip_source_t* _source;

        std::streamsize xsputn(char const* s, std::streamsize n) override;
        int overflow(int c) override;

    public:
        _ZipBuffer(zip_source_t* file);
};

源码.cpp

// create the streambuf and send it to the ostream
_buffer.reset(new _ZipBuffer(_source.get()));
_stream.reset(new std::ostream(_buffer.get()));

// the implementation of _ZipBuffer
Zip::Source::_ZipBuffer::_ZipBuffer(zip_source_t* source) {
    _source = source;
}

std::streamsize Zip::Source::_ZipBuffer::xsputn(char const* s, std::streamsize n) {
    return zip_source_write(_source, s, n * sizeof(char));
}

int Zip::Source::_ZipBuffer::overflow(int c) {
    return zip_source_write(_source, &c, sizeof(int));
}

主文件

Zip::Source src;

src << "Some text and a number : " << 2.5 << std::endl;
src << "another line !";

// zip is an object of class Zip that takes my source and write it in the archive
zip.addFile("test.txt", src);

如果我std::endl在我的主目录中删除,文本文件将被识别为文本文件。如果我添加它,它会被识别为二​​进制文件。

二进制文件是有效的 utf-8 输出(NUL 字节除外):

496c 2065 7374 2070 6f73 7369 626c 6520
6427 c3a9 6372 6972 6520 6465 7320 6e6f
6d62 7265 7320 c3a0 2076 6972 6775 6c65
203a 2032 2e35 0a00 0000 736f 6d65 7468
696e 6720 656c 7365 

谢谢!

4

2 回答 2

12

您实现overflow()如下:

int Zip::Source::_ZipBuffer::overflow(int c) {
   return zip_source_write(_source, &c, sizeof(int));
}

您的 C++ 库显然实现了std::endl,通过调用作为参数传递。overflow()'\n'

这完全符合 C++ 规范。您的 overflow() 实现有一个错误。

参数 tooverflow()是单个字符,作为int. 您的实现将整个二进制文件写入int输出文件,这正是您所看到的。显然,您sizeof(int)是 4,因此您会看到0x0a另外三个空字节写入输出。

于 2017-12-26T17:49:55.773 回答
2

好的,刚刚发现问题...

在我写的 std::streambuf::overflow 重载中,当我收到一个字符时,我正在写一个整数。所以我的 int 中的前导 0 被写入文件中。

我不得不将我的 int 转换为 char 并且问题消失了:)

于 2017-12-26T17:49:43.213 回答