fopen的一个实现(ZT)

博客介绍了open和fopen的区别,open属于低级IO,无缓冲,返回文件描述符,与read、write配合;fopen是高级IO,有缓冲,返回文件指针,与fread、fwrite配合,且大多情况下使用fopen。还给出了fopen的一个实现代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

open和fopen的区别:
前者属于低级IO,后者是高级IO。
前者返回一个文件描述符,后者返回一个文件指针。
前者无缓冲,后者有缓冲。
前者与 read, write 等配合使用, 后者与 fread, fwrite等配合使用。
后者是在前者的基础上扩充而来的,在大多数情况下,用后者。

===============================================

fopen的一个实现

#if        defined(_POSIX_SOURCE)
#include        <sys/types.h>
#endif
#include        <stdio.h>
#include        <stdlib.h>
#include        "loc_incl.h"

#define        PMODE                0666

/* The next 3 defines are true in all UNIX systems known to me.
*/
#define        O_RDONLY        0
#define        O_WRONLY        1
#define        O_RDWR                2

/* Since the O_CREAT flag is not available on all systems, we can't get it
* from the standard library. Furthermore, even if we know that <fcntl.h>
* contains such a flag, it's not sure whether it can be used, since we
* might be cross-compiling for another system, which may use an entirely
* different value for O_CREAT (or not support such a mode). The safest
* thing is to just use the Version 7 semantics for open, and use creat()
* whenever necessary.
*
* Another problem is O_APPEND, for which the same holds. When "a"
* open-mode is used, an lseek() to the end is done before every write()
* system-call.////////////////////////////////////////////////////////////////////////////////////////////////////////
*
* The O_CREAT, O_TRUNC and O_APPEND given here, are only for convenience.
* They are not passed to open(), so the values don't have to match a value
* from the real world. It is enough when they are unique.
*/
#define        O_CREAT                0x010
#define        O_TRUNC                0x020
#define        O_APPEND        0x040

int _open(const char *path, int flags);
int _creat(const char *path, Mode_t mode);
int _close(int d);

FILE *
fopen(const char *name, const char *mode)
{
        register int i;
        int rwmode = 0, rwflags = 0;
        FILE *stream;
        int fd, flags = 0;

        for (i = 0; __iotab[i] != 0 ; i++)
                if ( i >= FOPEN_MAX-1 )
                        return (FILE *)NULL;

        switch(*mode++) {
        case 'r':
                flags |= _IOREAD | _IOREADING;       
                rwmode = O_RDONLY;
                break;
        case 'w':
                flags |= _IOWRITE | _IOWRITING;
                rwmode = O_WRONLY;
                rwflags = O_CREAT | O_TRUNC;
                break;
        case 'a':
                flags |= _IOWRITE | _IOWRITING | _IOAPPEND;
                rwmode = O_WRONLY;
                rwflags |= O_APPEND | O_CREAT;
                break;         
        default:
                return (FILE *)NULL;
        }

        while (*mode) {
                switch(*mode++) {
                case 'b':
                        continue;
                case '+':
                        rwmode = O_RDWR;
                        flags |= _IOREAD | _IOWRITE;
                        continue;
                /* The sequence may be followed by additional characters */
                default:
                        break;
                }
                break;
        }

        /* Perform a creat() when the file should be truncated or when
         * the file is opened for writing and the open() failed.
         */
        if ((rwflags & O_TRUNC)
            || (((fd = _open(name, rwmode)) < 0)
                    && (rwflags & O_CREAT))) {
                if (((fd = _creat(name, PMODE)) > 0) && flags  | _IOREAD) {
                        (void) _close(fd);
                        fd = _open(name, rwmode);
                }
                       
        }

        if (fd < 0) return (FILE *)NULL;

        if (( stream = (FILE *) malloc(sizeof(FILE))) == NULL ) {
                _close(fd);
                return (FILE *)NULL;
        }

        if ((flags & (_IOREAD | _IOWRITE))  == (_IOREAD | _IOWRITE))
                flags &= ~(_IOREADING | _IOWRITING);
        stream->_count = 0;
        stream->_fd = fd;
        stream->_flags = flags;
        stream->_buf = NULL;
        __iotab[i] = stream;
        return stream;
}

在C语言中,`fopen`是`stdio.h`库中的一个函数,用于打开一个文件并返回一个指向该文件的`FILE`指针。如果你想手动编写一个类似功能的程序,可以创建一个简单的文件打开函数,但请注意,这通常不是推荐的做法,因为标准库函数已经非常高效且可靠。 下面是一个简化的示例,仅用于演示如何实现基本的文件打开操作。这个例子将检查文件路径是否存在,并尝试以指定模式(如读取、写入或追加)打开文件: ```c #include <stdio.h> #include <stdlib.h> #include <errno.h> // 错误码 #include <string.h> // 自定义的简单文件打开函数 FILE* my_fopen(const char* filename, const char* mode) { FILE* file = NULL; char* error_message = ""; if (filename == NULL || strlen(filename) == 0) { error_message = "Invalid filename."; goto open_error; } if (mode == NULL || strlen(mode) == 0) { error_message = "Invalid mode."; goto open_error; } int access_mode = strcmp(mode, "r") == 0 ? O_RDONLY : strcmp(mode, "w") == 0 ? O_WRONLY | O_TRUNC : // 追加模式 strcmp(mode, "a") == 0 ? O_WRONLY : // 默认为追加 -1; // 其他模式未处理,抛出错误 if (access_mode == -1) { error_message = "Unsupported file mode."; goto open_error; } file = fopen(filename, mode); open_error: if (file == NULL) { perror(error_message); // 输出错误信息 exit(EXIT_FAILURE); // 执行退出,释放资源 } return file; } int main() { FILE* file = my_fopen("test.txt", "w+"); if (file) { fprintf(file, "Hello, this is a test.\n"); fclose(file); } else { printf("Failed to open the file.\n"); } return 0; } ``` 尽管这个例子给出了基本的思路,但请注意在实际项目中应尽量使用标准库函数`fopen`,因为它已包含了错误处理和其他高级特性。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值