2011-05-13 13 views
10

Pracuję nad prostym programem dzielenia plików/łączenia w języku programowania C. Problem polega na tym, że z jakiegoś powodu fopen zwraca NULL, a z tego powodu mój program ulega awarii na oświadczeniu fwrite. Jak to naprawić?Dlaczego "fopen" zwraca wskaźnik NULL?

Tutaj jest plik C:

int SplitFile(char* filename, char* output, size_t size) 
{ 
    char current_file_name[256]; 
    int file_count = 0, i = 0; 
    FILE *file = fopen(filename, "rb"); 
    printf("split %s into chunks of %d named\n", filename, size); 

    if (!file) 
     return E_BAD_SOURCE; 
    else 
    { 
     output = (char *) malloc(size * sizeof(char)); 
     if (output == NULL) 
      return E_NO_MEMORY; 
     else 
     { 
      int bytes_read = 0; 
      FILE *outFile; 
      do 
      { 
       bytes_read = fread(output, sizeof(char), size, file); 
       sprintf(current_file_name, "%s%04lu\n", "part", file_count++); 
       outFile = fopen (current_file_name, "wb"); // THIS RETURNS NULL 
       fwrite(output, sizeof(char), bytes_read, outFile); //CRASHES ON THIS LINE 
      } 
      while (bytes_read > 0) 
       ; 

      //fclose(outFile); 
     } 
    } 
    fclose(file); 
    printf("...\n"); 
    return 0; 
} 
+1

Snarky - sprawdzić plik otwierany przed spróbować napisać do niego. Prawdziwa odpowiedź brzmi: prawdopodobnie nie masz uprawnień do systemu plików lub znajduje się w ścieżce do folderu, która nie istnieje – EnabrenTane

+9

Jaki błąd jest zapisany w 'errno'? Po prostu dodaj 'if (! OutFile) perror (" fopen ");' i pozwól bibliotece powiedzieć dlaczego się nie udało. :) – sarnold

+0

w errno Dostaję fopen: nieważny argument – k787

Odpowiedz

9

Właściwą rzeczą do zrobienia jest sprawdzić errno gdy fopen powraca NULL.

Zgaduję, że problem polega na tym, że próbujesz pisać do systemu plików, który nie zezwala na \n w nazwach plików, ale może to być problem z uprawnieniami.

+1

Właściwą sprawą jest sprawdzenie errno, gdy fopen zwróci NULL. Prawdopodobnie miałeś na myśli fopen zamiast fwrite. –

+0

kiedy komentuję sprintf i robię to; outFile = fopen ("part000", "wb"); to działa dobrze. – k787

+0

@Windows: Ups! Dzięki. – Gabe

0

Czy fopen do zapisu zwraca NULL w pierwszym uruchomieniu?

Zauważyłem, że podczas gdy ty trzymasz otwarte pliki do zapisu, ale nie zamykając ich.

Spróbuj dodać fclose (plik_wy) po fwrite:

outFile = fopen (current_file_name , "wb");  
fwrite(output, sizeof(char), bytes_read, outFile); 
fclose(outFile) 

Możliwe jest otwarcie więcej plików niż system operacyjny pozwala.

+0

tak Myślałem o tym samym i zamknąłem pliki, ale nie działało – k787

1

Jak powiedział Gabe, Twoim problemem jest nowa linia w nazwie pliku, która jest nielegalna w systemie Windows.

Ale dlaczego po prostu nie użyjesz podziału z GNU Core Utilities. Zainstalowany domyślnie na Unices/Linux, można pobrać na Windows z GnuWin32 project.

split --suffix-length=4 --numeric-suffixes --bytes=1M - part < filename 
5

Istnieje wiele powodów fopen może powrócić NULL tym (ale na pewno nie tylko):

  • Plik nie istnieje
  • Plik jest otwierany w trybie, który nie zezwalaj na dostęp innym
  • Sieć jest wyłączona
  • Plik istnieje, ale nie masz uprawnień
  • Plik istnieje z podaną nazwą, ale bieżący katalog procesu nie jest zgodny z oczekiwaniami, więc względna ścieżka dostępu nie znajduje i nie otwiera pliku.

Aby dowiedzieć się, kto jest odpowiedzialny, należy zagłębić się w kod errno.

Jednak tylko dlatego, że rozwiązujesz ten konkretny błąd, nie oznacza to, że możesz założyć, że fopen nigdy nie zwróci NULL. Podczas pracy z operacjami we/wy kod musi po prostu oczekiwać porażki. Nie można przewidzieć sukcesu operacji we/wy i zawsze mogą się nie udać.

+0

co z brakującym miejscem? Czy to nie sprawi, że zwróci NULL? (wiem, że powiedziałeś "nie ogranicza się do" moje pytanie nie jest retoryką) – Nande

+0

@Nande: 'fopen()', który tworzy nowy plik może lub nie może się powieść na pełnym dysku. Jeśli katalog nie potrzebuje rozwinąć (i nie jesteś poza i-węzłami), może się to udać, ale następujące 'fwrite()' (** lub ** 'fclose()'!) Zakończy się niepowodzeniem. –

1

Oznacza to, że plik może nie istnieć lub wystąpił błąd uprawnień podczas uzyskiwania dostępu do pliku, takiego jak "Tylko do odczytu" lub "Chroniony przed zapisem", więc w tych przypadkach fopen zwróci 0 (wskaźnik NULL). Po sukcesie zwróci wskaźnik pliku jako moduł obsługi.

fp=fopen("c:\\ABC.txt", "r"); nie może być taki sam jak fp=fopen("c:\\abc.txt", "r");.

Użyj // zamiast \\ w środowisku Linux.

P.S .: w systemach operacyjnych Linux i nazw plików uniksowych są rozróżniana.

0

W systemie Unix, dla fopen(), nie ma powodu, aby poprzedzać ./ nazwę pliku przekazaną do fopen().

0

W moim przypadku czytałem ten sam plik w pętli while i zapomniałem go zamknąć.

użyłem funkcji do odczytu pliku i znalezienia dopasowania, a funkcja miała return; oświadczenie, że zakończony funkcję przed wykonaniem fclose(fp): D

Powiązane problemy