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" nettJa, 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 wieFindFirstFile()
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
sollteMAX_PATH
sein.- Der Datentyp für Speichergrößen ist
size_t
aus<stddef.h>
, nichtint
. - Wenn eine Anzahl von Dateien größer
_FH_FILES
gefunden werden kackt dein Code ohne Fehlerbehandlung ab. - Wofür
run
infhandler()
? Der selbe Wert steht auch immer inptr->count
. - Du Wertest das erste Ergebnis (
find_data
nachFindFirstFile()
) 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).
- Wofür
-
_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
sollteMAX_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.