【问题标题】:reading non-text file in c++在 C++ 中读取非文本文件
【发布时间】:2021-07-24 05:42:20
【问题描述】:

我用记事本++(打开方式)错误地打开了 mp3 文件,并在记事本中以文本形式显示了整个文件,这太酷了。 因为我又在学习 c++,所以我告诉自己让我们编写一个程序,在控制台中打开任何文件并在控制台上显示它们的内容,所以我开始我的代码是这样的:

int readAndWrite() {

    string filename(R"(path\to\a\file)");

    ifstream file(filename);



    string line;

    if (!file.is_open()) {
        cerr << "Could not open the file - '"
             << filename << "'" << endl;
        return EXIT_FAILURE;
    }

    while (getline(file, line)){
        cout << line;
    }

    return EXIT_SUCCESS;
}

但它只显示文件的 3 或 4 行然后退出程序我再次检查我的记事本++,发现那里有大约 700,000 行。 我告诉自己文件中可能有一个字符,所以我开始编写上面的代码并进行以下更改。而不是显示文件,让我们写在一个文本文件中。

int readAndWrite() {

    string filename(R"(path\to\a\file)");
    string filename2(R"(path\to\a\file\copy)");

    ifstream file(filename);
    ofstream copy(filename2);


    string line;

    if (!file.is_open()) {
        cerr << "Could not open the file - '"
             << filename << "'" << endl;
        return EXIT_FAILURE;
    }

    while (getline(file, line)){
        copy << line;
    }

    return EXIT_SUCCESS;
}

同样的结果。下次尝试我放弃逐行读取文件,所以我开始使用此功能进行复制。

void copyStringNewFile(ifstream& file, ofstream& copy)
{
    copy << file.rdbuf();
}

他们的结果并没有改变。 在这一点上,我告诉自己问题可能来自文件,这有点是因为当我使用简单的文本文件时,上述所有代码都可以工作。

【问题讨论】:

  • 只是一种预感,但是如果将ifstream file(filename); 更改为ifstream file(filename, std::ios::binary); 会有所不同吗?
  • 无论如何,path\to\a\file\copy 将不起作用,因为file 不是目录。
  • 可能是 MP3 文件里面有一个 EOF 字符,你试过在不同的文件上运行它吗?也许是一些包含几行普通文本的简单文本文件?
  • @jamit /@/ted-lyngmo 不,ios::binary 和复制文件之间没有区别,即使我删除它也是如此。

标签: c++ file c++14


【解决方案1】:

与所有其他非文本文件一样,mp3 文件不包含 ,因此您不应使用 std::getline。使用istream::readostream::write。您可以使用istream::gcount 来检查实际读取了多少个字符。

由于您处理的是非文本文件,因此也以binary 模式打开文件。

您还应该测试打开这两个文件是否有效 - 即输入和输出文件。

例子:

#include <cerrno>
#include <cstring>
#include <fstream>
#include <iostream>

int readAndWrite() {
    std::string filename(R"(path\to\a\file)");
    std::string filename2(R"(path\to\a\file_copy)");

    std::ifstream file(filename, std::ios::binary);
    if(!file) {
        std::cerr << '\'' << filename << "': " << std::strerror(errno) << '\n';
        return EXIT_FAILURE;
    }

    std::ofstream copy(filename2, std::ios::binary);
    if(!copy) {
        std::cerr << '\'' << filename2 << "': " << std::strerror(errno) << '\n';
        return EXIT_FAILURE;
    }

    char buf[1024];
    while(file) {
        file.read(buf, sizeof(buf));
        // write as many characters as was read above
        if(!copy.write(buf, file.gcount())) {
            // write failed, perhaps filesystem is full?
            std::cerr << '\'' << filename2 << "': " << std::strerror(errno) << '\n';
            return EXIT_FAILURE;
        }
    }

    return EXIT_SUCCESS;
}

int main() {
    return readAndWrite();
}

【讨论】:

  • 谢谢,但我再次测试您的代码,只复制了几行。原始文件为 1mb,复制文件约为 1kb
  • @Milad 没有。此代码应该生成您从中读取的文件的精确副本。您确定您查看的不是输出文件的旧副本吗?
  • 我将您的代码复制粘贴到我的主程序中,结果正如我所说,原始文件超过 1Mb,但复制文件约为 322 字节
  • @Milad 请先删除复制文件并重新运行程序。顺便说一句,你的文件系统满了吗?我在循环中添加了一个新测试。
  • 谢谢,它需要一个干净的重建和工作。你从哪里得到 buf[1024] 我读了一个教程,他用了 buf[4096]
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-10-10
  • 1970-01-01
  • 2014-06-22
  • 2016-11-07
  • 1970-01-01
相关资源
最近更新 更多