简体   繁体   English

在C中读取和写入文件(将其加倍)

[英]Read and Write within a file in C (double it)

I am trying to read a file, read in how many bytes it contains and then round it up to its nearest GB and then double the file size. 我正在尝试读取文件,读取文件包含多少个字节,然后将其舍入到最接近的GB,然后将文件大小加倍。 However, is there is way to read the file and then some do all this stuff back into the same file? 但是,有没有办法读取文件,然后将所有这些东西都放回到同一文件中?

Here is what I have so far, but it creates a new file with the new contents but I'm not sure if my logic is correct 这是我到目前为止的内容,但是它使用新内容创建了一个新文件,但是我不确定我的逻辑是否正确

Also, do you create a constant like BYTE with #define? 另外,您是否使用#define创建像BYTE这样的常量?

So far as a test case I just used byte as an int and make it equal to 50 就测试用例而言,我只是将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;
}

You're working way too hard. 你工作太辛苦了。 I'll assume your OS is Windows or Linux. 我假设您的操作系统是Windows或Linux。

On Windows, _stat will get the exact length of a file. 在Windows上, _stat将获取文件的确切长度。 In Linux it's stat . 在Linux中,它是stat Both will do this from file system information, so it's almost instantaneous. 两者都会从文件系统信息中执行此操作,因此几乎是瞬时的。

On Windows, _chsize will extend the file to any number of bytes. 在Windows上, _chsize会将文件扩展到任意数量的字节。 On Linux it's ftruncate . Linux它是ftruncate The OS will be writing zeros to the extension, so it will be a fast write indeed. 操作系统将向扩展写入零,因此确实是一种快速写入。

In all cases it's simple to find the documentation by searching. 在所有情况下,都可以通过搜索找到文档。

The code will be straight-line (no loops), about 10 lines. 该代码将是直线(无循环),大约10行。

Rounding up to the next GB is simply done with 舍入到下一个GB只需完成

#define GIGA ((size_t)1 << 30)
size_t new_size = (old_size + GIGA - 1) & ~(GIGA - 1);

You increment bytes before you check for EOF, so you have an off-by-one error. 在检查EOF之前要增加bytes ,因此会出现一个一一错误。

However, reading a file byte by byte is a slow way of finding its size. 但是,逐字节读取文件是查找文件大小的缓慢方法。 Using standard C, you may be able to use ftell() — if you're on a 64-bit Unix-like machine. 使用标准C,您可能可以使用ftell() -如果您使用的是类似64位Unix的计算机。 Otherwise, you're working too close to the values that will fit in 32-bit values. 否则,您的工作就太接近了32位值所适合的值。 Using a plain int for bytes is going to run into trouble. bytes使用普通的int会遇到麻烦。

Alternatively, and better, you stat() or fstat() to get the exact size directly. 另外,更好的是,您可以使用stat()fstat()直接获取确切大小。

When it comes to doubling the size of the file, you could simply seek to the new end position and write a byte at that position. 如果要将文件大小增加一倍,则只需查找新的结束位置,然后在该位置写入一个字节即可。 However, that does not allocate all the disk space (on a Unix machine); 但是,这并不能分配所有磁盘空间(在Unix机器上)。 it will be a sparse file. 这将是一个稀疏文件。

On rewrite, you need to know how your system will handle two open file streams on a single file. 重写时,您需要知道系统如何处理单个文件上的两个打开的文件流。 On Unix-like systems, you can open the original file once for reading and once for writing in append mode. 在类似Unix的系统上,您可以在追加模式下打开一次原始文件以进行读取,并一次写入。 You could then read large chunks (64 KiB, 256 KiB?) of data at a time from the read file descriptor and write that to the write descriptor. 然后,您可以一次从读取文件描述符读取大块数据(64 KiB,256 KiB?),然后将其写入写入描述符。 However, you need to keep track of how much data to write because the read won't encounter EOF. 但是,您需要跟踪要写入多少数据,因为读取不会遇到EOF。

Your code is going to write a lot of 0xFF bytes to the tail of the file on most systems (where EOF is recorded as -1). 在大多数系统(EOF记录为-1)上,您的代码将向文件的尾部写入很多0xFF字节。

Note that there are Gibibytes GiB (2 30 = 1,073,741,824 bytes) and Gigabytes GB (officially 10 9 = 1,000,000,000 bytes, but not infrequently used to mean GiB). 请注意,有千兆字节的GiB(2 30 = 1,073,741,824字节)和千兆字节的GB(正式为10 9 = 1,000,000,000字节,但很少用于表示GiB)。 See Wikipedia on Binary prefix , etc. 参见Wikipedia上的Binary前缀等。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM