Reading and writing 64bits by 64 bits in C
Asked Answered
P

1

0

I have this super simple code where I read blocks of 8 bytes (I will encrypt them later in the code) and then write them down in a new file.

It works well but for the last 8 bytes which don't get written. Any idea why?

#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>

int main()
{
    uint64_t data;
    FILE *input, *output;

    // create output file

    output = fopen("output.txt", "w");

    // read file
    input = fopen("test.txt", "rb");

    if(input)
    {
        while(fread(&data, 8, 1, input) == 1)
        {
            fwrite(&data, 8, 1, output);
        }

        size_t amount;
        while((amount = fread(&data, 1, 8, input)) > 0)
        {
         fwrite(&data, 1, amount, output);
        }

        fclose(input);
        fclose(output);
    }

    return EXIT_SUCCESS;
}
Piscatelli answered 8/2, 2014 at 15:19 Comment(6)
Is it a text file? The name test.txt suggests that. Perhaps there are newlines that you are not counting, and the input file is not a multiple of 8 bytes in size. Also, you should not assume CHAR_BIT == 8 or sizeof(uint64_t) == 8Unconscious
yes it is a simple text file with some lines. It is not a multiple of 8 bytes in size, should it be? I might be missing something here. And how could sizeof(uint64_t) be different from 8?Twum
If you are working on a machine with 64 bit chars, sizeof(uint64_t) could be 1. If the size of your input file is not a multiple of 8, then your loop will be entered one time too little, since fread returns 0 when there are not enough data left to fulfill the requested size.Unconscious
I see! But I really need to read only 64bits at a time, so I guess my code is correct here to do that right?Twum
@WilliamPursell, sizeof(uint64_t) would be 1 if the machine has 64-bit characters. That is quite a stretch of the imagination (Crays used to have all types 32 bits for performance, but that is the weirdest I've seen).Jilly
Just a note: The POSIX specification requires that CHAR_BIT == 8, see pubs.opengroup.org/onlinepubs/009695399/basedefs/limits.h.html.Berneta
B
2
fread(&data, 8, 1, input)

tries to read one "item" with 8 bytes into the buffer, and returns the number of items. If less than 8 bytes are left from the current position to EOF, it returns 0.

One possible solution would be to read 8 items à 1 byte instead:

ssize_t amount;
while ((amount = fread(&data, 1, 8, input)) > 0)
{
    fwrite(&data, 1, amount, output);
}

Inside the while-block you can then check if amount is 8 or less, for your encryption method.

Berneta answered 8/2, 2014 at 15:45 Comment(4)
I thought about this, BUT, what if there is less than a byte for the last bits? Is it possible to have a file with only 7 bits for example?Twum
@David天宇Wong: That is not possible. A file is a collection of bytes.Berneta
Thanks a lot for this! Also what about adding the code you provided after the while I did? I tried and it didn't work, isn't the input pointer supposed to have gone back to the last place it could read?Twum
@David天宇Wong: I have to correct myself. The last read of your first loop actually consumes the bytes, therefore the second loop does not read anything. So you should use only the second loop.Berneta

© 2022 - 2024 — McMap. All rights reserved.