Mehrere Dateien einlesen



  • beginner88888 schrieb:
    Ok, da ist evtl. was dabei. Naja, mal sehen, das "riecht" nach einigem zum einlesen.

    Wo ist dein Problem?

    Habe nichts von Problem geschrieben. Habe noch nie mit Win Api gearbeitet, darum einlesen. Sonst sind die nächsten 25 Beiträge à la "Jetzt geht aber das nicht"... vorprogrammiert.

    beginner88888 schrieb:
    [...] ich müsste irgendwie eine Liste mit allen Dateinamen im aktuellen Ordner ins Programm bekommen.....

    Oh. Ups. Sorry. 🙂

    => Kein Problem. Hmm... Wer spricht aus Erfahrung, wie lange ungefähr bis man mit C# sowas auf die Reihe bekommt? Anm: Habe gehört in C# gibt es unsicheren Code, der dann auch Pointer zulässt. .... Könnte ich da evtl. "komplett" meinen bisherigen Code reinballern?



  • beginner88888 schrieb:

    beginner88888 schrieb:
    Ok, da ist evtl. was dabei. Naja, mal sehen, das "riecht" nach einigem zum einlesen.

    Wo ist dein Problem?

    Habe nichts von Problem geschrieben. Habe noch nie mit Win Api gearbeitet, darum einlesen. Sonst sind die nächsten 25 Beiträge à la "Jetzt geht aber das nicht"... vorprogrammiert.

    Swordfish hat dir schon alles gegeben, was du brauchst.
    Du musst lediglich puts( w32_find_data.cFileName ) durch my_decode(w32_find_data.cFileName) ersetzen.

    beginner88888 schrieb:
    [...] ich müsste irgendwie eine Liste mit allen Dateinamen im aktuellen Ordner ins Programm bekommen.....

    Oh. Ups. Sorry. 🙂

    => Kein Problem. Hmm... Wer spricht aus Erfahrung, wie lange ungefähr bis man mit C# sowas auf die Reihe bekommt? Anm: Habe gehört in C# gibt es unsicheren Code, der dann auch Pointer zulässt. .... Könnte ich da evtl. "komplett" meinen bisherigen Code reinballern?

    Nein, C# ist nicht abwärtskompatibel mit C. C++ ist größtenteils, aber nicht C#.
    Ich kenn mich jetzt selber nciht mit C# aus, aber du kannst wie Th69 schon schrieb, dein existierendes C Programm als ausführbare Datei von einem C# Programm aus aufrufen.
    Aber wenn du C# noch nicht kennst musst du dich da erst einmal komplett reinarbeiten, inklusive OO-Denken und allem.



  • Swordfish hat dir schon alles gegeben, was du brauchst.
    Du musst lediglich puts( w32_find_data.cFileName ) durch my_decode(w32_find_data.cFileName) ersetzen.

    Danke derweilen, ich versuche das mal so hinzubekommen. C# stell ich erst mal hinten an 🙂



  • Alter, die MSDN ist jetzt nicht wirklich mein Fall...

    Kann ich das besser spezifizieren :

    HANDLE find_handle = FindFirstFileA( "*", &w32_find_data );
    

    Ich bräuchte alle Dateien ausser *.exe . ...



  • und Unterordner sollten auch nicht durchsucht werden....



  • Nimm doch einfach strcmp und vergleich den Dateinamen.
    Oder such manuell mit strrchr (mit zwei r) nach '.' und check ob das danach gleich "exe" ist um alle exe Dateien auszuschließen.
    Alternativ kannste auch einfach das Wildcard-Pattern "" durch ".txt" ersetzten um bspw. alle txt zu bekommen.

    Edit: Und was Unterordner angeht:
    Check ob w32_find_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY true ist, wenn ja, skip die Datei.



  • Oder such manuell mit strrchr (mit zwei r) nach '.' und check ob das danach gleich "exe" ist um alle exe Dateien auszuschließen.

    Ich wollte das auf die "Faule" Art von find_handle erledigen lassen.

    Das mit dem Wildcard Pattern funzt auch nicht so ganz. "*.txt" bezieht sich wohl nicht auf das aktuelle Verzeichnis? Und bei %CD% klappts auch nicht.



  • Nachtrag ".txt " funktioniert natürlich schon, war mein Fehler.
    Es wäre hald etwas wie "
    .alles ausser txt" nett 🙂



  • beginner_offl schrieb:

    Nachtrag ".txt " funktioniert natürlich schon, war mein Fehler.
    Es wäre hald etwas wie "
    .alles ausser txt" nett 🙂

    Ja, FindFirstFile unterstützt leider kein Regex.
    FindFirstFileEx eventuell, werd allerdings aus der Doku auch nicht schlau.



  • Nathan schrieb:

    FindFirstFileEx eventuell, werd allerdings aus der Doku auch nicht schlau.

    Bei FindFirstFileEx() kann man sich aussuchen, ob einen 8.3 Namen interessieren ( FINDEX_INFO_LEVELS Enumeration), ob sich das Ding benehmen soll wie FindFirstFile() oder nur Verzeichnisse berücksichtigen soll ( FINDEX_SEARCH_OPS Enumeration), ob es case-sensitive ( FIND_FIRST_EX_CASE_SENSITIVE ) sein soll und/oder einen größeren Puffer für bessere Performance verwenden soll ( FIND_FIRST_EX_LARGE_FETCH ). Hilft also alles nix.

    Für die Faulen:

    #define _CRT_SECURE_NO_WARNINGS
    #include <stdbool.h>
    #include <stddef.h>
    #include <memory.h>
    #include <string.h>
    #include <stdlib.h>
    #include <stdio.h>
    
    #include <windows.h>
    
    typedef char ** file_list_t;
    
    /*
     *	false && !file_list -> error
     *	true  && !file_list -> no files found
     */ 
    bool create_file_list_ex( file_list_t * file_list, char const ** exclude_list )
    {
    	char * extension;
    	HANDLE find_handle;
    	WIN32_FIND_DATAA find_data;
    	size_t i;
    	size_t file_list_size = 0;
    	file_list_t temp_file_list;
    	*file_list = NULL;
    
    	if( ( find_handle = FindFirstFileA( "*", &find_data ) ) == INVALID_HANDLE_VALUE )
    		return GetLastError() == ERROR_FILE_NOT_FOUND;
    
    	do {
    		if( GetFileAttributesA( find_data.cFileName ) & FILE_ATTRIBUTE_DIRECTORY  )
    			continue;
    
    		if( exclude_list && ( extension = strrchr( find_data.cFileName, '.' ) ) ) {	
    			for( i = 0; exclude_list[ i ]; ++i ) 
    				if( stricmp( extension, exclude_list[ i ] ) == 0 )
    					break;
    			if( exclude_list[ i ] )
    				continue;
    		}
    
    		temp_file_list = realloc( *file_list, ++file_list_size * sizeof *file_list );
    
    		if( !temp_file_list ) {
    			while( file_list_size-- )
    				free( (*file_list)[ file_list_size ] );
    			free( *file_list );
    			*file_list = NULL;
    			FindClose( find_handle );
    			return false;
    		}
    
    		*file_list = temp_file_list;
    		(*file_list)[ file_list_size - 1 ] = malloc( strlen( find_data.cFileName ) + 1 ); // TODO: Error handling ...
    		strcpy( (*file_list)[ file_list_size - 1 ], find_data.cFileName );
    
    	} while( FindNextFileA( find_handle, &find_data ) );
    
    	if( GetLastError() == ERROR_NO_MORE_FILES )
    		temp_file_list = realloc( *file_list, ++file_list_size * sizeof *file_list );
    	else
    		temp_file_list = NULL;
    
    	if( !temp_file_list ) {
    		while( file_list_size-- )
    			free( (*file_list)[ file_list_size ] );
    		free( *file_list );
    		*file_list = NULL;
    		FindClose( find_handle );
    		return false;
    	}
    
    	*file_list = temp_file_list;
    	(*file_list)[ file_list_size - 1 ] = NULL;
    
    	FindClose( find_handle );
    	return true;
    }
    
    bool create_file_list( file_list_t * file_list )
    {
    	return create_file_list_ex( file_list, NULL );
    }
    
    void print_file_list( file_list_t file_list )
    {
    	size_t i;
    
    	if( !file_list )
    		return;
    
    	for( i = 0; file_list[ i ]; ++i )
    		puts( file_list[ i ] );
    }
    
    void free_file_list( file_list_t file_list )
    {
    	size_t i;
    
    	if( !file_list )
    		return;
    
    	for( i = 0; file_list[ i ]; ++i )
    		free( file_list[ i ] );
    	free( file_list );
    }
    
    int main( void )
    {
    	file_list_t file_list;
    	char const * exclude_list[] = { ".c", ".h", NULL };
    	create_file_list_ex( &file_list, exclude_list );
    	print_file_list( file_list );
    	free_file_list( file_list );
    }
    


  • Danke für das Beispiel, aber das ist mir zu "Umfangreich", und ich mag nichts hernehmen ,das ich nicht entweder selbst gemacht habe, oder wovon ich nicht alles 100% verstehe.

    Habe mittlerweile , im Vergleich zu Deiner Lösung wohl "recht billige" Variante erstellt, die für meine Zwecke ausreicht.

    Wer Lust hat kann ja mal drüber sehen, Code folgt



  • void fhandler(F_HANDLE *ptr){
    
    int run=0;
    
    WIN32_FIND_DATAA find_data; 
    HANDLE find_handle = FindFirstFileA( "*", &find_data );
    ptr->count=0;    
    
        while( FindNextFileA( find_handle, &find_data ) ) {
    
    	   if( strcmp(find_data.cFileName, "..") != 0){
    		   if (strstr (find_data.cFileName,".exe") == NULL){
    		   	//puts( find_data.cFileName ); 
    		   	strcpy(&ptr->data[run++][_STR], find_data.cFileName);
    		    ptr->count++;		   	 
    		   }
    	   } 	 	
        }
    
     }//END
    

    fhandler.h

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <windows.h>  
    #define _FH_LENGTH  125
    #define _FH_FILES    20
    #define _STR 0
    
    typedef struct{
    	 char data[_FH_FILES][_FH_LENGTH];
    	 int count;
    	}F_HANDLE;
    
    void fhandler(F_HANDLE *ptr);
    


  • Jetzt mal auf die Schnelle:
    -Alle Namen, die mit einem Unterstricht beginnen und wo danach ein Großbuchstabe folgt sind für die Implementierung reserviert, deine Markos haben also falsche Namen.
    -die erste Datei wird nicht gefunden (das ist afaik zwar eh immer '.', also das aktuelle Verzeichnis, aber trotzdem)
    -das Pattern ".exe" als Ausschluss hardzucoden ist nicht sonderlich schön, dann musst du später den Code anpassen, wenn du den ggf. wieder verwenden willst und das verletzt das Open-Closed-Principle
    -Welche genaue Bedeutung hat _STR? Ein Offset im zweiten Array?
    -_FH_LENGTH solltest du umbenennen (s.o) und als MAX_PATH definieren, das ist die maximale Länge eines Files unter Windows
    -Alle includes in fhandler.h sind aktuell überflüssig (bzw. bis auf windows.h wenn du MAX_PATH nutzt), du solltest sie entfernen;
    in der .c dann nur die includieren, die du brauchst (windows.h, wenn nicht schon im Header, und string.h)



    • Wofür _STR ?
    • Wofür die ganzen includes im Header?
    • _FH_LENGTH sollte MAX_PATH sein.
    • Der Datentyp für Speichergrößen ist size_t aus <stddef.h> , nicht int .
    • Wenn eine Anzahl von Dateien größer _FH_FILES gefunden werden kackt dein Code ohne Fehlerbehandlung ab.
    • Wofür run in fhandler() ? Der selbe Wert steht auch immer in ptr->count .
    • Du Wertest das erste Ergebnis ( find_data nach FindFirstFile() ) nicht aus und "übersiehst" dadurch immer eine Datei.
    • if (strcmp(find_data.cFileName, "..") != 0) /* ... */ schließt nur /. und /.. aus - anderen Verzeichnisse landen in deiner Liste.
    • if (strstr (find_data.cFileName,".exe") == NULL){ Prüft nicht die Extension gegen ".exe sondern schlägt immer an, sobald sich ".exe" irgendwo im Dateinamen befindet.
    • strcpy(&ptr->data[run++][_STR], find_data.cFileName); ... strcpy( ptr->data[ ptr->count ], find_data.cFileName); täts auch ...
    • FindClose(find_handle); fehlt.
    • Fehlerbehandlung fehlt komplett.
    • Bezeichner, die mit einem Underscore beginnen sind reservierte Bezeichner und dürfen nicht verwendet werden (§7.1.3.1).


  • _STR ist für die Katz, wenn ich an strcpy ohen "&" übergebe.

    •Du Wertest das erste Ergebnis (find_data nach FindFirstFile()) nicht aus und "übersiehst" dadurch immer eine Datei.

    Ist bei mir immer "."

    if (strstr (find_data.cFileName,".exe") == NULL){ Prüft nicht die Extension gegen ".exe sondern schlägt immer an, sobald sich ".exe" irgendwo im Dateinamen befindet.

    Stimmt, aber ich habe keine Dateien die "test.exeample.pdf" heißen oder so.

    Rest bisschen nachgebessert:
    fhandler.h

    #include <windows.h>  
    #define FH_LENGTH  125
    #define FH_FILES    20  
    
    typedef struct{
    	 char data[FH_FILES][FH_LENGTH];
    	 int count;
    	}F_HANDLE;
    
    int fhandler(F_HANDLE *ptr);
    

    fhandler.c

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include "fhandler.h"
    
    int fhandler(F_HANDLE *ptr){
    
    WIN32_FIND_DATAA find_data; 
    HANDLE find_handle = FindFirstFileA( "*", &find_data );
    ptr->count=0;    
    
        while( FindNextFileA( find_handle, &find_data ) ) {
    
    	   if( strcmp(find_data.cFileName, "..") != 0){
    		   if (strstr (find_data.cFileName,".exe") == NULL){
    		   	//puts( find_data.cFileName ); 
    		   	strcpy(ptr->data[ptr->count++], find_data.cFileName);	
    
    			   if (ptr->count >= FH_FILES){
    			   	   puts("Max defined in FH_FILES exceeded\n");
    			   	   system("pause");
    			   	   return 1;
    			   }			   	    	   	 
    		   }
    	   } 	 	
        }
     FindClose(find_handle) ;  
     }//END
    

    main.c

    #include <stdio.h>
    #include <stdlib.h>
    #include <windows.h>
    #include <string.h>
    #include "fhandler.h"
    
    int main(int argc, char *argv[]) {  
    
    char *filename;
    int z1, run;
    
    //____BEGIN_____________
    F_HANDLE verz;
    fhandler(&verz);
    filename=malloc(FH_LENGTH); 
    
    if(!filename){
    	puts("dreck");
    	return 0;
    }
    
    for(run=0; run<verz.count; run++){
    	strcpy(filename, verz.data[run]);
    	printf("Datei Nr.: %2d   Name : %s\n", run, filename);
    }
    
    free(filename); 
    	return 0;
    }
    

    Es sind viele #includes, aber meine IDE (Dev C++ ... ja ich weiß, aber auf Arbeit geht´s hald nicht anders) motzt sonst.



  • Swordfish schrieb:

    • _FH_LENGTH sollte MAX_PATH + 1 sein.

    "+ 1" ist überflüssig. Vgl. http://msdn.microsoft.com/en-us/library/aa365247.aspx



  • Tatsächlich! 😮 😮 😮



  • Nathan schrieb:

    -die erste Datei wird nicht gefunden (das ist afaik zwar eh immer '.', also das aktuelle Verzeichnis, aber trotzdem)

    Der erste Eintrag ist wohl meistens '.', aber nicht im Root-Directory, z. B. mit lpFileName = "C:\*" bei FindFirstFile.


Anmelden zum Antworten