简体   繁体   中英

Read bytes from file and store in array - C

I'm trying to read all bytes from a .raw file and store it in an array, using fread. This is my code:

//open up card file    
FILE* file = fopen("card.raw", "r");

if (file == NULL)
{
    printf("Unable to open/create file\n");
    return 1;
}

//size of file
fseek(file, 0, SEEK_END);
int size = ftell(file);
fseek(file, 0, SEEK_SET);

//buffer array
int buffer[size];

fread(&buffer, 512, size/512, file);

return(0);

I want to read 512 bytes at a time and everything in the file. Now my code gives me Segmanetation Fault , why is this? I guess it has to do with memeory leak or something similar but I can't figure it out. I also tried to change the mode of the file file to w but then all file contents disappear. What am I doing wrong?

So there are a few issues with your code:

  1. size and int buffer[size] : size is the number of bytes in the file, so creating an integer array of size size will actually use size * 4 bytes. You mention in the comments that your file is 14.3MB so the buffer array will be 57.2 MB. If you actually want to read 4 byte integers, then you need to adjust the size of your buffer array accordingly (divide by 4 and account for remainder - more on this later).
  2. Stack size: The stack is limited on most systems. If you are writing/running this on Linux, try typing ulimit -s at the command line to see the maximum number of kilobytes on the stack. On my machine this is 8 MB and trying to fread into a larger array causes a segfault. If you want to read this entire file in to memory, you will need to use the heap ( malloc / free ).
  3. size/512 : Integer division throws away the remainder, so this calculation is wrong.
  4. Typos/Other: You don't want to pass the address of buffer (you are using &buffer ) you want to pass the address of the first element of buffer which conveniently can be done by just using buffer (or &buffer[0] but you rarely see this in reality).

Here is a "working" version of your program:

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

#define BYTES_PER_READ 512

int main(int argc, char *argv[])
{   
    long size;
    size_t number_of_ints;
    size_t number_of_elements;
    size_t read;
    int *buffer;

    /* Open up card file */
    FILE *file = fopen("card.raw", "r");

    if (!file) {
        fprintf(stderr, "Unable to open/create file\n");
        return 1;
    }

    /* Size of file */
    fseek(file, 0, SEEK_END);
    size = ftell(file);
    fseek(file, 0, SEEK_SET);

    /* 'size' is the number of bytes, not the number of ints,
       so we need to adjust accordingly */
    number_of_ints = (size % sizeof(int) ? 1 : 0) + (size / sizeof(int));

    /* We want to read 512 bytes at a time, and we need to know
       how many we need to read to consume the whole file
       (this is identical to the calculation above) */
    number_of_elements = (size % BYTES_PER_READ ? 1 : 0) +
        (size / BYTES_PER_READ);

    if (!(buffer = malloc(number_of_ints * sizeof(int)))) {
        fprintf(stderr, "Failed to allocate memory\n");
        return 1;
    }

    read = fread(buffer, BYTES_PER_READ, number_of_elements, file);

    printf("I read %zu elements of size %d bytes (total bytes read: %zu)\n",
        read, BYTES_PER_READ, read * BYTES_PER_READ);

    free(buffer);

    return 0;
}

If you could describe what your intend to do with the contents of the buffer array, someone could potentially tell you a better way to go about it (the way you are reading right now is a bit odd...)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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