C语言writefile函数如何正确使用?

99ANYc3cd6
预计阅读时长 19 分钟
位置: 首页 C语言 正文

在标准 C 语言库(C Standard Library)中,并没有一个叫做 writefile 的函数。

c语言writefile函数
(图片来源网络,侵删)

您很可能指的是在 Linux/Unix 系统中,用于向文件写入数据的系统调用函数 write(),或者在某些特定平台/库中可能存在的自定义函数。write() 是 C 程序员与操作系统进行底层文件交互的核心函数之一。

下面,我将重点介绍标准的 write() 系统调用,因为它是最常见和最基础的理解。


核心概念:write() 系统调用

write() 函数用于将缓冲区中的数据写入到一个已打开的文件、管道、套接字等文件描述符中。

函数原型

#include <unistd.h> // 头文件
ssize_t write(int fd, const void *buf, size_t count);

参数详解

  1. int fd: 文件描述符

    c语言writefile函数
    (图片来源网络,侵删)
    • 这是一个非负整数,是操作系统为每个打开的文件、设备、管道等分配的唯一标识符。
    • 你不能直接通过文件名(如 "myfile.txt")来写入,必须先通过 open() 函数打开文件,它会返回一个文件描述符。
    • 标准文件描述符
      • 0: 标准输入
      • 1: 标准输出
      • 2: 标准错误
  2. const void *buf: 缓冲区指针

    • 这是一个指向内存缓冲区的指针,缓冲区中存放了你想写入文件的数据。
    • const 关键字表示 write() 函数不会修改这个缓冲区中的内容。
    • 它的类型是 void *,意味着它可以指向任何类型的数据(如 char*, int*, struct* 等)。
  3. size_t count: 要写入的字节数

    • 指定了你想从 buf 缓冲区中写入多少个字节到文件中。

返回值

  • 成功时:返回实际写入文件的字节数,这个值可能会小于 count,原因可能包括:
    • 文件达到了其最大大小限制。
    • 写入了磁盘上的可用空间。
    • 从管道或套接字读取数据的进程消费了数据。
  • 出错时:返回 -1,并设置全局变量 errno 来指示具体的错误原因。

常见错误

  • EBADF: fd 不是一个有效的文件描述符,或者它没有被以写方式打开。
  • EINTR: 写操作被信号中断。
  • EAGAINEWOULDBLOCK: 文件描述符被设置为非阻塞模式,并且写操作会阻塞。
  • EFAULT: buf 指针指向了进程的不可访问地址空间。

使用 write() 的完整示例

下面是一个完整的示例,展示了如何使用 open()write() 函数来创建一个文件并向其中写入内容。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>      // open() 函数的头文件
#include <unistd.h>     // write(), close() 函数的头文件
#include <errno.h>      // errno 变量
int main() {
    const char *filename = "test_write.txt";
    const char *message = "Hello, C write() function!\n";
    int fd;             // 文件描述符
    ssize_t bytes_written; // 实际写入的字节数
    // 1. 打开文件 (使用 open)
    // O_CREAT: 如果文件不存在,则创建它
    // O_WRONLY: 以只写方式打开
    // O_TRUNC: 如果文件已存在,则将其长度截断为0
    // 0644: 文件权限 (所有者读写,组和其他用户只读)
    fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0644);
    // 检查 open 是否成功
    if (fd == -1) {
        // 使用 perror() 打印一个描述性错误信息
        perror("Error opening file");
        return EXIT_FAILURE;
    }
    printf("File '%s' opened successfully with fd: %d\n", filename, fd);
    // 2. 写入文件 (使用 write)
    bytes_written = write(fd, message, strlen(message));
    // 检查 write 是否成功
    if (bytes_written == -1) {
        perror("Error writing to file");
        // 即使写入失败,也要记得关闭文件
        close(fd);
        return EXIT_FAILURE;
    }
    printf("Successfully wrote %zd bytes to the file.\n", bytes_written);
    // 3. 关闭文件
    if (close(fd) == -1) {
        perror("Error closing file");
        return EXIT_FAILURE;
    }
    printf("File closed.\n");
    return EXIT_SUCCESS;
}

如何编译和运行

  1. 将代码保存为 write_example.c

    c语言writefile函数
    (图片来源网络,侵删)
  2. 打开终端,使用 GCC 进行编译:

    gcc write_example.c -o write_example
  3. 运行生成的可执行文件:

    ./write_example
  4. 查看输出和结果:

    # 终端输出
    File 'test_write.txt' opened successfully with fd: 3
    Successfully wrote 28 bytes to the file.
    File closed.
    # 查看当前目录下是否生成了文件
    ls -l test_write.txt
    # 查看文件内容
    cat test_write.txt
    # 输出: Hello, C write() function!

write() 与标准 I/O 函数(fputs, fprintf)的对比

作为 C 程序员,你更可能熟悉 fputs(), fprintf(), fputc() 等标准 I/O 函数,它们和 write() 有什么区别?

特性 write() (系统调用) fputs() / fprintf() (标准 I/O 库)
层次 底层,直接与操作系统交互 高层,在用户空间提供缓冲机制
性能 无缓冲,每次调用都会直接触发系统调用,可能较慢 全缓冲(默认对文件)或行缓冲(对终端),数据先写入内存缓冲区,缓冲区满或遇到换行符时才真正写入磁盘,通常更快
可移植性 不可移植,是 POSIX 标准,主要用于 Linux/Unix/macOS 高度可移植,是 ANSI C 标准,可在任何 C 编译器上运行
接口 操作原始字节(void* 操作格式化文本(const char*, printf 风格格式化字符串)
错误处理 返回 -1errno 返回错误指示符(如 EOF),可以使用 ferror()perror() 检查
使用场景 需要精确控制、高性能(如大文件复制)、设备编程、网络编程 99% 的常规文本文件处理,代码更简洁、可读性更高
  • 对于日常的文本文件写入,优先使用标准 I/O 函数(如 fprintf, fputs),因为它们更简单、更安全、通常性能更好。
  • 当你需要极致性能(复制一个几十 GB 的大文件,避免频繁的系统调用开销)、或者需要直接与设备/网络交互、或者在进行系统级编程时,write() 这样的系统调用是更好的选择。

writefile 的其他可能性

虽然 write() 是最可能的答案,但在某些情况下,你可能会遇到名为 writefile 的函数:

  1. 特定平台或库:某些嵌入式系统、游戏引擎(如 GameMaker)或旧的图形库(如 DOS 下的 BGI)可能会提供自己的 writefile 函数,你需要查阅该平台或库的官方文档来了解其用法。

  2. 自定义函数:在某个项目或代码片段中,开发者可能自己实现了一个名为 writefile 的函数,作为对 write() 的一个简单封装,使其更易于使用。

    // 一个可能的 writefile 自定义函数示例
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <fcntl.h>
    #include <unistd.h>
    // 封装 write,使其直接接受文件名和内容
    int writefile(const char *filename, const char *content) {
        int fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0644);
        if (fd == -1) {
            perror("open");
            return -1;
        }
        size_t len = strlen(content);
        ssize_t bytes_written = write(fd, content, len);
        close(fd);
        if (bytes_written == (ssize_t)len) {
            return 0; // 成功
        } else {
            return -1; // 失败
        }
    }
    int main() {
        if (writefile("my_log.txt", "This is a log entry.") == 0) {
            printf("File written successfully.\n");
        } else {
            printf("Failed to write file.\n");
        }
        return 0;
    }

    如果你在代码中看到了这样的函数,你需要找到它的定义(通常在 .h.c 文件中)来理解其具体行为。

当你在 C 语言中谈论“写入文件”时,最核心、最底层的函数是 write(),它不是一个标准的 C 库函数,而是操作系统提供的系统调用,对于绝大多数应用场景,推荐使用更高级、更便携的标准 I/O 函数(如 fprintf),如果你遇到的 writefile 不是 write() 的别名,那么它很可能是一个特定于某个平台或项目的自定义函数。

-- 展开阅读全文 --
头像
Windows句柄在C语言中如何创建与使用?
« 上一篇 前天
dede 页码 当前窗口打开
下一篇 » 前天

相关文章

取消
微信二维码
支付宝二维码

目录[+]