Linux: IO operation (fopen series and open series)

  • First, the understanding of IO basic interface
  • Two, the difference between fopen and open
          • 1. Call library
          • 2. Return data
          • 3. Header file
          • 4. Cache
  • 3. Usage of open series functions
          • 1. open
          • 2. write
          • 3. read
          • 4. lseek
          • 5. close
          • 6. Use cases
  • 4. Usage of fopen series functions
          • 1. fopen
          • 2. fwrite
          • 3. fread
          • 4. fseek
          • 5. fclose
          • 6. Use cases

1. Understanding of IO basic interface

In a project with a system, some scenarios of file operations are often encountered. Common interfaces include the c language standard library function fopen() series fopen, fwrite, fread, fclose, etc., as well as the UNIX system library open() series open, write, read, close, etc.

The following is an introduction to the differences and usage of these two series.

2. The difference between fopen and open

1. Call library

open series: It is a UNIX system call library and an interface provided to users to operate files
fopen series: It is a standard library function interface for reading files provided by the c language, and its implementation is also realized by calling the underlying open and read

2. Return data

open series: the return is an int type file description symbol, generally written as fd
fopen series: returns a FILE structure pointer, also known as “file handle”

3. Header file

open series: “#include ” etc. are required to use the open series functions, terminal command man 2 + function name such as (man 2 open) query description
fopen series: “#include ” is required to use the fopen series of functions, terminal command man 3 + function name such as (man 3 fopen) query description

4. Cache

Open series: According to the data, the functions of the open series are cached when operating hard disk data. Unlike the fopen series of functions, they are cached in the kernel, so the cache space is relatively limited.
fopen series: The fopen series functions are called by the user from the layer, so its data is cached in the user layer, and the cache space is also defined by the user according to the demand.

Therefore, in general, the portability of the fopen series of functions is stronger. For moving data from one disk to another, it is better to use the open series of functions, because it can avoid entering the user space, and directly operate the kernel at the bottom layer, which is more efficient; For the case that the file needs to enter the user program, fread can access the cpu less times, then use the fopen series of functions to improve efficiency.

3. Open series function usage

1, open
int open(const char* pathname, int flags, mode_t mode);

1. const char* pathname: file path
2. int flags: file opening method
 required:         
- O_RDONLY---->read-only open
- O_WRONLY----> Open for writing only
 - O_RDWR---->open for reading and writing
Options:
- O_CREAT: If the file does not exist, create it
 - O_TRUNC: Truncated file-discard original data
- O_APPEND: Append write
3. mode_t mode: file permissions such as 0777, note that 0 cannot be omitted
4. Return value: If successful, return a file descriptor (non-negative integer) as a file operation handle, and return -1 if failed
2, write
#include <unistd.h>
       ssize_t write(int fd, const void *buf, size_t count);
       
1. When fd: open opens a file, the returned file descriptor
2. buf: the first address of the data space to be written into the file (write the content pointed to by buf into the file)
3. count: the number of bytes written to the file
4. Return value: Returns the number of bytes written to the file successfully, returns -1 on failure
3, read
#include <unistd.h>
       ssize_t read(int fd, void *buf, size_t count);
       
1. When fd: open opens a file, the returned file descriptor
2. buf: the first address of a space, used to store the data read from the file
3. count: the number of bytes read
4. Return value: Returns the number of bytes read if successful, returns -1 if failed
4, lseek
#include <sys/types.h>
#include <unistd.h>
       off_t lseek(int fd, off_t offset, int whence);
       
1. When fd: open opens a file, the returned file descriptor
2. offset: offset
3. whence: based on what position to start the offset
SEEK_SET: offset relative to the beginning of the file
SEEK_CUR: offset relative to the current position of the file
SEEK_END: offset relative to the end of the file
4. Return value: Returns the number of bytes read if successful, returns -1 if failed
5, close
#include <unistd.h>
       int close(int fd);
       
1. When fd: open opens a file, the returned file descriptor
2. Return value: 0 means success - 1 means failure
6. Use case
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>

int main() {<!-- -->
  /*open a file*/
  int fd = open("./my.ini", O_CREAT | O_RDWR, 0777);
  if (fd < 0) {<!-- -->
    printf("open file fail!\
");
  }

  // lseek(fd, 6, SEEK_SET);
  /*write file*/
  char* data = "hello world!";
  ssize_t back = write(fd, data, strlen(data));
  if (back < 0) {<!-- -->
    printf("write file fail!\
");
  }

  /* change cursor offset */
  lseek(fd, 1, SEEK_SET);

  /*read file*/
  char buf[100] = {<!-- -->0};
  ssize_t re = read(fd, buf, strlen(data) + 6);
  if (re < 0) {<!-- -->
    printf("write file fail!\
");
  } else {<!-- -->
    printf("read data : %s\
", buf);
  }

  /*closure*/
  if (close(fd) == 0) {<!-- -->
    printf("close fail! \
");
  }

  return 0;
}

4. Usage of fopen series functions

1. fopen
 #include <stdio.h>
       FILE *fopen(const char *pathname, const char *mode);
       
1. pathname: file path.
2. mode: Indicates the access mode of the file.
"r" opens a file for reading. The file must exist.
"w" creates an empty file for writing. If the file name is the same as an existing file, the contents of the existing file are deleted and the file is treated as a new empty file.
"a" appends to a file. Write operations append data to the end of the file. If the file does not exist, the file is created.
"r + " opens a file for updating, both for reading and writing. The file must exist. .
"w + " creates an empty file for reading and writing.
"a + " opens a file for reading and appending.
3. Return value: return a FILE pointer successfully. NULL is returned on failure, and the global variable errno is set to identify the error.
2, fwrite
#include <stdio.h>
       size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);

1. ptr: Pointer to the array of elements to be written.
2. size: The size of each element to be written, in bytes.
3. nmemb: the number of elements, the size of each element is size bytes.
4. stream: A pointer to a FILE object that specifies an output stream.
5. Return value: a nmemb is returned if successful, and -1 is returned if failed.
3, fread
 #include <stdio.h>
       size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);


1. ptr: A pointer to a memory block with a minimum size of size*nmemb bytes, used to store the read data.
2. size: The size of each element to be read, in bytes.
3. nmemb: the number of elements, the size of each element is size bytes.
4. stream: A pointer to a FILE object that specifies an output stream.
5. Return value: a nmemb is returned if successful, and -1 is returned if failed.
4, fseek
 #include <stdio.h>
       int fseek(FILE *stream, long offset, int whence);
1. stream: A pointer to a FILE object that specifies an output stream.
2. offset: offset, that is, the position of the cursor.
3. whence: where to start the offset.
SEEK_SET: offset relative to the beginning of the file
SEEK_CUR: offset relative to the current position of the file
SEEK_END: offset relative to the end of the file
4. Return value: return 0 for success, and -1 for failure.
5, fclose
#include <stdio.h>
       int fclose(FILE *stream);
1. stream: A pointer to a FILE object that specifies an output stream.
2. Return value: return 0 for success, and -1 for failure.
6. Use case
#include <stdio.h>
#include <string.h>

int main() {<!-- -->
  /*open a file*/
  FILE* fd = fopen("./my.ini", "r + ");
  if (fd == NULL) {<!-- -->
    printf("open file fail!\
");
  }

  /*write file*/
  char* data = "hello world!";
  ssize_t back = fwrite(data, strlen(data), 2, fd);
  printf("back = %ld\
", back);

  if (back < 0) {<!-- -->
    printf("write file fail!\
");
  }

  /* change cursor offset */
  fseek(fd, 0, SEEK_SET);

  /*read file*/
  char buf[100] = {<!-- -->0};
  ssize_t re = fread(buf, strlen(data), 1, fd);
  if (re < 0) {<!-- -->
    printf("write file fail!\
");
  } else {<!-- -->
    printf("read data : %s\
", buf);
  }
 /*closure*/
  if (fclose(fd) == 0) {<!-- -->
    printf("close fail! \
");
  }

  return 0;
}