Ir ao conteúdo
  • Cadastre-se

C++ Ler varios arquivos Simultaneamente


Cortella

Posts recomendados

você pode usar a biblioteca <dirent.h> para obter todos os nomes de arquivos de um diretório:

#include <dirent.h>
#include <stdio.h>
 
int main()
{
    DIR *d;
    struct dirent *dir;
    d = opendir("."); //diretório atual;
    if (d != NULL)
    {
        while ((dir = readdir(d)) != NULL) //lsita todos os arquivos do diretorio
        {
            printf("%s\n", dir->d_name); 
            FILE * pFile;
            pFile = fopen (dir->d_name,"r"); //abre o arquivo
            if (pFile!=NULL)
            {
               // insira aqui o codigo que manipula o arquivo
                fclose (pFile);
            }
        }
          closedir(d);
    }
    return 0;
}

 

Link para o comentário
Compartilhar em outros sites

No C++ tem a biblioteca <filesystem> a partir da versão C++17 da linguagem:

https://en.cppreference.com/w/cpp/header/filesystem

 

Fiz um programa exemplo:

#include <iostream>
#include <string>
#include <fstream>
#include <filesystem>
namespace fs = std::filesystem;
 
int main()
{
    std::string data;
    fs::create_directories("sandbox/a/b"); //cria subdiretórios sandbox/a/b no diretório atual
    std::ofstream file1("sandbox/file1.txt"); //cria arquivo no diretório sandbox
    std::ofstream file2("sandbox/file2.txt"); //cria arquivo no diretório sandbox
    file1 << "123";
    file2 << "ABC";
    file1.close();
    file2.close();
    for(auto& p: fs::directory_iterator("sandbox")){ //itera nos arquivos e subdiretórios do sandbox
        std::cout << p << '\n';
        if(fs::is_regular_file(p)){ //Se for um arquivo
            std::ifstream(p.path()) >> data; //lê o conteúdo do arquivo
            std::cout << data << "\n"; //imprime o conteúdo
        }
        std::cout << std::endl;
    }
    fs::remove_all("sandbox"); //deleta todos o diretório sandbox e seus arquivos e subdiretórios
    return 0;
}

 

Mas precisa usar um compilador recente que disponibilize os recursos da versão C++17 ou mais recente da linguagem C++, e compilar usando a flag para essas versões (-std=c++17, -std=gnu++17, -std=c++2a ou -std=gnu++2a).

 

 

Na versão C++14 filesystem estava disponível como experimental (#include <experimental/filesystem>), e para versões antes disso seria necessário usar a biblioteca não padrão Boost.

Link para o comentário
Compartilhar em outros sites

Olá!

 

Não estou certo de que queira ler 12000 arquivos simultaneamente se eles estão na mesma pasta. Vou imaginar que queira ler sequencialmente, afinal estão todos no mesmo disco e na mesma pasta.

 

Como @Flávio Pedroza disse, dirent é uma opção. Tem mais de vinte anos, roda em várias plataformas e é código aberto. O arquivo único dirent.h tem 23K apenas e pode ser copiado de https://github.com/tronkko/dirent.

 

Usar a biblioteca boost ou sua versão com roupa nova <filesystem> é uma opção se estiver usando C++ em Windows, como sugeriu @isrnick 

 

Acredito o mais compatível com várias versões de windows e compiladores seria usar FindFirstFile, FindNextFile e FindClose, como descrito pelo dono do campo, da bola e das camisas em http://docs.microsoft.com. Pode ver aqui um exemplo da Microsoft de como listar os arquivos de um diretório, de maio de 2018... Serviria  para seu caso também

 

Eu ficaria com o mais portável e simples dirent...

Veja um exemplo usando dirent:

Supondo  que: 

você tem umas funções que fazem algo com um arquivo 'a', como ler ou imprimir informações sobre 'a', 
e quer chamar estas funções para todos os arquivos comuns na pasta 'p'.

E você gostaria de chamar uma mágica função assim:

executa_na_pasta(pasta, faz_o_servico_1)  ou
executa_na_pasta(pasta, faz_o_servico_2) 

para rodar 
    faz_o_servico_1(p) ou 
    faz_o_servico_2(p) 
na pasta 'p'

Vamos imaginar que a função 1 seja bem simples, apenas liste na tela o nome do arquivo, e a função 2 liste na tela o nome e o tamanho do arquivo em bytes, e as duas retornem um long, irrelevante no caso da primeira ou com o tamanho do arquivo no caso da segunda. Assim usando a segunda você pode ir somando o total de bytes ocupados pelos arquivos na pasta

 

Para uma pasta assim

 

190606-lista-pasta.png.0f34ee135df76fe8dad328a5a898ecee.png

 

A saída dese programa seria assim

 

190606-saida-programa.png.4cffcf20ba77068e977cf143ae44f61c.png

 

E isso serve de exemplo para o que você precisa fazer. Eis uma possível função 1, que só imprime o nome do arquivo, bem besta

long faz_o_servico_1(const char * arquivo)
{
    printf("%s\n", arquivo);
    return 0;
}

Eis uma possível função 2, que imprime também o tamanho, como suposto no exemplo

long faz_o_servico_2(const char * arquivo)
{
    struct stat fileInfo;
    int r = stat(arquivo, &fileInfo);
    printf(
        "%-40s\t%8d\n",
        arquivo, fileInfo.st_size
    );
    return fileInfo.st_size;
}

Você chamaria essa função de que precisa assim:

    printf("\n--------------------------------------------------\n");
    printf("\ntesta com a funcao 1\n");
    executa_na_pasta(pasta_local, faz_o_servico_1);
    printf("\n--------------------------------------------------\n");
    printf("\ntesta com a funcao 2\n");
    executa_na_pasta(pasta_local, faz_o_servico_2);

E ela rodaria a função indicada na sua pasta com 5 ou 12.000 arquivos. Para qualquer função que você escreva desde que retorne int ou long, certo? 

 

Eis uma possível implementação de executa_na_pasta(), que funciona em Windows. Para Linux ou MAC acho que precisa só mudar o separador de \ para / porque eu não me preocupei com portabilidade afinal, nada mais

long executa_na_pasta(const char * pasta, long(*a_funcao)(const char *))
{
	// roda a funcao a_funcao() para todos os arquivos na
	// pasta 'pasta' e retorna o total em bytes da soma do
	// tamanho dos arquivos
	struct dirent *diretorio;		// descreve o diretorio
	DIR *pDir = opendir(pasta);		// o ponteiro para o diretorio
	char * nome_completo;			// nome do arquivo na pasta
	long total = 0;					// para somar os tamanhos
	printf("\n[%s]\n\n", pasta);
	if (pDir == NULL)
	{
		printf("Erro ao abrir %s\n", pasta);
		return(-1);
	}	// end if
	while ((diretorio = readdir(pDir)) != NULL)
	{
		// em d->name esta o nome do arquivo
		// entao precisamos da string 'pasta\nome'
		// para ver se e um arquivo comum e listar afinal
		int n = 2 + strlen(pasta) + strlen(diretorio->d_name);
		nome_completo = (char *)malloc((size_t)n);
		// monta o nome do arquivo: pasta \ nome no windows
		sprintf_s(nome_completo, n, "%s\\%s", pasta, diretorio->d_name);
		// se for um arquivo comum, chama a funcao

		//   faz o servico para cada arquivo na pasta     ***********************
		if (eh_um_arquivo(nome_completo)) total = total + a_funcao(nome_completo);
		//                                                ***********************
		free(nome_completo);	// libera o nome
	}	// end while
	printf("\nTotal de %d bytes nos arquivos da pasta\n", total);
	closedir(pDir);	//	ao sair fecha a pasta
	return(0);
}	// end executa_na_pasta()

Só isso. O trabalho mesmo está em uma linha só, entre os comentários com ***************** onde chama 

        if (eh_um_arquivo(nome_completo)) total = total + a_funcao(nome_completo);

a função eh_um_arquivo() recebe o nome do arquivo, que é pasta\arquivo no Windows e retorna 1 se é um arquivo comum, só para ficar fácil de ler o programa. Pra não faltar nada:

int eh_um_arquivo(const char * nome)
{
    int r;
    struct stat fileInfo;
    r = stat(nome, &fileInfo);
    if ((r == 0) && (S_ISREG(fileInfo.st_mode))) return (1);
    return(0);
}    // end eh_um_arquivo()

É isso. Fim do exemplo. Pode escrever sua rotina de serviço e vai rodar de imediato com esse código. Veja de novo a saída do programa lá em cima e se não entendeu escreva de novo

 

 

Link para o comentário
Compartilhar em outros sites

Gostaria de agradecer de coracao a ajuda de todos em especial a de@arfneto ...

Tentei utilizar a biblioteca,porém me deparei com o seguinte erro:

 

C:\Cortella\Projetos\Trabalho_PDS\Buscador>g++ Buscador.cpp
In file included from Buscador.cpp:5:0:
dirent.h:383:28: error: missing binary operator before token "("
 #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
                            ^
dirent.h:405:28: error: missing binary operator before token "("
 #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
                            ^
dirent.h: In function '_WDIR* _wopendir(const wchar_t*)':
dirent.h:413:43: error: 'wcsncpy_s' was not declared in this scope
     wcsncpy_s (dirp->patt, n+1, dirname, n);
                                           ^

 

Gostaria de saber se o erro em questão se trata de uma incompatibilidade em meu sistema: segue meu codico em anexo ...

#include <iostream>
#include "dirent.h"

using namespace std;

int main(int argc, char* argv[]) {

	DIR* d;
	struct dirent* dir;
	d = opendir(".data"); //diretório atual;
	if (d != NULL) {
		//le todos os arquivos no diretorio especificado
		while ((dir = readdir(d)) != NULL) {
			//cout << "\n " << dir->d_name << endl;
			char namePaste[50] = "./data/";
			int aux;

			//Copia nome das pastas do diretorio
			for (int i = 0; i < dir->d_namlen; i++) {
				aux = (int)dir->d_name[i];
				//seleciona caracteres a partir de ASCII
				if ((aux >= 97 && aux <= 122) || (aux >= 48 && aux <= 57) || (aux == 45) || (aux == 46)) {
					namePaste[i+7] = dir->d_name[i];
					//Cria novo diretorio para entrar na pasta
					DIR* p;
					struct dirent* paste;
					//Abre Pasta
					p = opendir(namePaste);
					if (p != NULL) {
						while ((paste = readdir(p)) != NULL) {
							cout << "\n " << paste->d_name;
						}
					}
				}

			}

		}
	}
	return 0;
}

 

Link para o comentário
Compartilhar em outros sites

  • 11 meses depois...

@Flávio Pedroza Boa tarde.

eu preciso listar e ler arquivos de um diretorio e tentei usar o seu codigo. Ele listou mas nao consegui ler o conteudo. Vou te mandar o que eu escrevi:

#include <sys/stat.h>
#include <dirent.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main()
{
    DIR *d;
    struct dirent *dir;
    d = opendir("./teste1"); //diretório atual;
    if (d != NULL)
    {
        while ((dir = readdir(d)) != NULL) //lsita todos os arquivos do diretorio
        {
          if (strcmp(dir->d_name, "."))
          if (strcmp(dir->d_name, ".."))
            printf("%s\n", dir->d_name);
            FILE * pFile;
            pFile = fopen (dir->d_name,"r"); //abre o arquivo
            if (pFile!=NULL)
            {
              double x;
              fscanf(pFile,"%lg",&x);
              printf("%s %lg\n",dir->d_name, x);
               // insira aqui o codigo que manipula o arquivo
                fclose (pFile);
            }
        }
          closedir(d);
    }
    return 0;
}
 

Link para o comentário
Compartilhar em outros sites

1 hora atrás, Liner de Souza Santos disse:

eu preciso listar e ler arquivos de um diretorio e tentei usar o seu codigo. Ele listou mas nao consegui ler o conteudo

 

Leu o exemplo no tópico 4, que faz exatamente isso e ainda pode chamar uma função para fazer algo com os arquivos da pasta?

 

O que seria "ler o conteúdo?"

Link para o comentário
Compartilhar em outros sites

12 minutos atrás, arfneto disse:

Leu o exemplo no tópico 4, que faz exatamente isso e ainda pode chamar uma função para fazer algo com os arquivos da pasta?

 

Leu?

 

Se leu sabe que pode só escrever uma função para fazer o que quer no arquivo e colocar lá. Se bem me lembro era só isso o que o exemplo fazia: você passa um diretório e uma função e ele roda a função para cada arquivo na pasta.... Como o map() do javascript.

 

Se vai simplesmente copiar o arquivo todo use as funções do sistema, como CopyFile() ou CopyFileTransacted()

 

Pode usar também FindFirst/FindNext.

 

Cuidado se vai criar arquivos dentro da mesma pasta para não copiar as cópias ;) e as cópias das cópias...

 

Link para o comentário
Compartilhar em outros sites

29 minutos atrás, Liner de Souza Santos disse:

Só nao entendi como eu chamo essa função no main()

 

Agora eu não entendi. De que função está falando?

adicionado 2 minutos depois

Se é do que eu expliquei então...

image.png.2873eddf4d222da3525d5f31eda7586e.png

 

E se fala de FindFirst/FindNext acho que eu postei o link de um exemplo também. E se fala ade CopyFile() tem um exemplo lá também, apesar de ser bem trivial

Link para o comentário
Compartilhar em outros sites

Crie uma conta ou entre para comentar

Você precisa ser um usuário para fazer um comentário

Criar uma conta

Crie uma nova conta em nossa comunidade. É fácil!

Crie uma nova conta

Entrar

Já tem uma conta? Faça o login.

Entrar agora

Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas comunidades sobre tecnologia do Brasil. Leia mais

Direitos autorais

Não permitimos a cópia ou reprodução do conteúdo do nosso site, fórum, newsletters e redes sociais, mesmo citando-se a fonte. Leia mais

×
×
  • Criar novo...

Ebook grátis: Aprenda a ler resistores e capacitores!

EBOOK GRÁTIS!

CLIQUE AQUI E BAIXE AGORA MESMO!