C专题8:文件操作2

发布于:2025-07-27 ⋅ 阅读:(11) ⋅ 点赞:(0)

6.文件位置

ftell: 返回当前的文件位置指示值
fgetpos: 获取文件位置指示器
fseek: 将文件位置指示符移动到文件中的指定位置
fsetpos: 将文件位置指示器移动到文件中的指定位置
rewind: 将文件位置指示器移动到文件首

long ftell( FILE *stream );

返回流 stream 的文件位置指示器。
        若流以二进制模式打开,则由此函数获得的值是从文件开始的字节数。
        若流以文本模式打开,则由此函数返回的值未指定,且仅若作为fseek()的输入才有意义。
参数
        stream: 要检验的文件流
返回值
        成功时为文件位置指示器,若失败发生则为-1L。失败时,设errno对象为实现定义的正值

int fgetpos( FILE *stream, fpos_t *pos );

        获得文件流 stream 的文件位置指示器和当前分析状态(若存在),并将它们存储于pos所指向的对象。存储的值仅在作为fsetpos的输入的情况有意义。
参数
        stream要检验的文件流
        pos指向要存储文件位置指示器到的fpos_t对象的指针
返回值
        成功为0,否则为非0值

int fseek( FILE *stream, long offset, int origin );

设置文件流 stream 的文件位置指示器为 offset 所指向的值。
        1)若 stream 以二进制模式打开,则新位置准确地是文件起始后(若 origin 为 SEEK_SET)或当前文件位置后(若 origin 为 SEEK_CUR),或文件结尾后(若 origin 为 SEEK_END)的 offset 字节。不要求二进制流支持 SEEK_END,尤其是是否输出附加的空字节。
        2)若 stream 以文本模式打开,则仅有的受支持 offset 值为零(可用于任何 origin)和先前在关联到同一个文件的流上对 ftell 的调用的返回值(仅可用于 SEEK_SET 的 origin )。
        3)若 stream 为宽面向,则一同应用对文本和二进制流的限制(允许 ftell 的结果与 SEEK_SET 一同使用,并允许零 offset 以 SEEK_SET 和 SEEK_CUR 但非 SEEK_END 为基准)。除了更改文件位置指示器,fseek 还撤销 ungetc 的效果并清除文件尾状态,若可应用。若发生读或写错误,则设置流的错误指示器(ferror)而不影响文件位置。
参数
        stream: 要修改的文件流
        offset: 相对 origin 迁移的字符数
        origin: offset 所加上的位置。它能拥有下列值之一:SEEK_SET、SEEK_CUR、SEEK_END
返回值
        成功为0,否则为非0值

int fsetpos(FILE *stream, const fpos_t *pos);

        按照pos所指向的值,设置文件流stream的文件位置指示器和多字节分析状态(若存在)。除了建立新的分析状态和位置,调用此函数还会撤销ungetc的效果,并若设置了文件尾状态则清除之。若读或写出现错误,则设置流的错误指示器(ferror)。
参数
        stream要修改的文件流
        pos指向fpos_t对象的指针,用作文件位置指示器的新值
返回值
        成功时为0,否则为非零值。

void rewind( FILE *stream);

        移动文件位置指示器到给定文件流的起始。函数等价于fseek(stream, 0, SEEK_SET),除了它清除文件尾和错误指示器。此函数丢弃任何来自先前对ungetc调用的效果。
参数
        stream要修改的文件流
返回值(无)

7.错误处理

clearerr  清除错误
feof  检查文件结尾
ferror  检查文件错误
perror  显示对应当前错误的字符串到stderr

void clearerr( FILE *stream );

        重置给定文件流的错误标志和EOF指示器。
参数
        stream:  要重置错误标志的文件流
返回值(无)

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>

int main(void)
{
    FILE* tmpf = tmpfile();
    fputs("abcde\n", tmpf);
    rewind(tmpf);
    int ch;
    while((ch=fgetc(tmpf))!=EOF)
        printf("%c", ch);
    assert(feof(tmpf)); // 此循环期待以 eof 终止

    puts("End of file reached");
    clearerr(tmpf); // 清除 eof

    if (feof(tmpf))
        puts("EOF indicator set");
    else
        puts("EOF indicator cleared\n");
}

 int feof(FILE *stream);

        检查是否已抵达给定文件流的结尾。
参数
        stream  要检验的文件流
返回值
        若已抵达流尾则为非零值,否则为0
注意
        此函数仅报告最近一次 I/O 操作所报告的流状态,而不检验关联的数据源。例如,若最近一次 I/O 是抵达文件最后字节的 fgetc,则 feof 返回零。下个 fgetc 失败并更改流状态为文件尾。然后 feof 才返回非零。
        典型用法中,输入流处理在任何错误时停止;而 feof 和 ferror 用于区别不同错误条件。

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    FILE* fp = fopen("test.txt", "r");
    if (!fp) {
        perror("File opening failed");
        return EXIT_FAILURE;
    }
    int c;
    while ((c = fgetc(fp)) != EOF) {
        putchar(c);
    }
    if (ferror(fp))
        puts("I/O error when reading");
    else if (feof(fp))
        puts("End of file reached successfully");
    fclose(fp);
}

int ferror(FILE *stream);

        检查给定文件流的错误。
参数
        stream 要检查的文件流
返回值
        若文件流已出现错误则为非零值,否则为0

void perror(const char *s);

        打印当前存储于系统变量 errno 的错误码到 stderr。
通过连接下列组分构成描述:
● s 所指向的空终止字节字符串的内容后随“: ”(除非 s 为空指针或 s 所指向字符为空字符)
● 实现定义的,描述存储于 errno 的错误码的错误消息字符串
● 后随换行符“\n”
错误消息字符串等同于 strerror(errno)的结果。
参数
        s 指向带解释消息的空终止字符串的指针
返回值 无

8.文件操作

remove  删除文件
rename  重命名文件
tmpfile  返回指向临时文件的指针
tmpfile_s  (c11)

int remove(const char *fname)

        删除fname所指向的字符串所标识的文件。若文件为当前进程或另一进程打开,则此函数行为是实现定义的。具体而言,POSIX系统解链接文件名,到最后一个运行的进程关闭该文件为止,即使这是最后一个到文件的硬链接也不回收文件系统空间。Windows不允许删除该文件。
参数
        fname 指向空终止字符串的指针,字符串含标识待删除文件的路径
返回值
        成功时为0,错误时为非零值。
注意 POSIX 指定此函数行为的许多额外细节。

#include<stdio.h>
int main(void)
{
    FILE* fp = fopen("file1.txt", "w");
    if(!fp) {
        perror("file1.txt");
        return 1;
    }
    puts("Created file1.txt");
    fclose(fp);

    int rc = remove("file1.txt");
    if(rc) {
        perror("remove");
        return 1;
    }
    puts("Removed file1.txt");

    fp = fopen("file1.txt", "r");
    if(!fp)
        perror("Opening removed file failed");
}

rc = remove("file1.txt");
if(rc)
    perror("Double-remove failed");

int rename(const char *old_filename, const char *new_filename);

        更改文件的文件名。该文件以old_filename所指向的字符串标识。新文件名以new_filename所指向的字符串标识。若new_filename存在,则行为是实现定义的。
参数
        old_filename 指向包含标识要重命名的文件的路径的空终止字符串的指针
        new_filename 指向包含文件新路径的空终止字符串的指针
返回值
        成功时为0,失败时为非零值。

#include<stdio.h>

int main(void)
{
    FILE* fp = fopen("from.txt", "w");
    if(!fp) {
        perror("from.txt");
        return 1;
    }
    fputc('a', fp);
    fclose(fp);

    int rc = rename("from.txt", "to.txt");
    if(rc) {
        perror("rename");
        return 1;
    }

    fp = fopen("to.txt", "r");
    if(!fp) {
        perror("to.txt");
        return 1;
    }
    printf("%c\n", fgetc(fp));
    fclose(fp);
}

9.无格式输入/输出

fgetc  getc  从文件流获取一个字符
fgets   从文件流获取一个字符串
fputc putc  将一个字符写入文件流
fputs   将一个字符串写入文件流
getchar   从 stdin 读取一个字符
gets(C11 中移除)
gets_s   从 stdin 读取一个字符串
putchar   将一个字符写入 stdout
puts    将一个字符串写入 stdout
ungetc   将一个字符送回文件流

int fgetc( FILE *stream );        int getc( FILE *stream );

        从给定的输入流读取下一个字符。getc()可以实现为宏。
参数
        stream 读取字符的来源
返回值
        成功时为获得的字符,失败时为EOF。
        若文件尾条件导致失败,则另外设置stream上的文件尾指示器(见feof()。若某些其他错误导致失败,则设置stream上的错误指示器(见ferror()

int fputs( const char         *str, FILE         *stream );
int fputs( const char *restrict str,FILE *restrict stream );

        将以NULL结尾的字符串str的每个字符写入到输出流stream,如同通过重复执行fputc。不将str的空字符写入
参数
        str 要写入的空终止字符串
        stream 输出流
返回值
        成功时,返回非负值。        失败时,返回EOF并设置stream上的错误指示器(见rror)。
注意
        相关函数puts后附新换行符到输出,而fputs写入不修改的字符串。不同的实现返回不同的非负数:一些返回最后写入的字符,一些返回写入的字符数(或若字符串长于INT_MAX则为该值),一些简单地非负常量,例如零。

int getchar(void);

         从 stdin 读取下一个字符。等价于 getc(stdin)。
参数(无)
返回值
        成功时为获得的字符,失败时为 EOF。若失败由文件尾条件产生,则另外设置 stdin 上的文件尾指示器(见 feof())。若失败由某些其他错误产生,则设置 stdin 上的错误指示器。

char *gets(char *str); (C11 中移除)
char *gets_s(char *str, rsize_t n); (C11 起)

        1)从 stdin 读入 str 所指向的字符数组,直到发现换行符或出现文件尾。在读入数组的最后一个字符后立即写入空字符。换行符被舍弃,但不会存储于缓冲区中。
        2)从 stdin 读取字符直到发现换行符或出现文件尾。至多写入 n-1 个字符到 str 所指向的数组,并始终写入空终止字符(除非 str 是空指针)。若发现换行符,则忽略它并且不将它计入写入缓冲区的字符数。
在运行时检测下列错误并调用当前安装的制约处理函数:
● n为零
● n大于 RSIZE_MAX
● str是空指针
● 在存储 n-1 个字符到缓冲区后没有遇到换行符或文件尾。
        任何情况下,gets_s 首先结束读取并忽略来自 stdin 的字符,直到换行符、文件尾条件,或在调用制约处理前的读取错误。同所有边界检查函数,gets_s 仅若实现定义 __STDC_LIB_EXT1__ 且用户在包含stdio.h前定义 __STDC_WANT_LIB_EXT1__ 为整数常量 1 才保证可用。
参数
        str 要被写入的字符串
        n char 数组的最大长度
返回值
        成功时为 str,失败时为空指针。若文件尾条件导致了失败,则附加设置 stdin 的文件尾指示器(见 feof() )。若其他某些原因导致了失败,则设置 stdin 的错误指示器。
注解
        gets() 函数不进行边界检查,从而此函数对缓冲区溢出攻击极度脆弱。无法安全使用它(除非程序运行的环境限定能出现在 stdin 上的内容)。因此,此函数在 C99 的第三次勘误中被弃用,而在 C11 标准发布时被移除。推荐的替代品是 fgets() 和 gets_s()。绝对不要用 gets()。

int putchar( int ch );

        写字符 ch 到 stdout。在内部,字符于写入前被转换为 unsigned char。等价于 fputc( ch , stdout )。
参数
        ch 要被写入的字符
返回值
        成功时返回写入的字符。失败时返回 EOF 并设置 stdout 上的错误指示器(见 ferror )。

int puts(const char *str);

        写入每个来自空终止字符串str的字符及附加换行符'\n'到输出流stdout,如同以重复执行putc写入。
不写入来自str的空终止字符。
参数
        str 要写入的字符串
返回值
        成功时返回非负值;失败时,返回EOF并设置stdout的错误指示器(见ferror())。
注意
        puts函数后附一个换行字符到输出,而fputs不这么做。不同的实现返回不同的非负数:一些返回最后写入的字符,一些返回写入的字符数(或若字符串长于INT_MAX则返回它),一些简单地返回非负常量。在重定向stdout到文件时,导致puts失败的典型原因是用尽了文件系统的空间。

int ungetc( int ch, FILE *stream );

        若 ch 不等于 EOF,则推入字符 ch (转译为 unsigned char )到与流 stream 关联的输入缓冲区,方式满足从 stream 的后继读取操作将取得该字符。不修改与流关联的外部设备。
        流重寻位操作 fseek、fsetpos 和 rewind 弃去 ungetc 的效果。
        若调用 ungetc 多于一次,而无中间读取或重寻位,则可能失败(换言之,保证大小为 1 的回放缓冲区,但任何更大的缓冲区是实现定义的)。若成功进行多次 ungetc ,则读取操作以 ungetc 的逆序取得回放的字符。
        若 ch 等于 EOF ,则操作失败而不影响流。
        对 ungetc 的成功调用清除文件尾状态标志 feof 。
        在二进制流上对 ungetc 的成功调用将流位置指示器减少一(若流位置指示器为零,则行为不确定)。
        在文本流上对 ungetc 的成功调用以未指定方式修改流位置指示器,但保证在以读取操作取得所有回放字符后,流位置指示器等于其在 ungetc 之前的值。
参数
        ch 要推入输入流缓冲区的字符
        stream 要回放字符到的文件流
返回值
        成功时返回 ch 。
        失败时返回 EOF ,而给定的流保持不变。
注意
        实践中,回放缓冲区的大小会在 4k ( Linux 、 MacOS )和 4 ( Solaris )或保证的最小值 1 ( HPUX 、 AIX )间变化。若回放的字符等于存在于外部字符序列中该位置的字符,则回放缓冲区的表观大小可以更大(实现可以简单地自减读取的文件位置指示器,并避免维护回放缓冲区)。


网站公告

今日签到

点亮在社区的每一天
去签到