2012-12-19 14 views
7

Powiel możliwe:
What’s the best way to check if a file exists in C? (cross platform)C, sprawdź, czy plik istnieje bez możliwości odczytu/zapisu?

chciałbym sprawdzić, czy plik istnieje, czy nie. Zmieniłem uprawnienia mojego pliku testowego na "chmod -r somefile". Jednak teraz mówi, że plik nie istnieje, mimo że istnieje.

Zakładam więc, że jeśli nie mam uprawnień do odczytu, nie mogę otworzyć pliku z "fopen r". Ale to oznaczałoby, że nie ma łatwego sposobu na stwierdzenie, czy plik istnieje, czy nie można go odczytać/napisać?

A może czegoś brakuje? Każda pomoc byłaby świetna.

Dzięki!

int doesFileExist(const char* filename) 
{ 
    FILE* fptr = fopen(filename, "r"); 
    if (fptr != NULL) 
    { 
    fclose(fptr); 
    printf("File exists\n"); 
    return 1; 
    } 
    printf("File doesnt exist\n"); 
    return 0; 
} 

Aktualizacja: Dzięki chłopaki za te świetne linki i objaśnienia!

+1

Um .. Czy można sprawdzić 'errno'? EDYCJA: spróbuj tego, aby uzyskać komunikat o błędzie: 'printf (" Plik nie istnieje:% s \ n ", strerror (errno));' nie zapomnij dołączyć nagłówka 'errno.h'. – Jack

+0

Tego właśnie nie lubię w przypadku stdio API, gdy trzeba zrobić coś nietuzinkowego, np. Zmienić rozmiar pliku lub przenieść plik bez kopiowania go i usuwania starego, nie ma szczęścia pod względem przenośności. – Thomas

Odpowiedz

18

fopen faktycznie próbuje otworzyć plik, którego nie można wykonać, jeśli nie masz dostępu do odczytu. Aby sprawdzić, czy plik istnieje bez jego otwierania, użyj stat; stat udostępnia metadane dotyczące pliku i wymaga tylko prawa odczytu do katalogu zawierającego plik, a nie do samego pliku.

int doesFileExist(const char *filename) { 
    struct stat st; 
    int result = stat(filename, &st); 
    return result == 0; 
} 

Można dostać hodowcy sprawdzając errno jeśli result nie jest 0; jeśli errno to ENOENT, to plik nie istnieje, jeśli jest to ENOTDIR, wtedy część podanej ścieżki nie jest katalogiem, jeśli jest to EACCESS, to nie masz uprawnień do odczytu w jednym z katalogów na ścieżce, więc można stat nie da ci odpowiedzi i tak dalej.

Należy również pamiętać, że jeśli korzystasz z platformy z dowiązaniami symbolicznymi (w systemie Unix lub Windows Vista lub nowszym), powinieneś wiedzieć, czy pytasz o dowiązanie symboliczne lub plik, do którego prowadzi. . Jeśli zadzwonisz pod numer stat, pytasz o plik, do którego on prowadzi; jeśli masz dowiązanie symboliczne dir/link, które wskazuje na other/file, wtedy stat zwróci wyniki o other/file (zwykle jest to, co chcesz, ponieważ to, co otrzymasz, jeśli otworzyłeś plik).Jednakże, jeśli jesteś zainteresowany samym linkiem (jeśli chcesz wiedzieć "czy istnieje dir/link, nawet jeśli other/file nie działa?"), Powinieneś użyć lstat().

stat() działa w systemie Windows jako opakowanie kompatybilności (wolą używać _stat() i ostrzega, jeśli tego nie zrobi), ale ogólnie lepiej jest używać platform API platformy macierzystej. W systemie Windows, powinieneś użyć GetFileAttributes():

int doesFileExist(const char *filename) { 
    return GetFileAttributes(filename) != INVALID_FILE_ATTRIBUTES; 
} 
-1

W systemie Linux (i wielu innych systemach) można używać katalogów opendir() i znajomych. Domyślam się, że pojawią się pliki tylko do odczytu. Powinny być podobne funkcje dostępne na innych platformach.

1

Naprawdę nie sprawdzasz, czy plik istnieje tutaj ... Sprawdzasz, czy możesz otworzyć go z dostępem do odczytu. Mogło się nie powieść z przyczyn innych niż plik nieistniejący. Jak widzisz, możesz nie mieć uprawnień do odczytu. Możliwe, że plik jest zablokowany.

Sprawdź tę odpowiedź:

What's the best way to check if a file exists in C? (cross platform)

To sugeruje użycie stat, który powinien działać w większości przypadków, z wyjątkiem, jeśli nie przeczytałeś dostępu do katalogu, w którym znajduje się plik.