2011-09-16 68 views
6

我在我的MFC应用程序中使用std :: string,我想将它存储在doc的Serialize()函数中。我不想将它们存储为CString,因为它将自己的东西写入其中,我的目标是创建一个文件,我知道其他应用程序的格式并可以在不需要CString的情况下读取它。所以我想将我的std :: strings存储为4个字节(int)的字符串长度,接着是包含字符串的那个大小的缓冲区。我可以重载CArchive <<运算符以使用std :: string吗?

void CMyDoc::Serialize(CArchive& ar) 
{ 
    std::string theString; 

    if (ar.IsStoring()) 
    { 
     // TODO: add storing code here 
     int size = theString.size(); 
     ar << size; 
     ar.Write(theString.c_str(), size); 

    } 
    else 
    { 
     // TODO: add loading code here 
     int size = 0; 
     ar >> size; 
     char * bfr = new char[ size ]; 
     ar.Read(bfr, size); 
     theString = bfr; 
     delete [] bfr; 
    } 
} 

上面的代码也不是很大,我必须分配一个临时BFR阅读的字符串。首先,我可以直接将字符串读入不带临时缓冲区的std :: string中?其次,我可以重载std :: string/CArchive缓冲区的<,所以我可以简单地使用ar < < theString?总体来说有更好的方法来读/写使用CArchive对象的std :: string吗?

回答

0

如果您正在使用仅适用于c风格字符串的库,则无法安全地write directly to the std::string。该问题已在C++ 0x中修复。 因此,像

// NOT PORTABLE, don't do this 
theString.resize(size); 
ar.Read(const_cast<char *>(theString.c_str(), size); 

可能会工作,但它可能以后产生一些微妙的,难以跟踪的错误。 当然你的问题意味着你已经对你的代码进行了剖析,并发现创建缓冲区和两次复制数据实际上是你的代码中的一个瓶颈。如果你还没有,那么你不应该对效率低下感到担忧。

+0

我试过这个,但c_str()返回'const char *',这是一个问题。我可能可以将它转换为简单的'char *',但这会违反c_str()函数。 – zar

+1

因此,“不要这样做”的评论。你可以使用'std :: vector '或者因为你在MFC土地使用'CString' – AJG85

1

尝试:

theString.resize(size); 
ar.Read(&theString[0], size); 

技术上&theString[0]不保证指向一个连续的字符缓冲区,但C++委员会做了一个调查,发现所有现有的实现以这种方式工作。

0

我想你可能违反STL指导原则,继承std::string并添加你自己的缓冲区获取器/设置器。然后覆盖std :: string的拷贝构造函数并转移缓冲区的所有权。

1

你可以从你的stl字符串建立一个就地CString并且序列化它。喜欢的东西:

CString c_string(my_stl_string.c_str(); 
ar << c_string; 

你可以从任何地方把它放进一个全球性的算子超载因此它可以你可以

ar << my_c_string; 

如:

CArchive& operator<<(CArchive rhs, string lhs) { 
    CString c_string(lhs.c_str()); 
    rhs << c_string; 
} 
1

它可能更好地写入数据作为一个CString的各种原因,但如果你必须将您的字符串(m_sString)转换为ASCII字符串,也许这样的事情会为你工作...

void myclass::Serialize(CArchive & ar) 
{ 
    CHAR* buf; 
    DWORD len; 
    if (ar.IsStoring()) // Writing 
    { 
     len = m_sString.GetLength(); // Instead of null terminated string, store size. 
     ar << len; 
     buf = (CHAR*)malloc(len); 
     WideCharToMultiByte(CP_UTF8, 0, m_sString, len, buf, len, NULL, NULL); // Convert wide to single bytes 
     ar.Write(buf, len); // Write ascii chars 
     free(buf); 
    } 
    else // Reading 
    { 
     ar >> len; 
     buf = (CHAR*)malloc(len); 
     ar.Read(buf, len); // Read ascii string 
     MultiByteToWideChar(CP_UTF8, 0, buf, len, m_sString.GetBufferSetLength(len), len); // Convert ascii bytes to CString wide bytes 
     free(buf); 
    } 
}