我正在尝试读取一个文件,读取它包含的字节数,然后将其四舍五入到最接近的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;
}
答案 0 :(得分:1)
你的工作方式太难了。我假设您的操作系统是Windows或Linux。
在Windows上,_stat
将获得文件的确切长度。在Linux中它是stat
。两者都将从文件系统信息中执行此操作,因此几乎是即时的。
在Windows上,_chsize
会将文件扩展为任意数量的字节。在Linux
上ftruncate
。操作系统会将零写入扩展名,因此它确实是一个快速写入。
在所有情况下,通过搜索找到文档很简单。
代码将是直线(无循环),大约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上的维基百科等。