C ++ Циклический просмотр файлов в каталоге и запись в другой каталог

Я пытаюсь модифицировать некоторый существующий код 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

Причина, по которой я не хочу просто вызывать программу 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;
}

В настоящее время я получаю ошибку компилятора: РЕДАКТИРОВАТЬ : ошибка компилятора исправлена, спасибо Blood !, но см. ниже ...

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

Есть мысли? Пожалуйста, дайте мне знать, если вам нужно больше кода /информации. Кроме того, я должен добавить, что я запускаю их в Windows XP, используя командную строку.

Спасибо.

EDIT:

Теперь он компилируется (спасибо 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)

Решение:

Вот ключевые изменения в коде (спасибо Нейту Колю!):

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

Помощь очень ценилась.

4 голоса | спросил David C 2 J000000Monday12 2012, 23:05:56

1 ответ


0

Убедитесь, что вы передаете правильный path в FindFirstFile.

Из документации :

  

Чтобы проверить каталог, который не является корневым каталогом, используйте путь к   этот каталог, без обратной косой черты. Например, аргумент   «C: \ Windows» возвращает информацию о каталоге «C: \ Windows»,   не о каталоге или файле в "C: \ Windows". Чтобы просмотреть файлы   и каталоги в «C: \ Windows», используйте lpFileName «C: \ Windows \ * ».


Edit:

В данный момент я не нахожусь возле окна 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);
ответил Nate Kohl 3 J000000Tuesday12 2012, 00:10:03

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132