open()的O_APPEND flag和用open()和lseek()将一个文件追加到另一个文件

目录

open()

所需头文件

原型 

描述

O_APPEND

用途

Macro Expansion

用法

lseek()

所需头文件

原型

描述

实现代码


open()

所需头文件

#include <fcntl.h>

原型 

int open (const char *filename, int flags[, mode_t mode])

描述

The open function creates and returns a new file descriptor for the file named by filename. Initially, the file position indicator for the file is at the beginning of the file. The argument mode is used only when a file is created, but it doesn't hurt to supply the argument in any case. 

The flags argument controls how the file is to be opened. This is a bit mask; you create the value by the bitwise OR of the appropriate parameters (using the | operator in C). , for the parameters available. 

The normal return value from open is a non-negative integer file descriptor. In the case of an error, a value of -1 is returned instead. In addition to the usual file name errors , the following errno error conditions are defined for this function: 


EACCES      The file exists but is not readable/writable as requested by the flags argument, the file does not exist and the directory is unwritable so it cannot be created. 


    - EEXIST Both O_CREAT and O_EXCL are set, and the named file already exists. 


    - EINTR The open operation was interrupted by a signal. . 


    - EISDIR The flags argument specified write access, and the file is a directory. 


    - EMFILE The process has too many files open. The maximum number of file descriptors is controlled by the RLIMIT_NOFILE resource limit; . 


    - ENFILE The entire system, or perhaps the file system which contains the directory, cannot support any additional open files at the moment. (This problem cannot happen on the GNU system.) 


    - ENOENT The named file does not exist, and O_CREAT is not specified. 


    - ENOSPC The directory or file system that would contain the new file cannot be extended, because there is no disk space left. 


    - ENXIO O_NONBLOCK and O_WRONLY are both set in the flags argument, the file named by filename is a FIFO , and no process has the file open for reading. 


    - EROFS The file resides on a read-only file system and any of O_WRONLY, O_RDWR, and O_TRUNC are set in the flags argument, or O_CREAT is set and the file does not already exist. 

If on a 32 bit machine the sources are translated with _FILE_OFFSET_BITS == 64 the function open returns a file descriptor opened in the large file mode which enables the file handling functions to use files up to 2^63 bytes in size and offset from -2^63 to 2^63. This happens transparently for the user since all of the lowlevel file handling functions are equally replaced. 

This function is a cancellation point in multi-threaded programs. This is a problem if the thread allocates some resources (like memory, file descriptors, semaphores or whatever) at the time open is called. If the thread gets canceled these resources stay allocated until the program ends. To avoid this calls to open should be protected using cancellation handlers. 

The open function is the underlying primitive for the fopen and freopen functions, that create streams. 

【有道机翻】

open函数为文件名命名的文件创建并返回一个新的文件描述符。最初,文件的文件位置指示器位于文件的开头。参数模式仅在创建文件时使用,但在任何情况下提供参数都没有坏处。

flags参数控制打开文件的方式。这是一个位掩模;您可以通过适当参数的位或(使用C语言中的|操作符)为可用参数创建值。

open的正常返回值是一个非负整数文件描述符。如果出现错误,则返回-1的值。除了常见的文件名错误外,这个函数还定义了以下errno错误条件:

EACCES文件存在,但是按照flags参数的要求是不可读/可写的,文件不存在,目录不可写,因此无法创建。

—EEXIST已设置O_CREAT和O_EXCL,且命名的文件已存在。

- EINTR开放操作被信号中断。

- EISDIR flags参数指定写访问权限,文件是一个目录。

- EMFILE进程打开的文件过多。文件描述符的最大数量由RLIMIT_NOFILE资源限制控制;。

- ENFILE整个系统,或者包含该目录的文件系统,目前不支持任何其他打开的文件。(这个问题不会发生在GNU系统上。)

—ENOENT指定的文件不存在,且未指定O_CREAT。

—ENOSPC磁盘空间已满,不能扩展将包含新文件的目录或文件系统。

- ENXIO O_NONBLOCK和O_WRONLY都设置在flags参数中,文件名命名的文件是FIFO,没有进程打开该文件供读取。

- EROFS该文件位于只读文件系统中,并且O_WRONLY、O_RDWR和O_TRUNC中的任意一个在flags参数中被设置,或者设置了O_CREAT,该文件不存在。

如果在32位机器上,源文件是用_FILE_OFFSET_BITS == 64进行转换的,那么open函数将返回一个以大文件模式打开的文件描述符,这使得文件处理函数可以使用2^63字节的文件,并且偏移量从-2^63到2^63。这对用户来说是透明的,因为所有的低级文件处理函数都被同等替换。

这个函数是多线程程序中的一个取消点。如果线程在调用open时分配了一些资源(如内存、文件描述符、信号量或其他),这就是一个问题。如果线程被取消,这些资源将一直分配到程序结束。为了避免这种情况,应该使用取消处理程序来保护打开调用。

open函数是创建流的fopen和freopen函数的基础原语。

O_APPEND

用途

        每次写操作执行前将标志位移至文件末尾

Macro Expansion

02000

用法

fd = open(fd_path, O_WRONLY | O_APPEND, fd_attrib);

lseek()

所需头文件

#include <unistd.h>

原型

off_t lseek (int filedes, off_t offset, int whence)

描述

The lseek function is used to change the file position of the file with descriptor filedes. 

The whence argument specifies how the offset should be interpreted, in the same way as for the fseek function, and it must be one of the symbolic constants SEEK_SET, SEEK_CUR, or SEEK_END. 


SEEK_SET      Specifies that whence is a count of characters from the beginning of the file. 

SEEK_CUR      Specifies that whence is a count of characters from the current file position. This count may be positive or negative. 


    - SEEK_END Specifies that whence is a count of characters from the end of the file. A negative count specifies a position within the current extent of the file; a positive count specifies a position past the current end. If you set the position past the current end, and actually write data, you will extend the file with zeros up to that position. 

The return value from lseek is normally the resulting file position, measured in bytes from the beginning of the file. You can use this feature together with SEEK_CUR to read the current file position. 

If you want to append to the file, setting the file position to the current end of file with SEEK_END is not sufficient. Another process may write more data after you seek but before you write, extending the file so the position you write onto clobbers their data. Instead, use the O_APPEND operating mode; . 

You can set the file position past the current end of the file. This does not by itself make the file longer; lseek never changes the file. But subsequent output at that position will extend the file. 
 Characters between the previous end of file and the new position are filled with zeros. Extending the file in this way can create a ``hole'': the blocks of zeros are not actually allocated on disk, so the file takes up less space than it appears to; it is then called a ``sparse file''. files in files 

If the file position cannot be changed, or the operation is in some way invalid, lseek returns a value of 
 -1. The following errno error conditions are defined for this function: 

    - EBADF The filedes is not a valid file descriptor. 


    - EINVAL The whence argument value is not valid, or the resulting file offset is not valid. A file offset is invalid. 


    - ESPIPE The filedes corresponds to an object that cannot be positioned, such as a pipe, FIFO or terminal device. (POSIX.1 specifies this error only for pipes and FIFOs, but in the GNU system, you always get ESPIPE if the object is not seekable.) 

When the source file is compiled with _FILE_OFFSET_BITS == 64 the lseek function is in fact lseek64 and the type off_t has 64 bits which makes it possible to handle files up to 2^63 bytes in length. 

This function is a cancellation point in multi-threaded programs. This is a problem if the thread allocates some resources (like memory, file descriptors, semaphores or whatever) at the time lseek is called. If the thread gets canceled these resources stay allocated until the program ends. To avoid this calls to lseek should be protected using cancellation handlers. 

The lseek function is the underlying primitive for the fseek, fseeko, ftell, ftello and rewind functions, which operate on streams instead of file descriptors. 

【有道机翻】

lseek函数用于使用描述符filedes改变文件的位置。

参数where指定如何解释偏移量,方法与fseek函数相同,并且它必须是符号常量SEEK_SET、SEEK_CUR或SEEK_END中的一个。

SEEK_SET指定从文件开头开始的字符数。

SEEK_CUR指定从当前文件位置开始的字符数。这个计数可以是正的,也可以是负的。

- SEEK_END从文件末尾开始的字符计数。负计数指定文件当前区段内的位置;正计数指定超过当前结束的位置。如果您将位置设置为超过当前结束的位置,并实际写入数据,则将文件扩展为0,直到该位置为止。

lseek的返回值通常是得到的文件位置,以字节为单位从文件开头测量。您可以使用这个特性和SEEK_CUR来读取当前文件的位置。

如果您想追加到文件,使用SEEK_END将文件位置设置到文件的当前末尾是不够的。另一个进程可能会在您查找之后写入更多的数据,但在您写入之前,扩展文件,以便您写入的位置clobbers他们的数据。相反,使用O_APPEND操作模式;。

您可以将文件位置设置在文件的当前末尾之后。这本身并不会使文件变长;Lseek永远不会更改文件。但是在该位置的后续输出将扩展该文件。

文件的前一个末尾和新位置之间的字符用零填充。以这种方式扩展文件会创建一个“洞”:0块实际上并没有分配到磁盘上,所以文件占用的空间比它看起来的要少;然后它被称为“稀疏文件”。文件在文件

如果不能更改文件位置,或者操作在某种程度上无效,lseek返回值为

1。为这个函数定义了以下errno错误条件:

- EBADF该文件不是一个有效的文件描述符。

- EINVAL从哪里来的参数值无效,或者产生的文件偏移量无效。文件偏移量无效。

- ESPIPE文件对应的是无法定位的对象,如管道、FIFO、终端设备等。(POSIX.1仅为管道和FIFOs指定了这个错误,但在GNU系统中,如果对象不可寻,你总是会得到ESPIPE。)

当用_FILE_OFFSET_BITS == 64编译源文件时,lseek函数实际上是lseek64, off_t类型有64位,这使得它可以处理长度为2^63字节的文件。

这个函数是多线程程序中的一个取消点。如果线程在调用lseek时分配了一些资源(如内存、文件描述符、信号量或其他),那么这就是一个问题。如果线程被取消,这些资源将一直分配到程序结束。为了避免这种情况,应该使用取消处理程序来保护对lseek的调用。

lseek函数是fseek、fseeko、ftell、ftello和rewind函数的基础原语,它们操作于流而不是文件描述符。

实现代码

/*
 * @author Jiang Pengdao
 * @version 26/3/2022
 */

#include <fcntl.h> /* For open(), O_APPEND */
#include <unistd.h> /* For close() */
#include <stdio.h> /* For puts() */
#include <stdlib.h> /* For exit() */

const int BUFFER_SIZE = 256; //the buffer size of the appender.

int main(int argc, char* argv[])
{
   int src_fd;                        //file descriptor for the source file
   int des_fd;                        //file descriptor for the destination file
   int read_count;                    //Bytes actually read each time
   mode_t f_attrib;                   //file permission
   unsigned char buffer[BUFFER_SIZE]; //Buffer holds the stream

   if(argc != 3) //Usage
       printf("Usage: %s <SOURCE FILE> <DESTINATION FILE>\n", argv[0]);

   const char *src_fd_path = argv[1];
   const char *des_fd_path = argv[2];
   src_fd = open(src_fd_path, O_RDONLY);                                //open the source file in read only mode
   f_attrib = S_IRWXU | S_IRWXG | S_IRWXO;                              //Set permission for the not exist destination file
   des_fd = open(des_fd_path, O_WRONLY | O_APPEND | O_CREAT, f_attrib); //open the destination file
   if (src_fd == -1) {                                                  //Check failure
      puts("Source file open failed.");
      close(src_fd);
      exit(1);
   }
   if (des_fd == -1) {                                                  //Check failure
      puts("Destination file open failed.");
      close(des_fd);
      exit(1);
   }

   while((read_count = read(src_fd, buffer, BUFFER_SIZE)) != 0) write(des_fd, buffer, read_count); //Append the file
   puts("Append complete.");

   close(src_fd); //close the file descriptor
   close(des_fd);
   return 0;
}

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值