Ir ao conteúdo
  • Cadastre-se
Cortella

C++ Lendo Arquivos em diversas pastas

Posts recomendados

Boa noite a todos,

 

Estou com um trabalho de faculdade para fazer e preciso ler arquivos em diferentes pastas, porém nunca fiz algo assim e estou enfrentando dificuldades, me sugeriram a biblioteca dirent.h , porém estou preso no seguinte bug:

 

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 do que se trata e como corrigir.

 

Meu codigo:

#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;
}

Ainda nao fiz a parte de leitura de arquivos porquê nao consigo prosseguir,

 

desde já agradeço a atencao.

  • Curtir 1

Compartilhar este post


Link para o post
Compartilhar em outros sites

@Cortella Você baixou o dirent ou está usando a que vem no mingw?

a do mingw aqui tá funcionando de boa aqui, mais a do projeto do tronkko não funcionou direito.

  • Curtir 1

Compartilhar este post


Link para o post
Compartilhar em outros sites

Olá!

 

Acho que as pessoas que acompanham esse forum vão acabar vendo as mesmas questões, então talvez abrir um novo tópico com o mesmo problema pode não ser assim efetivo...

 

Como te disse antes, talvez ajudasse você explicar qual seu ambiente de desenvolvimento... O código que postei funciona perfeitamente, bastaria criar uma nova rotina e passar o nome dela pra a função executa_na_pasta()

 


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()

se a sua função for teste() bastaria chamar com executa_na_pasta("nome da pasta",  teste) 

 

Acho que tem algo errado na configuração de seu ambiente.

 

4 horas atrás, KXSY disse:

dirent ou está usando a que vem no mingw?

a do mingw aqui tá funcionando de boa aqui, mais a do projeto do tronkko não funcionou direito

 

Não é pra ter diferença a versão de mingw e o código original. Não faria sentido, porque iria contra a própria razão de sucesso dessa biblioteca, que tem mais de vinte anos e roda até no videogame. De qualquer forma, a versão de Toni Ronkko vem sendo mantida há mais de vinte anos e é, claro, definitiva. Foi essa que usei para testar a rotina acima, essa

long executa_na_pasta(const char * pasta, long(*a_funcao)(const char *))

 

apenas escrevi duas rotinas de teste. Postei até a saída da execução em 

 

e compila sem problemas em Windows 10 e Visual Studio 2017.

 

Seu problema não é este.

 

Compartilhar este post


Link para o post
Compartilhar em outros sites
19 horas atrás, arfneto disse:

Não é pra ter diferença a versão de mingw e o código original.

É sim, há realmente uma diferença entre a versão do tronkko e a versão do mingw, a do tronkko foi feita baseada no windows.h e tinha um conflito com a biblioteca sockets, já a do mingw e baseada na biblioteca io.h (essa ultima e basicamente uma gambiarra da biblioteca io que faz a mesma coisa que o dirent).

Compartilhar este post


Link para o post
Compartilhar em outros sites
1 hora atrás, KXSY disse:

É sim, há realmente uma diferença entre a versão do tronkko e a versão do mingw, a do tronkko foi feita baseada no windows.h e tinha um conflito com a biblioteca sockets, já a do mingw e baseada na biblioteca io.h (essa ultima e basicamente uma gambiarra da biblioteca io que faz a mesma coisa que o dirent).

 

Não tenho tanto tempo e nem tanto interesse para comparar essas hipotéticas "duas versões"... Mas eventualmente vou fazer isso porque sou curioso :) O próprio autor, T. Ronkko diz na página de download que Mingw e Cygwin disponibilizam a API dirent completa. Mas nada diz sobre uma possível diferença.

Mas não faz sentido ter duas versões de uma biblioteca tão simples e estabelecida, e o autor afinal é o próprio T. Ronkko. Um eventual conflito com sockets.h parece um pouco distante do nível de acesso de dirent. Usar uma dessas opções incluída no compilador economizaria um download :) mas não tenho acesso fácil a esses compiladores.

 

Por outro lado, alguém podem se sentir inseguro ao usar uma biblioteca de mesmo nome que não é, digamos, a original. Ainda mais sabendo que o autor continua atualizando a API na página no github ainda hoje. A última atualização foi há 3 meses. Para uma API de 27 anos... O raciocínio é simples: seja qual for o seu ambiente, se todos usarem a mesma API --- de 23k --- não tem como dar errado a menos que tenha um erro na API, certo? E ela vem sendo mantida regularmente. Agora se eu usar a de um compilador e tiver algo lá diferente, que eu não sei o que é...

 

Posso dizer apenas do ambiente com Visual Studio 15.9.12 e sob Windows 10. Que usei para testar o programa que postei. E funciona sem problemas. Nem sei quais versões de sistema usei no passado, mas nunca me ocorreu usar uma API que não a do autor, porque aí eu teria que me preocupar com o que aconteceria se eu passasse a usar um outro ambiente de desenvolvimento que usasse outra "versão". E sempre funcionou...

 

 

 

 

 

 

Compartilhar este post


Link para o post
Compartilhar em outros sites

@arfneto  Segundo a própria página do github do T. Ronkko a versão dele foi uma "versão portada para Windows" que ele fez da dirent.h original feita para Linux/UNIX.

 

Ele também diz que fez isso pois na época não haviam muitas alternativas, mas menciona que hoje em dia existem boas alternativas, e aponta o MinGW e o Cygwin como alternativas pois permitem compilar programas UNIX no Windows (ou seja, ele sugere que poderia compilar a dirent.h original do Linux/UNIX diretamente, ao invés de uma a versão portada para Windows), e ele também aponta que ambos já fornecem a API dirent completa como parte do pacote, além de várias outras APIs do Linux/UNIX.

 

Citação

Alternatives to Dirent

I ported Dirent to Microsoft Windows in 1998 when only a few alternatives were available. However, the situation has changed since then and nowadays both Cygwin and MingW allow you to compile a great number of UNIX programs in Microsoft Windows. They both provide a full dirent API as well as many other UNIX APIs. MingW can even be used for commercial applications!

 

Compartilhar este post


Link para o post
Compartilhar em outros sites
44 minutos atrás, arfneto disse:

Não tenho tanto tempo e nem tanto interesse para comparar essas hipotéticas "duas versões"... Mas eventualmente vou fazer isso porque sou curioso :) O próprio autor, T. Ronkko diz na página de download que Mingw e Cygwin disponibilizam a API dirent completa. Mas nada diz sobre uma possível diferença.

Não são hipotéticas, são bem reais. dirent.thumb.png.d7e5b490b4332842e0f47472336582a5.png

a esquerda apresento dirent by tronkko (ela falha se você linkar com SDL 1.2), e a direita temos dirent (de novo) do mingw (e ainda temos uma hipótese de uma terceira versão no mingw-w64).

54 minutos atrás, arfneto disse:

Um eventual conflito com sockets.h parece um pouco distante do nível de acesso de dirent.

Sim, também não entendi o porquê mas parece ser alguma coisa relacionada ao windows.h, no print que eu mandei tem falando sobre isso na linha 22.

Compartilhar este post


Link para o post
Compartilhar em outros sites
1 hora atrás, KXSY disse:

a esquerda apresento dirent by tronkko (ela falha se você linkar com SDL 1.2), e a direita temos dirent (de novo) do mingw (e ainda temos uma hipótese de uma terceira versão no mingw-w64)

 

Passei perto de ter um problema desses então :) . Usei SDL mas os arquivos vinham como parâmetro então não tinha razão para usar dirent. Mas acho que era SDL 2.0.9 porque é a única que vejo nos backups. SDL 1.2 parou em 2012 acho. E foi bem depois que eu usei.

 

:) Obrigado por mostrar ao menos duas. Faltou um diff :D :D 

 

Saudações!

 

Compartilhar este post


Link para o post
Compartilhar em outros sites
2 horas atrás, isrnick disse:

Segundo a própria página do github do T. Ronkko a versão dele foi uma "versão portada para Windows" que ele fez da dirent.h original feita para Linux/UNIX.

 

Ele também diz que fez isso pois na época não haviam muitas alternativas, mas menciona que hoje em dia existem boas alternativas, e aponta o MinGW e o Cygwin como alternativas pois permitem compilar programas UNIX no Windows (ou seja, ele sugere que poderia compilar a dirent.h original do Linux/UNIX diretamente, ao invés de uma a versão portada para Windows), e ele também aponta que ambos já fornecem a API dirent completa como parte do pacote, além de várias outras APIs do Linux/UNIX

 

@isrnick Não entendi o que você está tentando dizer. Isso que o autor escreveu é uma referência histórica, apenas a razão do autor ter portado a API para Windows ainda em '98. E ele acrescentou que existem hoje boas alternativas para compilar programas UNIX no windows. E citou esses compiladores. E acrescentou que ambos esses oferecem a API dirent. Só isso.

 

Isso não muda em nada a realidade de quem quer, como o autor do tópico aqui no forum, criar uma função que envolve varrer diretórios e executar procedimentos. Não é o caso de recompilar no Windows programas do UNIX. E usar as API do Cygwin ou MinGW não faz sentido se você não usa já esses compiladores.

 

Outro caso é precisamente o que temos aqui: se você vai postar esse código  aqui, onde você não sabe que compilador o leitor vai estar usando, deve concordar que é mais seguro testar com a implementação original da dirent para Windows, ou não? E se o leitor usa Eclipse? Borland? Visual Studio? Por isso eu usei Visual Studio atualizado e testei numa máquina usando uma versão recente de Windows.

 

Essa implementação se tornou a recomendada pela Microsoft até outro dia. Mesmo em C++. Depois passou a se recomendar a <filesystem> ainda nos tempos da biblioteca boost. E agora a recomendação é iterar usando  FindFirstFile, FindNextFile e FindClose.

 

 

Compartilhar este post


Link para o post
Compartilhar em outros sites

@arfneto  Esta parte que quotei é a sessão do readme do github onde o autor mostra alternativas ao dirent, eu estava comentando que o próprio autor menciona que o MinGW e Cygwin usam outros API que não são o dirent programado por ele.

Compartilhar este post


Link para o post
Compartilhar em outros sites
12 horas atrás, isrnick disse:

@arfneto  Esta parte que quotei é a sessão do readme do github onde o autor mostra alternativas ao dirent, eu estava comentando que o próprio autor menciona que o MinGW e Cygwin usam outros API que não são o dirent programado por ele.

 

@isrnick  Só posso imaginar que não leu o que escrevi sobre isso ser uma referência histórica do porque T. Ronkko portou dirent para Windows em '98. E não leu o que escrevi sobre as razões pelas quais, a menos que você já use um desses compiladores citados, é melhor usar as soluções modernas:

 

13 horas atrás, arfneto disse:

iterar usando  FindFirstFile, FindNextFile e FindClose

 

Ou usar <filesystem> 

 

Ou usar dirent.h como provida no github pelas razões que expliquei acima...

 

De todo modo, o autor do tópico parece não estar se valendo dessa discussão... :D 

  • Haha 1

Compartilhar este post


Link para o post
Compartilhar em outros sites

FindFirstFile, FindNextFile e FindClose não são modernos, fazem parte da Win32 API que já está aí desde 1995.

 

 

Agora que <filesystem> faz parte da biblioteca padrão do C++, ela é a melhor opção disponível atualmente para funcionar em todas as situações e ser portável, pois não precisa lidar com versões corretas de bibliotecas para cada compilador, e não depende do sistema operacional utilizado.

  • Haha 1

Compartilhar este post


Link para o post
Compartilhar em outros sites
8 horas atrás, isrnick disse:

FindFirstFile, FindNextFile e FindClose não são modernos, fazem parte da Win32 API que já está aí desde 1995.

 

 

Agora que <filesystem> faz parte da biblioteca padrão do C++, ela é a melhor opção disponível atualmente para funcionar em todas as situações e ser portável, pois não precisa lidar com versões corretas de bibliotecas para cada compilador, e não depende do sistema operacional utilizado.

 

@isrnick Ainda não entendo onde quer chegar: Essa discussão começou como sabe em outro tópico, onde você também escreveu. De lá vem a consideração de "moderna" para essa opção, não porque ela tenha de fato pouca idade, mas por um detalhe bem óbvio e que foi listado lá:

 

Em https://docs.microsoft.com/pt-br/windows/desktop/FileIO/listing-the-files-in-a-directory na documentação oficial da empresa que escreveu o Windows e onde é colaborador o próprio criador da linguagem, Dr. Bjarne Stroustrup, está um tópico com esse título: Listando os arquivos em um Diretório e tem uma exemplo pronto de como fazer isso. Simples assim. Isso atenderia o que o autor do tópico precisa e vem de uma fonte, digamos, importante. E esse artigo é de maio de 2018, não de '95. Talvez entenda porque eu disse "moderna"

 

190611-listing-files.png.5be5b92ad4915970e3bdf53c315dc2e1.png

 

Resumindo o que já disse lá no outro tópico:  considerando que

  • aqui é um forum para discussão de C C# e C++ e frequentado por estudantes que podem estar usando qualquer versão de compilador e não necessariamente Cygwin ou MinGW
  • muitos usam Linux ou Mac
  • dirent roda igualzinho nos dois ambientes
  • E eu até postei até um código completo que automatiza a chamada de uma função para todos os arquivos comuns de uma pasta, e que rodaria apenas mudando o delimitador de / para \ em Linux. Faltaria só escrever a função que faz o trabalho que o autor do tópico precisa. Eu implementei 2 exemplos

Eu acho mais simples usar essa solução.

 

Talvez possa colaborar e acrescentar um trecho de código usando <filesystem> . A Microsoft já postou um usando os iteradores. Assim um eventual leitor do tópico poderia fazer as contas com 3 exemplos concretos. Não escrevi porque tenho pouco tempo e não me pareceu útil.

 

Abraço

Compartilhar este post


Link para o post
Compartilhar em outros sites

Crie uma conta ou entre para comentar

Você precisar ser um membro 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 publicações 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...

GRÁTIS: minicurso “Como ganhar dinheiro montando computadores”

Gabriel TorresGabriel Torres, fundador e editor executivo do Clube do Hardware, acaba de lançar um minicurso totalmente gratuito: "Como ganhar dinheiro montando computadores".

Você aprenderá sobre o quanto pode ganhar, como cobrar, como lidar com a concorrência, como se tornar um profissional altamente qualificado e muito mais!

Inscreva-se agora!