3

我正在尝试将字符串直接存储到文件中以便稍后在 C++ 中读取(基本上对于完整范围,我试图将带有字符串变量的对象数组存储在文件中,并且这些字符串变量将通过对象之类的东西读取[0].字符串)。但是,每次我尝试读取字符串变量时,系统都会给我一个混乱的错误。以下代码是我正在尝试的基本部分。

#include <iostream>
#include <fstream>
using namespace std;

/*
//this is run first to create the file and store the string
int main(){
    string reed;
    reed = "sees";
    ofstream ofs("filrsee.txt", ios::out|ios::binary);
    ofs.write(reinterpret_cast<char*>(&reed), sizeof(reed));
    ofs.close();

}*/

//this is run after that to open the file and read the string
int main(){
    string ghhh;
    ifstream ifs("filrsee.txt", ios::in|ios::binary);
    ifs.read(reinterpret_cast<char*>(&ghhh), sizeof(ghhh));
    cout<<ghhh;
    ifs.close();
    return 0;
}

第二部分是当我尝试阅读时事情变得混乱的地方。抱歉,如果之前有人问过,我已经环顾四周寻找类似的问题,但其中大多数与我想要做的有点不同,或者我不太明白他们想要做什么(仍然很新的)。

4

3 回答 3

6

我究竟做错了什么?

您正在从文件中读取数据并尝试将数据放入字符串结构本身,然后覆盖它,这是完全错误的。

正如可以在http://www.cplusplus.com/reference/iostream/istream/read/上进行验证的那样,您使用的类型是错误的,并且您知道这一点,因为您必须std::string使用.char *reinterpret_cast

C++ 提示:在 C++ 中使用 a reinterpret_cast(几乎)总是表明你做错了什么。

为什么读取文件如此复杂?

很久以前,读取文件很容易。在一些类似 Basic 的语言中,您使用了 function LOAD瞧!,你有你的文件。那么为什么我们现在不能这样做呢?

因为你不知道文件中有什么。

  • 它可能是一个字符串。
  • 它可能是一个序列化的结构数组,其中包含从内存中转储的原始数据。
  • 它甚至可以是实时流,即连续附加的文件(日志文件、标准输入等)。
  • 您可能希望逐字读取数据
  • ...或逐行...
  • 或者文件太大以至于无法放入字符串中,因此您想分部分读取它。
  • ETC..

更通用的解决方案是读取文件(因此,在 C++ 中,一个 fstream),使用函数 get 逐字节读取(参见http://www.cplusplus.com/reference/iostream/istream/get/),然后执行自己操作将其转换为您期望的类型,并在 EOF 处停止。

std::isteam接口具有以不同方式读取文件所需的所有功能(请参阅http://www.cplusplus.com/reference/iostream/istream/std::string ),即便如此,还有一个额外的非成员函数读取文件直到找到分隔符(通常是“\n”,但它可以是任何东西,请参阅http://www.cplusplus.com/reference/string/getline/

但我想要一个“加载”功能std::string

好的我明白了。

我们假设您放入文件中的是 a 的内容std::string,但要使其与 C 风格的字符串兼容,即\0字符标记字符串的结尾(如果不是,我们需要加载文件直到到达EOF)。

loadFile我们假设您希望函数返回后完全加载整个文件内容。

所以,这里的loadFile功能:

#include <iostream>
#include <fstream>
#include <string>

bool loadFile(const std::string & p_name, std::string & p_content)
{
    // We create the file object, saying I want to read it
    std::fstream file(p_name.c_str(), std::fstream::in) ;

    // We verify if the file was successfully opened
    if(file.is_open())
    {
        // We use the standard getline function to read the file into
        // a std::string, stoping only at "\0"
        std::getline(file, p_content, '\0') ;

        // We return the success of the operation
        return ! file.bad() ;
    }

    // The file was not successfully opened, so returning false
    return false ;
}

如果您使用的是启用 C++11 的编译器,则可以添加这个重载函数,这不会花费您任何费用(而在 C++03 中,进行优化,它可能会花费您一个临时对象):

std::string loadFile(const std::string & p_name)
{
    std::string content ;
    loadFile(p_name, content) ;
    return content ;
}

现在,为了完整起见,我编写了相应的saveFile函数:

bool saveFile(const std::string & p_name, const std::string & p_content)
{
    std::fstream file(p_name.c_str(), std::fstream::out) ;

    if(file.is_open())
    {
        file.write(p_content.c_str(), p_content.length()) ;

        return ! file.bad() ;
    }

    return false ;
}

在这里,我用来测试这些功能的“主要”:

int main()
{
    const std::string name(".//myFile.txt") ;
    const std::string content("AAA BBB CCC\nDDD EEE FFF\n\n") ;

    {
        const bool success = saveFile(name, content) ;
        std::cout << "saveFile(\"" << name << "\", \"" << content << "\")\n\n"
                  << "result is: " << success << "\n" ;
    }

    {
        std::string myContent ;
        const bool success = loadFile(name, myContent) ;

        std::cout << "loadFile(\"" << name << "\", \"" << content << "\")\n\n"
                  << "result is: " << success << "\n"
                  << "content is: [" << myContent << "]\n"
                  << "content ok is: " << (myContent == content)<< "\n" ;
    }
}

更多的?

如果您想做更多的事情,那么您需要探索 C++ IOStreams 库 API,网址为http://www.cplusplus.com/reference/iostream/

于 2012-09-09T15:38:38.910 回答
4

你不能std::istream::read()用来读入一个std::string对象。您可以做的是确定文件的大小,创建一个合适大小的字符串,并将数据读入字符串的字符数组:

std::string str;
std::ifstream file("whatever");
std::string::size_type size = determine_size_of(file);
str.resize(size);
file.read(&str[0], size);

棘手的一点是确定字符串应该具有的大小。鉴于字符序列可能在读取时被翻译,例如,因为行尾序列被转换,这几乎相当于在一般情况下读取字符串。因此,我建议不要这样做。相反,我会使用以下内容读取字符串:

std::string   str;
std::ifstream file("whatever");
if (std::getline(file, str, '\0')) {
     ...
}

这适用于文本字符串,并且与大多数系统上的速度一样快。如果文件可以包含空字符,例如,因为它包含二进制数据,那么这并不完全有效。如果是这种情况,我会使用中间std::ostringstream

std::ostringstream out;
std::ifstream      file("whatever");
out << file.rdbuf();
std::string str = out.str();
于 2012-09-09T15:45:16.877 回答
0

字符串对象不仅仅是一个字符数组,行

ifs.read(reinterpret_cast<char*>(&ghhh), sizeof(ghhh));

可能是你问题的根源。

尝试应用以下更改:

char[BUFF_LEN] ghhh;
....
ifs.read(ghhh, BUFF_LEN);
于 2012-09-09T15:39:19.463 回答