??二進制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中
float data[10]
...
if (fwrite(&data[2], sizeof(float), 4, fp) != 4)printf("fwrite error.\n");
??這段代碼調用fwrite向文件流寫入data數組從第3個元素起的連續4個元素,每個數據塊的大小為一個元素(一個浮點數)的大小,如果寫入的元素個數不為4,則說明發生了錯誤。
struct {short count;long total;char name[NAMESIZE];
}item;
...
if (fwrite(&item, sizeof(item), 1, fp) != 1)printf("fwrite error");
??這段代碼盜用fwrite向文件流寫入結構體變量item,數據塊為1,返回值如果不為1,則說明發生了錯誤。
目標:實現簡單的問價復制功能
#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可以取如下三個常量
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中。
版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。
工作时间:8:00-18:00
客服电话
电子邮件
admin@qq.com
扫码二维码
获取最新动态