在C中的文件中读写(加倍)

时间:2014-07-21 02:47:19

标签: c io binary

我正在尝试读取一个文件,读取它包含的字节数,然后将其四舍五入到最接近的GB,然后将文件大小加倍。但是,是否有办法读取文件,然后一些人将所有这些东西重新放回同一个文件中?

这是我到目前为止所做的,但它创建了一个包含新内容的新文件,但我不确定我的逻辑是否正确

另外,你是否使用#define创建一个类似BYTE的常量?

就测试用例而言,我只使用byte作为int并使其等于50

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

// #define BYTE 50

int main()
{
    FILE *fp1, *fp2;
    int ch1;
    clock_t elapsed;
    char fname1[40], fname2[40];
    char a;

    printf("Enter name of the file:");
    fgets(fname1, 40, stdin);
    while ( fname1[strlen(fname1) - 1] == '\n')
    {
        fname1[strlen(fname1) -1] = '\0';
    }

    fp1 = fopen(fname1, "r");
    if ( fp1 == NULL )
    {
        printf("Cannot open %s for reading\n", fname1 );
        exit(1);
    }

    printf("This program will round up the current file into highest GB, and then double it");

    elapsed = clock(); // get starting time

    ch1  =  getc(fp1); // read a value from each file

    int num = 50;

    int bytes = 0;

    while(1) // keep reading while values are equal or not equal; only end if it reaches the end of one of the files
    {
        ch1 = getc(fp1);

        bytes++;

        if (ch1 == EOF) // if either file reaches the end, then its over!
        {
            break; // if either value is EOF
        }
    }

    // 1,000,000,000 bytes in a GB 
    int nextInt = bytes%num;

    // example: 2.0GB 2,000,000,000 - 1.3GB 1,300,000,000 = 7,000,000,000 OR same thing as 2,000,000,000%1,300,000,000 = 700,000,000

    int counter = 0;

    printf("Enter name of the file you would like to create:");
    fgets(fname2, 40, stdin);
    while ( fname2[strlen(fname2) - 1] == '\n')
    {
        fname2[strlen(fname2) -1] = '\0';
    }

    fp2 = fopen(fname2, "w");
    if ( fp1 == NULL )
    {
        printf("Cannot open %s for reading\n", fname2);
        exit(1);
    }

    if(fp2 == NULL)
    {
     puts("Not able to open this file");
     fclose(fp1);
     exit(1);
    }

    while(counter != nextInt)
    {
     a = fgetc(fp1);
     fputc(a, fp2);
     counter++;
    }

    fclose(fp1); // close files
    fclose(fp2);

    printf("Total number of bytes in the file %u: ", bytes);
    printf("Round up the next GB %d: ", nextInt);

    elapsed = clock() - elapsed; // elapsed time
    printf("That took %.4f seconds\n", (float)elapsed/CLOCKS_PER_SEC);
    return 0;
}

2 个答案:

答案 0 :(得分:1)

你的工作方式太难了。我假设您的操作系统是Windows或Linux。

在Windows上,_stat将获得文件的确切长度。在Linux中它是stat。两者都将从文件系统信息中执行此操作,因此几乎是即时的。

在Windows上,_chsize会将文件扩展为任意数量的字节。在Linuxftruncate。操作系统会将零写入扩展名,因此它确实是一个快速写入。

在所有情况下,通过搜索找到文档很简单。

代码将是直线(无循环),大约10行。

只需使用

完成下一个GB
#define GIGA ((size_t)1 << 30)
size_t new_size = (old_size + GIGA - 1) & ~(GIGA - 1);

答案 1 :(得分:1)

在检查EOF之前,您需要增加bytes,这样就会出现一个错误。

但是,逐字节读取文件是查找其大小的缓慢方法。使用标准C,您可以使用ftell() - 如果您使用的是64位类Unix机器。否则,您的工作距离太接近适合32位值的值。对int使用普通bytes会遇到麻烦。

或者,更好的是,您stat()fstat()可以直接获得确切的尺寸。

当涉及到文件大小加倍时,您可以简单地寻找新的结束位置并在该位置写入一个字节。但是,这不会分配所有磁盘空间(在Unix机器上);它将是一个稀疏文件。

在重写时,您需要知道系统如何在单个文件上处理两个打开的文件流。在类Unix系统上,您可以打开原始文件一次进行读取,一次打开以追加模式进行写入。然后,您可以从读取文件描述符一次读取大块数据(64 KiB,256 KiB?)并将其写入写入描述符。但是,您需要跟踪要写入多少数据,因为读取不会遇到EOF。

您的代码将在大多数系统上将大量0xFF字节写入文件的尾部(其中EOF记录为-1)。

请注意,有Gibibytes GiB(2 30 = 1,073,741,824字节)和千兆字节GB(正式10 9 = 1,000,000,000字节,但很少用于表示GiB)。请参阅Binary prefix上的维基百科等。