在ostream上使用std :: endl使我的文件成为二进制文件

问题描述 投票:5回答:2

我正在开发一个使用libzip的项目。我在c ++ 14工作,我在libzip周围写了一个小包装,让我的生活更轻松。

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

一切都很好,直到我使用std::endl。当我这样做时,输出文件被我的所有文本阅读器读取为二进制文件(仅写入字符串)。

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

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

我的代码(提取它可能不完全相同)。

source.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);
};

source.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));
}

main.cpp中

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);

如果我删除了main中的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 

谢谢!

c++ c++14 ostream streambuf libzip
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()实现有一个bug。

overflow()的参数是单个字符,作为int传递。您的实现将整个二进制int写入输出文件,这正是您所看到的。你的sizeof(int)显然是4,所以你看到0x0a和三个空字节写入输出。


2
投票

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

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

我不得不把我的int转换为char,问题消失了:)

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