【问题标题】:C++ Looping Through Files In Directory and Writing to a Different DirectoryC++ 循环遍历目录中的文件并写入不同的目录
【发布时间】:2012-07-02 19:05:56
【问题描述】:

我正在尝试修改一些现有的 C++ 代码以满足我的需要,但我以前从未使用过 C++,因此遇到了一些困难。

我的目标是:

--> time and memory-intensive processes for preparation

for each file in directory:
    open file;
    generate a tagged representation; //the current code just does this
    write file; //different directory but same filename

我不想只为每个文件(例如,使用 shell 脚本)调用 C++ 程序的原因是,在运行以下代码之前,会执行时间和内存密集型的预处理步骤。 (这些大约需要 45-60 秒。而代码只需要大约 2-5 秒即可运行。)

我已经粘贴了下面的代码部分。我想从命令行读取参数。

int main(int argc, char** argv) {
  /*
  pre-processing stuff
  */

  /* for each file */
  HANDLE hFind = INVALID_HANDLE_VALUE;
  string path = argv[1];
  string outpath = argv[2];
  WIN32_FIND_DATA ffd;

  //EDIT 2:
  cout << "Path: " << path << '\n'; 
  cout << "Outpath: " << outpath << '\n';

  hFind = FindFirstFile(path.c_str(), &ffd);
  if (hFind == INVALID_HANDLE_VALUE) {
    cout << "error searching directory\n";
    return false;
  }

  do {
    //istream *is(&std::cin);
    string filePath = path + ffd.cFileName;
    ifstream in( filePath.c_str() );
    if (in) {
      /* for each line */
      string line;
      int n = 1;
      string str;
      string fullOutpath = outpath + ffd.cFileName;
      ofstream File;
      File.open(fullOutpath);
      while (getline(in, line)) {
        if (line.size() > 1024) {
          cerr << "warning: the sentence seems to be too long at line " << n;
          cerr << " (please note that the input should be one-sentence-per-line)." << endl;
        }

        string postagged = bidir_postag(line, vme, vme_chunking, dont_tokenize);

        /* output to file */
        File << postagged << endl;
        //cout << postagged << endl;

        /* increment counter */
        n++;
      }
      File.close();
    } else {
      cout << "Problem opening file " << ffd.cFileName << "\n";
    }
  } while (FindNextFile(hFind, &ffd) != 0);

  if (GetLastError() != ERROR_NO_MORE_FILES) {
    cout << "Something went wrong during searching\n"; 
  }
  return true;
}

目前,我收到编译器错误:EDIT:编译器错误已修复,感谢 Blood!,但请参见下文...

error: no matching function for call to 'std::basic_ofstream<char>::open<std::string&>

有什么想法吗?如果您需要更多代码/信息,请告诉我。另外,我应该补充一点,我正在使用命令提示符在 Windows XP 上运行这些。

谢谢。

编辑:

它现在可以编译(感谢 Blood),虽然它在运行时只是尝试打开目录,而不是目录中的文件。

Problem opening file directory_name.

ifstream 应该打开目录中的文件,而不是目录本身。

编辑 2:

我正在使用以下提示从命令行运行可执行文件:

.\tag.exe C:\indir C:\outdir

我也试过了:

.\tag.exe C:\indir\* C:\outdir\

这会枚举所有文件,但我如何捕获它们?另外,有没有更简单的方法来修改我的代码/输入?

我也试过了:

.\tag.exe C:\indir\ C:\outdir\

这给出:错误搜索目录。

编辑 3:

使用:

.\tag.exe "C:\indir\*" C:\outdir\

我得到了输出:

Problem opening file .

Problem opening file ..

Problem opening file 2967

Problem opening file 2966

Problem opening file 4707

etc. (100s)

解决方案:

以下是代码的主要更改(感谢 Nate Kohl!):

string path = argv[1];
path += "\\*";

hFind = FindFirstFile(path.c_str(),&ffd);

    // in the 'do-while' loop
    string filePath = argv[1];
    filePath += "\\";
    filePath += ffd.cFileName;

    ifstream in(filePath.c_str());

    //regarding the outpath
    fullOutpath = outpath + "\\";
    fullOutpath += ffd.cFileName;
    File.open(fullOutpath.c_str());

从命令行:

.\tag.exe C:\indir C:\outdir

非常感谢您的帮助。

【问题讨论】:

    标签: c++ io


    【解决方案1】:

    确保您将正确的path 格式传递给FindFirstFile

    来自the documentation

    要检查不是根目录的目录,请使用以下路径 该目录,没有尾随反斜杠。例如,一个参数 "C:\Windows" 返回有关目录 "C:\Windows" 的信息, 与“C:\Windows”中的目录或文件无关。 检查文件 和“C:\Windows”中的目录,使用“C:\Windows\*”的 lpFileName。


    编辑:

    我现在不在 windows 框附近(所以这可能无法编译!)但我想“循环遍历目录中的每个文件”看起来像这样:

    // argv[1] is the input path with no trailing characters, e.g. "c:\indir"
    
    // add a wildcard because FindFirstFile expects e.g. "c:\indir\*"
    TCHAR wildcard_path[MAX_PATH];
    PathCombine(wildcard_path, argv[1], "*"); 
    
    // iterate over each file
    WIN32_FIND_DATA ffd;
    HANDLE hFind = FindFirstFile(wildcard_path, &ffd);
    if (hFind == INVALID_HANDLE_VALUE) { } // error
    
    do {
       // ignore directories
       if (!(ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
    
          // create a full path for each file we find, e.g. "c:\indir\foo.txt"
          TCHAR file_path[MAX_PATH];
          PathCombine(file_path, argv[1], ffd.cFileName);
    
          // ...and do something with file_path.
       }
    } while (FindNextFile(hFind, &ffd) != 0);
    
    FindClose(hFind);
    

    【讨论】:

    • 我正在从命令行运行编译后的可执行文件,并将文件指定为 C:\indir* C:\outdir\ (我认为这是您的建议?)。在这种情况下,'path' 成为目录中的第一个文件,而 outpath 成为目录中的第二个文件。另外,我收到上面的错误“打开文件 0064 问题”(注意:0064 是正确的文件名之一。
    • @DavidC:应该是C:\indir\*(注意尾随\*)。
    • @DavidC:哦,你的 shell 在你的应用程序之前执行通配符扩展!在这种情况下,您应该只从命令行传递 C:\indir 并在您的应用程序中附加 \*
    • @DavidC:尝试在它周围加上引号,例如foo.exe "C:\indir\*"
    • 尝试让您的错误消息显示filePath,这是无法打开的实际路径。我怀疑连接路径和文件名不正确,尤其是现在路径包含* 字符。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-03
    • 2020-11-05
    • 1970-01-01
    • 1970-01-01
    • 2012-07-25
    • 1970-01-01
    相关资源
    最近更新 更多