1. 程式人生 > >C語言 檔案大小,分配空間,讀入檔案,寫入檔案,實現複製的功能

C語言 檔案大小,分配空間,讀入檔案,寫入檔案,實現複製的功能

首先通過兩種方法得到檔案的大小,位元組為單位,根據這個大小使用malloc分配固定的空間buffer,二進位制流讀入檔案,把二進位制流寫入buffer中,buffer輸出寫入到新的檔案。
原始檔1.txt,輸出檔案1.txt.txt
環境為Ubuntu 16.04,gcc

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <sys/stat.h>
//get file size
int file_size(char *filename)
{
    struct
stat statbuf; stat(filename, &statbuf); int size = statbuf.st_size; printf("the size of file %s is : %d byte\n", filename, size); return size; } long file_size2(FILE *file) { /* 獲取檔案大小 */ fseek (file, 0, SEEK_END); long lSize; lSize = ftell (file); rewind (file)
;//point back to the begin printf("the size of file is : %ld byte\n", lSize); return lSize; } //inputName: 1.txt -> outputName:1.txt.txt void initOutname(char *filename) { int nameLen = strlen(filename), suffixLen = 0; char *first = strrchr(filename, '.'); if (first == NULL) return
; strcat(filename, first); } int main(int argc, char *argv[]) { char *buffer = NULL; char filename[100]; if(argc == 1){ strcpy(filename, "1.txt"); }else if(argc == 2){ strcpy(filename, argv[1]); }else { printf("parameter ERROR!\n"); return -1; } int len = file_size(filename); FILE *file = fopen(filename, "rb"); if (!file) { printf("%s: can not open %s\n", __func__, filename); return -1; } long llen = file_size2(file); //len bytes buffer = malloc(llen); // printf("%ld\n", sizeof(char)); if(NULL != buffer) { printf("success\n"); } else { printf("the file is too large to load!\n"); return -1; } /* 將檔案拷貝到buffer中 */ size_t result = fread (buffer, 1, llen, file); if (result != llen) { printf("fread ERROR\n"); return -1; } printf("%ld\n", result); printf("%s\n", buffer); initOutname(filename); FILE *fileOut = fopen(filename, "w+"); if (!fileOut) { printf("%s: can not open %s\n", __func__, filename); return -1; } result = fwrite(buffer, 1, llen, fileOut); if (result != llen) { printf("%s: can not write %s\n", __func__, filename); return -1; } fclose (fileOut); fclose (file); free(buffer); return 0; }

在測試大檔案(5G)大小時候,第一種方法測出只有1G,第二種方法比較準確,原因還未知,讀者知道的麻煩告訴下~

[email protected]:/workfile$ ./test /media/sf_share/16.04.vdi
the size of file /media/sf_share/16.04.vdi is : 1075838976 byte
the size of file is : 5370806272 byte
success

第一種方法是一次性申請讀入檔案大小的記憶體空間buffer,一次性寫入buffer,再輸出到檔案中,但檔案特別大時候,malloc時候就失敗了,解決方法是申請固定size大小的buffer,得到檔案的大小len,每次寫入size位元組的內容,更新len為len-size,剛開始判斷len<size,如果是的話則寫入len大小。最終退出迴圈時,len減為0
在這裡插入圖片描述
更新後的程式碼使用第二種檔案大小得到方法,程式碼如下:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAXSIZE 32768

#include <sys/stat.h>

//inputName: 1.txt  -> outputName:1.txt.txt
void initOutname(char *filename)
{
    int nameLen = strlen(filename), suffixLen = 0;
    char *first = strrchr(filename, '.');
    if (first == NULL) return ;
    strcat(filename, first);
}

long file_size2(FILE *file)
{
    /* 獲取檔案大小 */
    fseek (file, 0, SEEK_END);
    long lSize;
    lSize = ftell (file);
    rewind (file);//point back to the begin
    printf("the size of file is : %ld byte\n",  lSize);
    return lSize;
}

int main(int argc, char *argv[])
{
    char *buffer = NULL;
    char filename[100];
    if(argc == 1)
    {
        strcpy(filename, "1.txt");
    }
    else if(argc == 2)
    {
        strcpy(filename, argv[1]);
    }
    else
    {
        printf("parameter ERROR!\n");
        return -1;
    }

    FILE *file = fopen(filename, "rb");
    if (!file)
    {
        printf("%s: can not open %s\n", __func__, filename);
        return -1;
    }

    initOutname(filename);
    FILE *fileOut = fopen(filename, "w");
    fclose (fileOut);
    fileOut = fopen(filename, "a+");
    if (!fileOut)
    {
        printf("%s: can not open %s\n", __func__, filename);
        return -1;
    }

    buffer = malloc(MAXSIZE);
    if(NULL != buffer)
    {
        printf("success\n");
    }
    else
    {
        printf("%s the file is too large to load!\n", __func__);
        return -1;
    }
    /* 將檔案拷貝到buffer中 */
    int bytes_read = 0;
    int onceSize = MAXSIZE;
    int len = file_size2(file);
    for(; len > 0; len -= onceSize)
    {
        if(len < MAXSIZE) onceSize = len;

        fread (buffer, 1, onceSize, file);
        fwrite(buffer, 1, onceSize, fileOut);
    }

    fclose (fileOut);
    fclose (file);
    free(buffer);
    return 0;
}

其中開啟輸出檔案方式先使用w目的是新建並清空之前的檔案內容,再用二進位制追加a+的方式開啟。
判斷生成的檔案和原始檔的sha224的值:

[email protected]:/workfile/SHA$ ./sha sha224 ../1.txt
File('../1.txt'): a069a467f410fae0559382f1e45ec9a850e1e26472eac466588291c7
[email protected]:/workfile/SHA$ ./sha sha224 ../1.txt.txt
File('../1.txt.txt'): a069a467f410fae0559382f1e45ec9a850e1e26472eac466588291c7

其中讀入再寫入有一種簡單的寫法,思想和圖片一樣。讀入了byte_read位元組,那麼就寫入byte_read位元組到檔案中。

    // int onceSize = MAXSIZE;
    // int len = file_size2(file);
    // for(; len > 0; len -= onceSize)
    // {
    //     if(len < MAXSIZE) onceSize = len;

    //     fread (buffer, 1, onceSize, file);
    //     fwrite(buffer, 1, onceSize, fileOut);
    // }

    while(bytes_read=fread (buffer, 1, MAXSIZE, file))
    	fwrite(buffer, 1, bytes_read, fileOut);