将文件转换为char *问题

时间:2015-10-31 17:02:23

标签: c++ string file stream

我是C ++编程的初学者,我遇到了一个问题。 我希望能够将文件的内容转换为char *,并且我使用了文件和字符串流。但是,它无法正常工作。

这是我完成工作的功能:

char* fileToChar(std::string const& file){

    std::ifstream in(file);
    if (!in){
        std::cout << "Error: file does not exist\n"; 
        exit(EXIT_FAILURE);
    }

    std::stringstream buffer;
    buffer << in.rdbuf() << std::flush;
    in.close();

    return const_cast<char *>(buffer.str().c_str());
}

但是,当我通过将其内容输出到另一个文件来测试方法时,这样:

std::ofstream file("test.txt");
file << fileToChar("fileTest.txt");

我只是得到了很多像这样的奇怪角色:

îþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþ[...etc]

这到底发生了什么?我错过了什么吗? 如果有更好的方法,我会很高兴知道!

3 个答案:

答案 0 :(得分:4)

return const_cast<char *>(buffer.str().c_str());

返回指向本地stringstream的内部缓冲区的临时副本的内部char缓冲区的指针。长话短说:退出函数后,此指针指向垃圾。

顺便说一下,即使这不是问题,const_cast也是危险的废话,你不能通过指针std::string::c_str返回。 const_cast的合法使用非常罕见。

以更好的方式:最好和最简单的方法是返回std::string。只有在不允许的情况下,std::vector<char>(首选)或new char[somelength](不赞成)才是可行的解决方案。

答案 1 :(得分:3)

char* fileToChar(std::string const& file){

这一行已经表明事情正朝着错误的方向发展。你返回一个指向某个字符串的指针,如果必须释放它,如果可以返回nullptr那么,对于负责释放已分配内存的函数的用户来说,它是完全不清楚的,等等。

如果你想要一个字符串,那么一定要使用std::string

std::string fileToChar(std::string const& file){
return const_cast<char *>(buffer.str().c_str());

应该使所有警报响起的另一条线。 const_cast始终是解决某些潜在问题(或外部代码的某些问题)的解决方法。

通常有一个很好的理由为什么是const。通过强制编译器关闭安全检查并允许它尝试修改不可修改的数据,通常会将编译错误转换为难以诊断的运行时错误。

即使如果此函数正常工作,任何修改结果的尝试都将是未定义的行为:

char* file_contents = fileToChar("foo.txt");
file_contents[0] = 'x'; // undefined behaviour

但无论如何它都无法正常工作。 buffer.str()会返回临时 std::string对象。 c_str()返回指向该临时对象内部管理内存的指针。对象的生命周期在评估完整表达式return const_cast<char *>(buffer.str().c_str())时结束。因此,使用结果指针也是未定义的行为。

问题听起来很复杂,但修复很容易。使函数返回std::string并将最后一个语句转换为return buffer.str();

答案 2 :(得分:-1)

如果您的问题是,如何将文件内容读入缓冲区,请考虑以下建议。但要注意缓冲区对于文件内容来说足够大。在调用fileToChar()之前,建议对文件大小进行检查并预先分配内存。

bool fileToChar(std::string const& file, char* buffer, unsigned int &buffer_size )
{
    FILE *f = fopen( file.c_str(), "rb" );

    if( f == nullptr )
    {
        return false;
    }

    fseek(f , 0, SEEK_END );

    const int size = ftell( f );

    rewind( f );
    fread( buffer, 1, size, f );
    fclose( f );

    return true;
}