使用 fstream 读取文件

Reading a file using fstream

当我尝试将文件读取到缓冲区时,它总是将随机字符附加到缓冲区的末尾。

char* thefile;
    std::streampos size;

    std::fstream file(_file, std::ios::in | std::ios::ate);
    if (file.is_open())
    {
        size = file.tellg();
        std::cout << "size: " << size;
        thefile = new char[size]{0};

        file.seekg(0, std::ios::beg);
        file.read(thefile, size);
        std::cout << thefile;
    }

    int x = 0;

而我文件中的原文是:"hello" 输出变为:"helloýýýý««««««««þîþîþ"

谁能帮我看看这是怎么回事?谢谢

这里有一个更好的阅读方式collection:

#include <vector>
#include <fstream>
#include <iostream>
#include <sstream>
#include <string>
#include <cstdint>
#include <iterator>

template<class T>
void Write(std::string const & path, T const & value, std::ios_base::openmode mode)
{               
    if (auto stream = std::ofstream(path, mode))
    {
        Write(stream, value);

        stream.close();
    }
    else
    {
        throw std::runtime_error("failed to create/open stream");
    }       
}

template<class T>
void Write(std::ostream & stream, T const & value)
{
    std::copy(value.begin(), value.end(), std::ostreambuf_iterator<char>(stream));

    if (!stream)
    {
        throw std::runtime_error("failed to write");
    }
}

template<class T>
void Read(std::istream & stream, T & output)
{
    auto eof = std::istreambuf_iterator<char>();

    output = T(std::istreambuf_iterator<char>(stream), eof);

    if(!stream)
    {
        throw std::runtime_error("failed to read stream");
    }
}

template<class T>
void Read(std::string const & path, T & output)
{               
    if (auto stream = std::ifstream(path, std::ios::in | std::ios::binary))
    {
        Read(stream, output);

        stream.close();
    }
    else
    {
        throw std::runtime_error("failed to create stream");
    }           
}


int main(void)
{
    // Write and read back text.

    {
        auto const s = std::string("I'm going to write this string to a file");

        Write("temp.txt", s, std::ios_base::trunc | std::ios_base::out);

        auto t = std::string();

        Read("temp.txt", t);
    }

    // Write and read back a set of ints.

    {
        auto const v1 = std::vector<int>() = { 10, 20, 30, 40, 50 };

        Write("temp.txt", v1, std::ios_base::trunc | std::ios_base::out | std::ios_base::binary);

        auto v2 = std::vector<int>();

        Read("temp.txt", v2);
    }

    return 0;
}

传入可迭代容器而不是使用 "new"。

如果文件不是用 ios::binary 模式打开的,您不能假设 tellg() 返回的位置会给出您将读取的字符数。文本模式操作可能会对流进行一些转换(f.ex:在windows上,它将转换“\n”中文件中的“\r\n”,因此您可能会发现一个大小共 2 个但只读 1)

无论如何,read() 不会添加空终止符。

最后,由于必须添加空终止符,您必须分配比预期大小多一个字符。否则,当您添加它时,您将面临缓冲区溢出的风险。

您应该验证实际上有多少个字符 read with gcount(),并相应地为您的字符串设置空终止符。

   thefile = new char[size + 1]{0};  // one more for the trailing null  
   file.seekg(0, std::ios::beg);
   if (file.read(thefile, size))
      thefile[size]=0;               // successfull read:  all size chars were read
   else thefile[file.gcount()]=0;   // or less chars were read due to text mode

来自 C++ 文档:http://cplusplus.com/reference/istream/istream/read

"This function simply copies a block of data, without checking its contents nor appending a null character at the end."

因此您的字符串遗漏了表示字符串结尾的尾随空字符。在这种情况下,cout 将继续打印内存中 thefile 之外的字符。

在字符串末尾添加 '[=12=]'