Перед тем ,как читать или писать в файл , нужно установить коннект с файлом .
Существует 2 подхода :
1. Файловые дескрипторы - имеют тип int
Это низкоуровневый интерфейс , к тому же не портабельный .
2. Потоки - имеют тип FILE *
Это высокоуровневый интерфейс с буферизацией .
Имеет мощные форматирующие функции ввода-вывода-printf,scanf
Позиция файла - базовое понятие , означающее число байт от начала файла .
Типичные ошибки доступа к файлам :
1. EACCES - нет разрешения
2. ENAMETOOLONG - имя файла превышает заданную длину
3. ENOENT - ссылка на несуществующий файл
4. ENOTDIR - ссылка на якобы директорию , которая на самом деле - файл
5. ELOOP - слишком много ссылок на файл
Потоки ввода-вывода :
при старте функции main мы уже имеем 3 потока :
FILE * stdin - ввод
FILE * stdout - вывод
FILE * stderr
Например , для перенаправления вывода в файл , можно сделать :
fclose (stdout);
stdout = fopen ("standard-output-file", "w");
Открытие файла :
1.FILE * fopen (const char *filename, const char *opentype)
2.FILE * fopen64 (const char *filename, const char *opentype)
открывает очень большие файлы
3.FILE * freopen (const char *filename, const char *opentype, FILE *stream)
открывает файл с предварительным закрытием,если открыт
4.int __freadable (FILE *stream)
определяет , открыт ли файл на чтение
5.t __fwritable (FILE *stream)
определяет,открыт ли файл на запись
6.int __freading (FILE *stream)
открыт ли файл на чтение или на запись
Закрытие :
1.int fclose (FILE *stream)
2.int fcloseall (void)
Многопоточное программирование и работа с файлами налагают дополнительную ответственность
на программиста .
Потоковые операции имеют атомарный уровень . Т.е. если выполняются 2 потока и в каждом
из них выполняется потоковая операция , то в сумме они выполняются так , как если бы они
исполнялись последовательно , вне потока . Для блокирования потоков необходимо выполнять
специальные функции .
1. void flockfile (FILE *stream)
2. int ftrylockfile (FILE *stream)
3. void funlockfile (FILE *stream)
Пример вывода в файл для многопоточного приложения :
FILE *fp;
{
flockfile (fp);
fputs ("This is test number ", fp);
fprintf (fp, "%d\n", test);
funlockfile (fp)
}
Пример разблокирования :
void
foo (FILE *fp)
{
if (ftrylockfile (fp) == 0)
{
fputs ("in foo\n", fp);
funlockfile (fp);
}
}
Следующий пример показывает использование функции fgetc
int
y_or_n_p (const char *question)
{
fputs (question, stdout);
while (1)
{
int c, answer;
/* Write a space to separate answer from question. */
fputc (' ', stdout);
/* Read the first character of the line.
This should be the answer character,but might not be.*/
c = tolower (fgetc (stdin));
answer = c;
/* Discard rest of input line. */
while (c != '\n' && c != EOF)
c = fgetc (stdin);
/* Obey the answer if it was valid. */
if (answer == 'y')
return 1;
if (answer == 'n')
return 0;
/* Answer was invalid: ask for valid answer. */
fputs ("Please answer y or n:", stdout);
}
}
Следующий пример показывает использование printf , в примере определяется структура Widget
и распечатываются ее аргументы .
#include < stdio.h >
#include < stdlib.h >
#include < printf.h >
typedef struct
{
char *name;
} Widget;
int print_widget (FILE *stream,const struct printf_info *info
,const void *const *args)
{
const Widget *w;
char *buffer;
int len;
/* Format the output into a string. */
w = *((const Widget **) (args[0]));
len = asprintf (&buffer, "", w, w->name);
if (len == -1) return -1;
/* Pad to the minimum field width and print to the stream. */
len = fprintf (stream, "%*s",
(info->left ? -info->width : info->width), buffer);
/* Clean up and return. */
free (buffer);
return len;
}
int print_widget_arginfo (const struct printf_info *info, size_t n, int *argtypes)
{
/*We always take exactly one argument and this is a pointer to the structure*/
if (n > 0)
argtypes[0] = PA_POINTER;
return 1;
}
int main (void)
{
/* Make a widget to print. */
Widget mywidget;
mywidget.name = "mywidget";
/* Register the print function for widgets. */
register_printf_function ('W', print_widget, print_widget_arginfo);
/* Now print the widget. */
printf ("|%W|\n", &mywidget);
printf ("|%35W|\n", &mywidget);
printf ("|%-35W|\n", &mywidget);
return 0;
}
|