UNIX/LINUX,Linux操作系統-標準IO庫(3)

 2023-12-09 阅读 37 评论 0

摘要:Linux操作系統—標準IO庫(3)(2015-8-5) 分類:Linux操作系統 二進制IO和定位流 ??二進制I/O也稱直接I/O,一個一個對象的I/O,面向記錄的I/O或面向結構的I/O。每次I/O操作讀取或寫一定數量的對象,而每個對象具有指定的長度。常用于二進制文件中讀或向

Linux操作系統—標準IO庫(3)(2015-8-5)

分類:Linux操作系統

二進制IO和定位流

??二進制I/O也稱直接I/O,一個一個對象的I/O,面向記錄的I/O或面向結構的I/O。每次I/O操作讀取或寫一定數量的對象,而每個對象具有指定的長度。常用于二進制文件中讀或向二進制文件中寫一個結構。

讀取二進制流

??使用fread函數可以進行二進制數據的讀取。

#include <stdio.h>
size_t fread(void *ptr, size_t size, size_t nitems, FILE *stream);

UNIX/LINUX,??函數fread的各參數和返回值的含義如下:
1. ptr:輸入緩存
2. size:數據塊的大小
3. nitems:數據塊的個數
4. stream:流文件指針
5. 返回值:返回實際讀取到的數據塊的個數。如果次數字小于nitems,則表示出錯或到達文件尾端,應調用ferror或feof以判斷究竟是哪一種情況

??這個函數參數有點多,還是找一個使用的例子來看看

nRead = fread(buf, sizeof(unsigned char), BUFFSIZE, fpIn);

??這一小段代碼的作用是:調用fread函數從源文件中讀取BUFFSIZE各字節。fpIn是源文件的流指針,BUFFSIZE是數據塊的個數,sizeof(unsigned char)是數據塊的大小,也即是一個字符的大小,buf是輸入的緩存,也即是fread讀取的數據存放的地方。fread返回的是實際讀取的字符數,該數值被記錄在了變量nRead中。
??實際讀取的數據塊的個數nRead如果小于預定的BUFFSIZE,則表示出錯或者到達文件尾端,應調用ferror或feof以判斷究竟是哪中情況。

寫二進制流

docker底層原理、??使用fwrite函數可以進行二進制數據塊的輸出。

#include <stdio.h>
size_t fwrite(const void *ptr, size_t size, size_t nitems, FILE *stream);

??函數fwrite的各參數和返回值的含義如下:
1. ptr:待輸出的數據的
2. size:數據塊的大小
3. nitems:數據塊的個數
4. stream:流文件的指針
5. 返回值:返回實際輸出的數據塊的個數,如果小于nitems,則表示出錯。

??總結這兩個函數(不嚴謹,但可以這樣區分兩者):
- fread:從stream流中讀取數據存入ptr中
- fwrite:從ptr總讀取數據存入stream中

二進制I/O的常見用法

  • 讀或寫一個二進制數組。例如:
float data[10]
...
if (fwrite(&data[2], sizeof(float), 4, fp) !=  4)printf("fwrite error.\n");

??這段代碼調用fwrite向文件流寫入data數組從第3個元素起的連續4個元素,每個數據塊的大小為一個元素(一個浮點數)的大小,如果寫入的元素個數不為4,則說明發生了錯誤。

  • 讀或寫一個結構。此時,指定size為結構體的大小,nitems指定為1。例如:
struct {short count;long total;char name[NAMESIZE];
}item;
...
if (fwrite(&item, sizeof(item), 1, fp) != 1)printf("fwrite error");

??這段代碼盜用fwrite向文件流寫入結構體變量item,數據塊為1,返回值如果不為1,則說明發生了錯誤。

  • 以上二者的結合。如:向一個結構體數組內寫數據。

二進制I/O實踐篇

目標:實現簡單的問價復制功能

#include <stdio.h>
#include <stdlib.h>
#define     BUFFSIZE    80  int main(int argc, char *argv[])
{FILE *fpIn, *fpOut;int nRead, nWrite;unsigned char buf[BUFFSIZE];if (argc != 3){         /* 如果從命令行傳遞過來的參數的個數不是3個 */                                          printf("Usage : %s <source_file> <destination_file>\n", argv[0]);return -1;}/* 如果要被復制的文件無法打開被讀取 */if ((fpIn = fopen(argv[1], "r")) == NULL){printf("Cannot open file [%s] for reading.\n", argv[1]);return -1;}/* 如果復制過來的新文件無法打開被寫入 */if ((fpOut = fopen(argv[2], "w")) == NULL){printf("Cannot open file [%s] for writing.\n", argv[2]);return -1;}/* 當要被復制的文件沒有到達文件尾時 */while (!feof(fpIn)){nRead = fread(buf, sizeof(unsigned char), BUFFSIZE, fpIn);if (nRead < BUFFSIZE){if (ferror(fpIn)){              /* 如果讀取出錯了 */printf("Copy failed.\n");break;}}if (nRead > 0){                     /* 進行復制操作 */nWrite = fwrite(buf, sizeof(unsigned char), nRead, fpOut);if (nWrite != nRead){           /* 如果復制出錯了 */printf("Copy failed.\n");break;}}}fclose(fpOut);                          /* 將文件關閉 */fclose(fpIn);return 0;
}

??編譯并運行

biantiao@lazybone1994-ThinkPad-E430:~/桌面$ gcc -o ioCopy ioCopy.c
biantiao@lazybone1994-ThinkPad-E430:~/桌面$ ./ioCopy
Usage : ./ioCopy <source_file> <destination_file>
biantiao@lazybone1994-ThinkPad-E430:~/桌面$ ./ioCopy a.txt b.txt
Cannot open file [a.txt] for reading.
biantiao@lazybone1994-ThinkPad-E430:~/桌面$ touch a.txt
biantiao@lazybone1994-ThinkPad-E430:~/桌面$ ./ioCopy a.txt b.txt
biantiao@lazybone1994-ThinkPad-E430:~/桌面$ ls
a.txt  b.txt  ioCopy  ioCopy.c
biantiao@lazybone1994-ThinkPad-E430:~/桌面$

??你可以發現參數argv[0]不是ioCopy而是./ioCopy,如果你不想在運行時加入./,就把ioCopy程序文件放入bin目錄下好了。

定位流

??可以調用fseek來定位流文件的讀寫指針。

#include <stdio.h>
int fseek(FILE *stream, long offset, int whence);

??函數fseek的各參數和返回值的含義如下:
1. stream:流文件的指針
2. offset:位移量
3. whence:指定位移量相對于何處開始。whence可以取如下三個常量

  • SEEK_SET:文件開始位置
  • SEEK_CUR:文件指針當前位置
  • SEEK_END:未見結束位置

4 返回值:成功返回0,失敗返回-1,錯誤記錄在errno

??一次成功的調用ftell()會清除流結束標志,并會撤銷已調用的ungetc()對流的影響。調用rewind()函數可以將一個流的讀寫指針設置到文件的起始位置。其原型如下:

#include <stdio.h>
void rewind(FILE *stream);

??該函數的唯一參數是已打開流的流文件指針。調用rewind(fp)基本等同于調用fseek(stream, 0L, SEEK_SET)。稍微不同的是,rewind函數將在讀寫指針設置到文件的起始位置時同時會將出錯指示errno清0
??調用ftell()函數可以獲得一個流的讀寫指針的當前位置。該函數的原型如下:

#include <stdio.h>
long ftell(FILE *stream);

??該函數返回讀寫指針當前相對于文件起始位置的位移量;若出錯,則返回-1,錯誤記錄在errno中。

版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。

原文链接:https://808629.com/195881.html

发表评论:

本站为非赢利网站,部分文章来源或改编自互联网及其他公众平台,主要目的在于分享信息,版权归原作者所有,内容仅供读者参考,如有侵权请联系我们删除!

Copyright © 2022 86后生记录生活 Inc. 保留所有权利。

底部版权信息