Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/109.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 带有gzstream lib last char的rapidjson'-1';_C++_Ios_Xcode_Zlib_Rapidjson - Fatal编程技术网

C++ 带有gzstream lib last char的rapidjson'-1';

C++ 带有gzstream lib last char的rapidjson'-1';,c++,ios,xcode,zlib,rapidjson,C++,Ios,Xcode,Zlib,Rapidjson,我已经编写了gzstream 1.5的简单包装器,用于rapidjson 0.1(ios,xcode 6.1) 问题:我必须在Peek()和Take()中检查eof。否则,我得到'\377'(-1)作为最后一个字符。我知道它是由eof的std::basic_stream::get()返回的 还有什么更优雅、更合适、更干净的解决方案 class GzOutStream { public: GzOutStream(std::string filename) : gs_(new ogzstre

我已经编写了gzstream 1.5的简单包装器,用于rapidjson 0.1(ios,xcode 6.1)

问题:我必须在Peek()和Take()中检查eof。否则,我得到'\377'(-1)作为最后一个字符。我知道它是由eof的std::basic_stream::get()返回的

还有什么更优雅、更合适、更干净的解决方案

class GzOutStream {
public:
    GzOutStream(std::string filename) : gs_(new ogzstream(filename.c_str())) {}
    bool Good() { return gs_->good(); }
    void Close() { delete gs_; gs_ = nullptr; }
    size_t Tell() { return gs_->tellp(); }
    void Put(char c) { gs_->put(c); }

    // Not implemented
    char* PutBegin() { return 0; }
    size_t PutEnd(char*) { return 0; }

private:
    ogzstream* gs_;
};

class GzInStream {
public:
    GzInStream(std::string filename) : gs_(new igzstream(filename.c_str())) {}
    bool Good() { return gs_->good(); }
    void Close() { delete gs_; gs_ = nullptr; }
    char Peek() { return gs_->eof()? '\0' : gs_->peek(); }
    char Take() { return gs_->eof()? '\0' : gs_->get(); }
    size_t Tell() { return gs_->tellg(); }
    void Put(char c) { } // Stab

    // Not implemented
    char* PutBegin() { return 0; }
    size_t PutEnd(char*) { return 0; }

private:
    igzstream* gs_;
};

下面提供的答案用于对当前问题的一般性讨论。我当时没有看rapidjson的行为

您的类旨在成为gzip输入流和rapidjson之间的粘合逻辑,因此您必须实现rapidjson所期望的接口。它甚至没有很好的功能。rapidjson期望的接口在EOF上返回“\0”,因此这是您必须执行的唯一选择。如果使用的GZIP流类正在实现C++流模型,则可以使用“示例ISTRAIM包装器”中描述的模式,该模式以通常与C++ IOFSUBLE一起工作的方式进行EOF检测。如果您当前的方式可以很好地处理gz流,那么您也可以保持原样


您基本上遇到了一个问题,即只要您没有尝试通过eof,输入流就会保持良好状态。GzInStream的接口不向用户提供任何可能性来检测在偷窥或偷拍返回无效值之前是否已命中EOF。这是由于C++ IoSokes的设计:大多数时候,除非您尝试通过它,否则低级API不指示“流结束”,因此高级API不提供这种功能,因为在许多(非文件)情况下实现是不平凡的。

标准C++ +流的PEEK(和)(和)(函数)返回“代码> INT/COME”而不是< Case> char < /代码>,原因是:它们指定返回从流中读取的字节作为正数量(在8位字节的系统上0…255),同时返回EOF(-1)错误。Peek和Get函数无法将256个不同的字节和EOF作为不同的返回值返回,因为有257种可能性无法用字符表示。因此,从Peek或Take中获取角色后,界面的客户端必须询问“Good()”,以确定是否真的需要获取角色。如果接口的客户端执行此操作,则返回“\377”或“\0”或任何其他值都无关紧要,因为该值无论如何都将被忽略。使用那个“额外”字节的客户端(在我看来)是有缺陷的,除非它被设计成忽略您返回的伪NUL字节

你可以用不同的方法解决这个问题

  • 如上所述修复您的客户机,并记录该类的行为
  • Have Good()return
    gs\uu->Good()!gs->eof()
  • 像标准iostream一样,从Peek和Take返回int
  • 从Peek and Take返回boost::optional,如果遇到eof,则返回boost::none
  • 在EOF的情况下抛出一个异常表单Peek和Take

大多数人会立即拒绝上一次建议的修复,因为它违反了“异常不应用于流控制”规则。我同意强制客户机使用异常处理来检测EOF是非常糟糕的风格,但事实上,这是唯一不需要更改Peek和Take签名,也不需要更改其他函数语义的可能性。我希望第二个建议(更改为“好”)是您用例中的方法。

谢谢您提供了一个非常清晰的答案。但是,我不想编辑rapidjson的代码。答案已经更新,包含了专门针对rapidjson中的用例的一部分,它基本上告诉您,您发布的代码可能会让您觉得可疑,但这是您需要遵守rapidjson预期行为的内容。