如何将 istream * 转换为字符串或直接打印它?

10
下面是Connector/C++的一个函数,它返回一个istream*类型的值。如果我试图直接打印它,会显示十六进制或内存地址,因为它是一种指针类型。
istream *stream = res->getBlob(1);

我尝试使用以下方法读取并打印它:

    string s; 
    while (getline(*stream, s))
    cout << s << endl; 

但是这样会导致访问冲突。还有其他方法可以打印它或将其转换为字符串吗?

在getline之前,stream的值为:

  • stream 0x005f3e88 {_Chcount=26806164129143632} std::basic_istream > *

所以对我来说似乎是有效的。如果失败了,我认为它将为null或0。


是的,我认为很好,我在我的更新中发布了它在观察变量位置所说的内容。 - user1397417
我并没有看出这个崩溃问题的原因:在 res->getBlob(1) 和调用 getline(*stream, s) 之间发生了什么?返回 std::istream* 很奇怪,因为它们相对昂贵,并且如果流不由 resres 指向的某些东西拥有,则似乎会导致内存泄漏。 - Dietmar Kühl
res->getBlob(1)getline(*stream, s) 之间没有任何东西。 - user1397417
2个回答

14
您可以通过使用流缓冲区来提取和打印std::istream
std::cout << in->rdbuf();

当然,这将会消耗输入流并且你可能无法再次获取它。如果你想保留内容,可以将其写入 std::ostringstream 中,并使用 str() 方法打印内容。或者,你也可以直接从流构造一个 std::string,例如:

std::string content{ std::istreambuf_iterator<char>(*in),
                     std::istreambuf_iterator<char>() };

顺便提一下,当你打印流指针时,实际上使用了 void const* 的输出运算符:它会打印指针所引用的地址。在 C++03 中,甚至可以通过使用 std::istream 读取 void* 来恢复对应打印的指针:只要所指向的对象没有被删除,你就可以通过这种方式获得一个指针!然而,在 C++11 中,指针隐藏是被禁止的,以支持未来可能添加到语言中的可选垃圾回收。非隐藏指针的保证也有助于成员调试器。


当我用我的while getline尝试替换std::cout << in->rdbuf();这一行时,它仍然会崩溃。两者都以访问冲突的方式崩溃。而且我对你提到的其他尝试方法并不太理解。 - user1397417
@user1397417:我没有看到它实际上会崩溃,所以回答了标题上的问题。另一种方法可能会以相同的方式崩溃。这意味着在您尝试使用它时,流可能已被销毁!在您获取流和使用它之间发生了什么?我猜您使结果无效了,例如通过移动到下一个元素或将流保留到以后。 - Dietmar Kühl
@user1397417:您尝试访问的字段的数据库类型是什么? - Dietmar Kühl
我的两个代码块之间没有任何东西。所选列的数据库结构为“英语 varchar(225) utf8_bin”。 - user1397417
@user1397417:看源代码,函数getBlob()实际上返回一个新的std::istringstream(在使用后需要确保被删除...假设使用得到解决...)。我能想到的一件事是,用于MySQL连接器和你的构建的标准C++库实际上是不同的:如果您应该验证两者是否使用完全相同版本的标准C++库进行构建。 - Dietmar Kühl
我卸载了所有的MySQL并重新下载了最新版本尝试再次构建。它提示找不到boost库,所以我安装了boost,然后它就成功构建和运行而没有崩溃。现在似乎一切正常。 - user1397417

1
您可以在while循环中使用std::getline函数来显示istream中的数据。这里是一个我运行过并且正确工作的示例:
#include <iostream>
#include <sstream>
#include <istream>
#include <string>

int main()
{

 std::stringstream s1("This is a test string\nWith two lines");
 std::istream s2(s1.rdbuf()); //just creates the istream to start with 

 std::string stt; 
 while(std::getline(s2,stt)) //can also have delimiter in getline 
 {                           
   std::cout<<stt<<std::endl;  
 }

 return 0;
}

运行它,它会显示:
This is a test string
With two lines

我也尝试过这种方法,使用了指向istream的指针,就像你所做的那样:
#include <iostream>
#include <sstream>
#include <istream>
#include <string>

int main()
{
  std::stringstream s1("This is a test string\nWith three lines);
  std::istream s2(s1.rdbuf()); //just creates istream to start with 
  std::istream *s3 = &s2; //and use a pointer to istream like code at top

  std::string stt;
  while(std::getline(*s3,stt,'\n')) 
  {                          
    std::cout<<stt<<std::endl; //result.  
  }

  return 0;
}

这段代码运行后,结果和我在不使用指针时得到的结果相同。我无法重现你的错误。因此,问题似乎出在你创建istream时(例如,istream *stream = res->getBlob(1);)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接