Получение файлов из подкаталога с использованием строковой переменной в качестве пути к файлу - С++

У меня есть подкаталог в главном каталоге моих проектов под названием «данные». В этом каталоге есть несколько CSV-файлов, а также текстовый файл, а текстовый файл содержит имена некоторых CSV-файлов, из которых я хочу прочитать данные. Используя цикл while, я хочу получить имя каждого файла из текстового файла «infile», сохранить его в строке «files» и использовать эту строковую переменную для открытия каждого файла в подкаталоге. Я просто не знаю, как я могу получить доступ к подкаталогу, используя эту строковую переменную. Что я сделал в приведенном ниже коде, так это переместил файлы, которые я хочу использовать, в мой основной каталог, и он работает так, как предполагалось, но я хочу добиться того же, просто получив доступ к подкаталогу. Какие-либо предложения?

    string files;

    ifstream infile("data\\met_index.txt"); //Open the text file that shows the csv files needed

    if(!infile) //Exits the program and outputs this message if the file is not found
    {

        cout << "File not found.";

        return -1;

    }

    Vector<string> headers; //A vector of type String to hold the headers for each column

    while(getline(infile, files))
    {

        ifstream datafile(files.c_str()); // How do I access sub directory here?
        if(!datafile) //Exits the program and outputs this message if the file is not found
        {

            cout << "File not found.";

            return -1;

        }
        cout << "File: " << files << endl;

}

person thedafferg    schedule 18.05.2020    source источник
comment
Вы указываете относительный путь для ifstream, например. имя файла в том же каталоге. Следуя этой логике, вы также можете указать subdir/filename, но вы должны использовать косую черту в качестве разделителя. std::string путь к файлу = данные/; путь к файлу += файлы; std::ifstream файл данных (fiepath.c_str()); Это был вопрос? Кстати. вы не должны использовать использование пространства имен std, это считается плохой практикой!   -  person Wolfgang    schedule 18.05.2020
comment
("data\\" + files).c_str() ? Также вы можете изучить en.cppreference.com/w/cpp/filesystem/path для лучшей совместимости, что позволяет правильно объединять пути.   -  person Askold Ilvento    schedule 18.05.2020
comment
Да, именно так я получаю текстовый файл в подкаталоге, а затем сохраняю их в строке «файлы». Но как бы я использовал строку, чтобы сделать то же самое? Например, ifstream(data/+files variable), какой правильный синтаксис? И да, мне действительно нужно привыкнуть не использовать пространство имен std @Wolfgang   -  person thedafferg    schedule 18.05.2020
comment
@AskoldIlvento Когда я пробую это утверждение, я получаю ожидаемую ошибку ',' или ';' до '.' жетон   -  person thedafferg    schedule 18.05.2020


Ответы (3)


Если вы можете использовать C++17 и ваш компилятор поддерживает библиотеку filesystem, вы должны использовать ее для лучшей переносимости.

#include <iostream>
#include <string>
#include <vector>
#include <filesystem>
#include <fstream>

namespace fs = std::filesystem;

int main() {
    const fs::path directory_path = "data";

    std::ifstream infile{directory_path / "met_index.txt"};
    if (!infile){
        std::cerr << "met_index.txt not found!\n";
        return -1;
    }

    std::vector<fs::path> file_paths{};

    std::string file_input;
    while(std::getline(infile, file_input)) {
        const fs::path file_path = directory_path / file_input;
        if(fs::exists(file_path)) {
            file_paths.push_back(file_path);
        }
    }

    for(const fs::path& file_path : file_paths) {
        std::cout << file_path << '\n';
    }
}

Помните, что вам нужно указать флаги вашего компилятора для компиляции с C++ 17, и если вы используете g++ или clang++, вам может потребоваться связать файловую систему с -lstdc++fs.

Кроме того, если вы используете свой файл met_index.txt только для хранения и чтения файлов, находящихся в вашем каталоге data, чтобы вы могли легко получить к ним доступ, вам следует посмотреть directory_iterator для получения файлов внутри каталога.

person Kaldrr    schedule 18.05.2020

Насколько я понимаю, вы просто хотите построить путь к файлу соответствующим образом. Например, это может выглядеть так:

std::string line;
while(std::getline(infile, line))
{
    std::string filepath("data/");
    std::ifstream datafile(filepath.append(line).c_str());

Как уже предлагал AskoldIlvento, вы должны (если возможно) использовать std::filesystem и т. д. для лучшей совместимости. Или с помощью библиотеки типа boost (boost::fileystem).

person Wolfgang    schedule 18.05.2020
comment
Когда я пробую это, а также приведенное выше решение, я получаю ту же ошибку, что и описанная в комментарии выше. Не думайте, что это что-то с моими файлами, потому что до этого мне удавалось заставить все работать успешно, когда все было в основном каталоге. - person thedafferg; 18.05.2020
comment
Пожалуйста, не обращайте внимания на вышесказанное, у меня все работает. Спасибо за совет и помощь - person thedafferg; 18.05.2020

Конструктор ifstream принимает аргумент char * или const std::string &, поэтому у вас нет причин использовать ._str(). Вы можете просто изменить свою строку с помощью:

ifstream datafile(std::string("data\\") + files);
    if(!datafile) //Exits the program and outputs this message if the file is not found
    {
person Serge Ballesta    schedule 18.05.2020
comment
Когда я пытаюсь это сделать, он выводит имя первого файла, а затем я получаю сообщение об ошибке «завершить вызов после создания экземпляра» std::invalid_argument, what (): stof ' - person thedafferg; 18.05.2020