用C++从文件中读取字符串

Reading a string from a file in C++

本文关键字:读取 字符串 文件 C++      更新时间:2023-10-16

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

#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;
}

第二部分是当我试图阅读它时,事情会失控的地方。很抱歉,如果以前有人问过,我已经四处寻找类似的问题,但大多数问题都与我想做的有点不同,或者我真的不明白他们想做什么(对此仍然很陌生)。

我做错了什么

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

由于可以在http://www.cplusplus.com/reference/iostream/istream/read/,您使用的类型是错误的,您知道这一点,因为您必须使用reinterpret_caststd::string强制转换为char *

C++提示:在C++中使用reinterpret_cast(几乎)总是你做错了什么的标志

为什么读取文件如此复杂

很久以前,读取文件很容易。在一些类似Basic的语言中,您使用了函数LOAD,并且voilà ,你有你的档案。为什么我们现在不能做呢?

因为你不知道文件里有什么

  • 它可能是一根绳子
  • 它可以是一个序列化的结构数组,其中包含从内存转储的原始数据
  • 它甚至可以是一个实时流,也就是说,一个连续附加的文件(日志文件、stdin等等)
  • 你可以逐字逐句地阅读数据
  • 。。。或者一行一行
  • 或者文件太大,无法放入字符串,所以您希望分部分读取
  • 等等

更通用的解决方案是使用get函数以字节为单位读取文件(因此,在C++中是一个fstream)(请参阅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的"加载"函数

好的,我明白了。

我们假设您在文件中放入的是std::string的内容,但要使其与C样式字符串兼容,即字符标记字符串的末尾(如果不是,则需要加载文件,直到到达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 ""
        std::getline(file, p_content, '') ;
        // 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 CCCnDDD EEE FFFnn") ;
    {
        const bool success = saveFile(name, content) ;
        std::cout << "saveFile("" << name << "", "" << content << "")nn"
                  << "result is: " << success << "n" ;
    }
    {
        std::string myContent ;
        const bool success = loadFile(name, myContent) ;
        std::cout << "loadFile("" << name << "", "" << content << "")nn"
                  << "result is: " << success << "n"
                  << "content is: [" << myContent << "]n"
                  << "content ok is: " << (myContent == content)<< "n" ;
    }
}

更多

如果您想做更多的工作,那么您需要探索C++IOStreams库API,位于http://www.cplusplus.com/reference/iostream/

不能使用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, '')) {
     ...
}

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

std::ostringstream out;
std::ifstream      file("whatever");
out << file.rdbuf();
std::string str = out.str();

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

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

可能是你问题的根源。

尝试应用以下更改:

char[BUFF_LEN] ghhh;
....
ifs.read(ghhh, BUFF_LEN);