【问题标题】:writing files and dirs using C++使用 C++ 编写文件和目录
【发布时间】:2009-08-18 10:10:41
【问题描述】:

我正在开发一个程序,该程序创建 2000 个目录并在每个目录中放置一个文件(只有 10KB 左右的文件)。我正在使用 mkdir 制作 dirs 和 ofstream(我也尝试过 fopen)将文件写入固态驱动器(我正在做速度测试以进行比较)。

当我运行代码时,目录创建良好,但文件在写入 1000 左右后停止写入。我尝试在每次写入之前设置延迟,以防它出现某种过载,并且还尝试使用 fopen 而不是 ofstream,但它总是在第 1000 个文件标记附近停止写入文件。

这是写入文件并退出的代码,告诉我它在哪个文件上失败了。

fsWriteFiles.open(path, ios::app); 
if(!fsWriteFiles.is_open()) 
{
   cout << "Fail at point: " << filecount  << endl; 
   return 1;
}
fsWriteFiles << filecontent;
fsWriteFiles.close();

有没有人有这方面的经验或有任何理论?

以下是完整代码: 此代码从一个随机数创建一个 2 位十六进制目录,然后从一个随机数创建一个 4 位十六进制目录,然后在该目录中存储一个文件。 在写入 1000 个文件后,它以“点失败”(我添加的一个 cout)退出。 这表明它无法创建文件,但它应该已经检查过该文件不存在。 有时它在 0 上失败,从底线开始第二个(文件已经存在的 else 子句)。任何帮助表示赞赏,我觉得这与我正在尝试创建的已经存在的文件有关,但是这些文件在我的文件存在检查中不知何故滑倒了。 有没有办法为失败的文件创建尝试获取错误消息?

int main()
{
  char charpart1[3] = "";
  char charpart3[5] = "";

  char path[35] = "";
  int randomStore = 0;

  //Initialize random seed
  srand(time(NULL));
  struct stat buffer ;

  //Create output file streams
  ofstream fsWriteFiles;    
  ifstream checkforfile;

  //Loop X times
  int dircount = 0;
  while(dircount < 2000)
  {
    path[0] = '\0'; //reset the char array that holds the path

    randomStore = rand() % 255;
    sprintf(charpart1, "%.2x", randomStore);
    randomStore = rand() % 65535;
    sprintf(charpart3, "%.4x", randomStore);

    //Check if top level dir exists, create if not
    strcat(path, "fastdirs/");
    strcat(path, charpart1);
    DIR *pdir=opendir(path);

    //If the dir does not exist create it with read/write/search permissions for owner 
    // and group, and with read/search permissions for others
    if(!pdir)
      mkdir(path,  S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);

    //Check if 3rd level dir exists, create if not
    strcat(path, "/");
    strcat(path, charpart3);
    DIR *pdir3=opendir(path);

    if(!pdir3)
      mkdir(path,  S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);

    strcat(path, "/");
    strcat(path, charpart3);
    strcat(path, ".txt");
    //Write the file if it does not already exist
    checkforfile.open(path, fstream::in);

    if (checkforfile.is_open() != true)
    {
      fsWriteFiles.open(path, ios::app); 
      if(!fsWriteFiles.is_open()) 
      {
        cout << "Fail at point: " << dircount << "\n" << endl;
        return 1;
      }
      fsWriteFiles << "test";
      fsWriteFiles.flush();
      fsWriteFiles.close();

      dircount ++; //increment the file counter
    }
    else
    {
      cout << "ex";
      checkforfile.close();
    }
  } 
}

【问题讨论】:

  • 只是猜测,强制冲洗怎么样?
  • mkdir 是否可能失败?你检查过它的返回值吗?可能是内存损坏。
  • 感谢 Kenny & Goz,尝试了刷新但没有更改,还检查并正在创建目录。
  • 请发布更多上下文 - 循环、fsWriteFiles 的声明等。它一个 ofstream,而不是其他东西,不是吗?

标签: c++ mkdir ofstream


【解决方案1】:

您使用 opendir() 打开目录,但从不使用 closedir() 关闭它们 - 我怀疑那里也存在资源限制。

【讨论】:

  • 我花了很多时间重新格式化被破坏的代码,以便我可以阅读它,你比我强!
  • 我认为这显示了在 SO 上提问时发布 ACTUAL CODE 的价值。
  • 确实如此,以后我会全部发布,而不仅仅是我认为我错了,再次感谢
  • 请只发布你一开始认为错误的部分,这样我就不会浪费我的时间,因为你是对的
【解决方案2】:

你会关闭文件吗?听起来您达到了通常为 1024 的文件描述符限制。要进行简单检查,请尝试“ulimit -n 4096”并再次执行您的程序。

【讨论】:

  • 这听起来很有可能。不幸的是,我不允许使用 ulimit 命令。另外我正在关闭文件,我认为可能是文件关闭速度不够快,但我在每次打开之前都尝试了等待,但没有帮助。感谢您的建议。
  • @Columbo 你不需要 ulimit。要验证这个假设,请打开 100 个文件,但不要在现有代码之前关闭它们。然后看看故障是否发生得更早。
  • 经过测试。没有关闭前 100 个文件并且没有任何更改,仍然开始失败大约 1000 个写入的文件。
  • 这并没有真正进行测试。在开始循环之前,您需要打开但不关闭不属于循环的 100 个文件,然后查看在正常关闭的情况下可以在循环中打开多少个文件。
  • 我现在在循环之前添加了一个循环,您可以在我发布的代码中看到它创建 100 个新文件并且不会关闭它们。仍然无法正常工作(我正在编辑我的原始帖子显示所有代码。
【解决方案3】:

我看不出所发布的代码有任何明显错误,但您没有提供足够的上下文来帮助任何人。

但是,如果您使用 RAII 来确保文件已关闭,通过使用 ofstream 构造函数/析构函数来执行打开/关闭,我会更高兴:-

for (int i=0; i != MAX_FILES; ++i)
{     
  ofstream sWriteFiles(getFilePath(i), ios::app); 

  if (!fsWriteFiles.is_open()) 
  {
    cout << "Fail at point: " << filecount  << endl; 
    return 1;
  }

  fsWriteFiles << filecontent;
}

是的,您每次循环都在“构造”流对象,但我发现这段代码更易于维护。

【讨论】:

  • 从他的代码中,它没有显示循环,这正是他正在做的,对 close() 的额外(无害)调用。
  • @Neil - 可能 - 但如果他的 ofstream 在循环之外并“重复使用”N 次,我不会感到惊讶。每次都从“新鲜”的流开始,感觉稍微干净一些。我们还假设它是一个 ofstream,而不是一个带有损坏的“关闭”方法的派生类。
  • 我现在在尝试打开的正上方添加了 ofstream 创建语句 - 在相同的 1000 个文件中仍然失败图 if(!checkforfile.is_open()) { ofstream fsWriteFiles; fsWriteFiles.open(路径,ios::app); ...
  • @Columbo : 请编辑原始帖子以显示更多您的真实代码。我们无法再猜测你写了什么。
【解决方案4】:

只是想确保您知道boost::filesystem。它可能会大大简化您的代码。

#include "boost/filesystem.hpp"   // includes all needed Boost.Filesystem declarations
#include <iostream>               // for std::cout
using boost::filesystem;          // for ease of tutorial presentation;
                                  //  a namespace alias is preferred practice in real code

path my_path( "some_dir/file.txt" );

remove_all( "foobar" );
create_directory( "foobar" );
ofstream file( "foobar/cheeze" );
file << "tastes good!\n";
file.close();
if ( !exists( "foobar/cheeze" ) )
  std::cout << "Something is rotten in foobar\n";

【讨论】:

  • 这看起来很有趣,我要去看看。达斯汀。
  • Boost 是 C++,因此可以使用 dtors。这会在很多情况下拯救你,并且可能会在这里拯救你。
【解决方案5】:

你有以下:

char charpart1[3] = "";
randomStore = rand() % 255;
sprintf(charpart1, "%.2x", randomStore);

您的意思是使用“%.2f”格式而不是 x 吗? %.2x 仍然打印溢出缓冲区的“3ff3c083”。此外,如果您切换到 %0.2f,您可能希望 charpart1 的大小为 5,而不是 3,因为它会写入 [0][.][2][3][\0](例如)。

【讨论】:

    猜你喜欢
    • 2013-12-09
    • 1970-01-01
    • 2011-02-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-29
    • 1970-01-01
    相关资源
    最近更新 更多