Binary I/O, positioning stream, formatted I/O, memory stream

Dongyang's study notes

1. Binary I/O

If performing binary I/O operations, then we prefer to read or write a complete structure at a time.

  • If you use getc or putc to read and write a structure, you must loop through the entire structure, processing one byte at a time, and reading or writing one byte at a time.这太麻烦了
  • If you use fgets and fputs, then because fputs stops when it encounters a null byte,而在结构中可能含有 null 字节
#include <stdio.h>

size_t fread(void *restrict ptr, size_t size, size_t nobj, FILE *restrict fp);

size_t fwrite(const void *restrict ptr, size_t size size_t nobj, FILE *restrict fp);

1.1 Function usage

  1. Read or write a binary array:
float data[10];

if (write(&data[2], sizeof(float), 4, fp) != 4)

    err_sys(“fwrite error");
  1. Read or write a structure
struct {
    
    

    short  count;

    long   total;

    char   name[NAMESIZE];

} item;

if (fwrite(&item, sizeof(item), 1, fp) != 1)

    err_sys(“fwrite error");

fread and fwrite return the number of objects read or written.

1.2 Basic problems in use

It can only be used to read data that has been written on the same system. It is often the case that data written on one system needs to be processed on another system. In this case, these two functions may not work properly. The reason is that:

  1. In a structure, the offset of the same member may vary with the compiler system
  2. The binary format used to store multi-byte integers and floating-point values ​​may vary from system to system

Two, positioning flow

There are three ways to locate the standard I/O stream.

  1. ftell and fssek functions. These two functions have existed since v7, but they both assume that the location of the file can be stored in a long integer.
  2. The ftello and fseekpos functions make it unnecessary to use long integers for file offsets. They use off_t data types instead of long integers.
  3. The fgetpos and fsetpos functions, these two functions were introduced by IOS C. They use an abstract data type fpos_t to record the position of the file. This data type can be defined as a large enough number as needed to record the file location.

需要移植到非 UNIX 系统上运行的应用程序应当使用 fgetpos 和 fsetpos

#include <stdio.h>

long ftell(FILE* fp);    // Returns:current file position indicator if OK, -1L on error

int fseek(FILE* fp, long offset, int whence);       // Returns:0 if OK , -1 on error

void rewind(FILE* fp);

The rewind function can set a stream to the beginning of the file.

  1. The offset of the binary file is the number of bytes from the beginning of the file to the current position;
  2. The ftell function returns the offset position of the current file;
  3. The fseek function is used to locate the file to the specified offset position;
  4. The parameter whoce of the fseek function is used to set the method of calculating the offset: SEEK_SET means that the calculation starts from the beginning of the file,
  5. SEEK_CUR means starting from the current offset position of the file, SEEK_END means starting from the end of the file.
  6. For some non-Unix operating systems, the storage format for storing text files will be different. The current file offset cannot be expressed by the number of bytes. In this case, the parameter whyce needs to be set to SEEK_SET, and there are only two values ​​for offset. Use: 0 means rewind to the beginning of the text; another available value is the return value of the function ftell.
#include <stdio.h>

off_t ftello(FILE* fp);     // Returns: current file position indicator if OK, (off_t) -1 on error

int fseeko(FILE* fp, off_t offset, int whence);     /// Returns: 0 if OK, -1 on error

Except that the type of the offset is off_t instead of long, the ftello function is the same as ftell, and the fseeko function is the same as fseek

#include <stdio.h>

int fgetpos(FILE* restrict fp, fpos_t *restrict pos);

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

ffetpos stores the current value of the file position indicator into the object pointed to by pos. You can use this value to reposition the stream to that position when you call fsetpos later.

Three, format IO

#include <stdio.h>

int scanf(const char *restrict format, ...);

int fscanf(FILE *restrict fp, const char *restrict format, ...);

int sscanf(const char *restrict buf, const char *restrict format, ...);

Function details:

  • The format parameter is followed by the parameter, which contains the address of the variable that stores the read string.
  • Other: slightly

Fourth, implementation details

#include <stdio.h>
int fileno(FILE* fp);    // 返回与该流相关联的文件描述符

If we need to call dup and fcntl, we need to call this function.

5. Temporary Files

The standard IO library provides two functions for creating temporary files.

#include <stdio.h>

char* tempnam(char *ptr);
FILE* tmpfile(void);

Function details:

  • The function tmpnam generates a string that is a valid path name and does not repeat any existing files.
  • The function tmpnam generates a different string every time it is called, knowing the number of TMP_MAX.
  • If the parameter ptr of the function tempnam is NULL, the generated path string is stored in the static memory area, and the function return value is a pointer to the path string. If you subsequently call tempnam again with a null parameter, it will overwrite the previously generated string.
  • If the parameter ptr of the function tempnam is not NULL, the generated path string is stored in the array pointed to by ptr, so it is necessary to ensure that the length of the array pointed to by ptr is at least L_tmpnam.
  • The function tmpfile function creates a temporary binary file (type wb+), the file is automatically deleted when the program terminates or the file is closed. For the UNIX operating system, generating a binary file has no effect, because the kernel does not distinguish between a text file and a binary file.
\#include "apue.h"

int main(void)

{
    
    

  char  name[L_tmpnam], line[MAXLINE];
  FILE  *fp;
  printf("%s\n", tmpnam(NULL));    /* first temp name */
  tmpnam(name);            /* second temp name */
  printf("%s\n", name);
  if ((fp = tmpfile()) == NULL)    /* create temp file */err_sys("tmpfile error");
  fputs("one line of output\n", fp); /* write to temp file */
  rewind(fp);             /* then read it back */
  if (fgets(line, sizeof(line), fp) == NULL)err_sys("fgets error");
  fputs(line, stdout);        /* print the line we wrote */
  exit(0);
}

In the system The Single UNIX Specification defines two other functions to handle temporary files:

char* mkdtemp(char* template);   // Returns: pointer to directory name if OK, NULL on error

int mkstemp(char* template);   // Returns: file descriptor if OK, -1 on error

Function details:

  • The mkdtemp function creates a folder with a unique name
  • The mkstemp function creates a regular file with a unique name (regular file)
  • The naming rule is template + six random characters

Six, memory flow

Some standard input and output streams do not correspond to open hard disk files. All operations are done by transferring bytes back and forth between the buffer and main memory. These streams are called memory streams.

Guess you like

Origin blog.csdn.net/qq_22473333/article/details/114382639