Почему "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
В моем случае это было потому, что я пытался создать файл в каталоге, который НЕ существует.