Почему "fopen" возвращает указатель NULL?

Я работаю над простой программой сплиттера/слияния файлов на языке программирования C. Проблема в том, что почему-то fopen возвращает NULL, и из-за этого моя программа рушится на fwrite. Как это исправить?

Вот файл 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

Правильная вещь - проверить errno, когда fopen возвращает NULL.

Я собираюсь угадать, что ваша проблема заключается в том, что вы пытаетесь записать файловую систему, которая не позволяет \n в именах файлов, но это может быть проблема с разрешениями.

Ответ 2

Есть много причин, по которым fopen может возвращать NULL, включая (но не ограничиваясь этим):

  • Файл не существует
  • Файл открывается в режиме, который не разрешает другие обращения
  • Сеть отключена.
  • Файл существует, но у вас нет прав доступа
  • Файл существует с именем, которое вы указали, но текущий каталог процесса не соответствует ожидаемому, поэтому относительный путь не может найти и открыть файл.

Способ выяснить, что несет ответственность, - это выкопать код errno.

Однако только потому, что вы разрешаете эту конкретную ошибку, не означает, что вы можете предположить, что fopen никогда не вернет NULL. При работе с операциями ввода-вывода ваш код просто должен ожидать отказа. Невозможно предсказать успех операций ввода-вывода, и они всегда могут выйти из строя.

Ответ 3

Это означает, что файл может отсутствовать или возникла некоторая ошибка разрешения при доступе к файлу, например "Только для чтения" или "Защита от записи", поэтому в тех случаях fopen вернет 0 (указатель NULL). При успешном завершении он вернет указатель файла в качестве обработчика.

fp=fopen("c:\\ABC.txt", "r"); не может быть таким же, как fp=fopen("c:\\ABC.txt", "r");.

Используйте // вместо \\ в среде Linux.

P.S.: В Linux и Unix-подобных операционных системах имена файлов чувствительны к регистру.

Ответ 4

Является ли fopen для записи return NULL в первом запуске?

Я заметил, что пока вы держите открытые файлы для записи, но не закрываете их.

Попробуйте добавить fclose (outFile) после fwrite:

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

Возможно, вы открываете больше файлов, чем позволяет ваша ОС.

Ответ 5

Как сказал Гейб, ваша проблема - это новая строка в имени файла, которая является незаконной в Windows.

Но почему бы вам просто не использовать split из GNU Core Utilities. Установленный по умолчанию в Unices/Linux, можно загрузить для Windows из проекта GnuWin32.

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

Ответ 6

В Unix для fopen() нет причин для добавления./к имени файла, переданному fopen().

Ответ 7

В моем случае я снова читал один и тот же файл в цикле while и забыл закрыть его.

Я использовал функцию для чтения файла и поиска соответствия, и функция имела оператор return;, который завершил функцию перед выполнением fclose(fp): D

Ответ 8

Путь, указанный для файла, проверяется везде, где присутствует исполняемый файл. В моем случае я открывал текстовый файл в файле c, когда оба присутствовали в одном и том же месте. Он постоянно выдавал ошибку файла не найден. Поместил файл в папку исполняемого файла и он начал работать.

Ответ 9

В моем случае это было потому, что я пытался создать файл в каталоге, который НЕ существует.