0

Here is a little code I wrote. Please note -

  1. The file that is being pointed to by rawbytes > 512 bytes
  2. Do I open the file being read from in "r" or "rb"? I don't know what is in it apart from a couple of JPEGs.
  3. Why does my fread always output 0, even when I make it fread(bytes, 1, 512, rawbytes)?

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

int main(int argc, string argv[])
{
    // Declaring a new type 
    typedef uint8_t BYTE;
    
    // Declaring an array of bytes, in which I want to read 512 bytes
    BYTE bytes[512];
    
    FILE *rawbytes = fopen(argv[1], "rb");
    int numberofbytesread = fread(bytes, 1, 512, rawbytes);
    
    // Check
    printf("%i\n", numberofbytesread);
    fclose(rawbytes);
}

Edit 1: Changed int data type to size_t data type. New code:

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

int main(int argc, string argv[])
{
    // Declaring a new type 
    typedef uint8_t BYTE;

    // Declaring an array of bytes, in which I want to read 512 bytes
    BYTE bytes[512];

    FILE *rawbytes = fopen(argv[1], "rb");
    size_t numberofbytesread = fread(bytes, 1, 512, rawbytes);

    // Check
    printf("%zu\n", numberofbytesread);
    fclose(rawbytes);
}

I don't know what %zu is, but the compiler told me to swap %i with %zu. Still getting 0 bytes read. :(

Edit 2: To make the problem reproducible, I have replaced argv[1] with the memory card file that I'm tasked to 'recover' JPEG files from called card.raw. This code is just a small code I wrote to check whether I'm able to read at least 512 bytes from card.raw

Execute wget https://cdn.cs50.net/2019/fall/psets/4/recover/recover.zip to download a (compressed) ZIP file with this problem’s distribution. Execute unzip recover.zip to uncompress that file.

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

int main(int argc, string argv[])
{
    // Declaring a new type 
    typedef uint8_t BYTE;

    // Declaring an array of bytes, in which I want to read 512 bytes
    BYTE bytes[512];

    FILE *rawbytes = fopen("card.raw", "rb");
    if (rawbytes == NULL)
    {
           return 1;
    }

    size_t numberofbytesread = fread(bytes, 1, 512, rawbytes);

    // Check
    printf("%zu\n", numberofbytesread);
    fclose(rawbytes);
}
Nate Eldredge
  • 48,811
  • 6
  • 54
  • 82
  • 2
    Has your file been opened successfully? Is `rawbytes != NULL`? -- As for `r` vs. `rb`, the former is for text (and text only), the latter for any kind of binary (including JPG). -- Nitpick: Return value of `fread` is `size_t`, not `int`. – DevSolar Sep 01 '20 at 06:39
  • 4
    Always check the result of important function calls, `fopen` in this case. – kaylum Sep 01 '20 at 06:40
  • 2
    Re "r or rb": Unless the file contains ascii text, Always open it with "rb". Otherwise the library will perform a newline -> carriage return+newline conversion on Windows, which would corrupt e.g. jpeg data (it has no effect on POSIX systems, in particular it does no harm there). – Peter - Reinstate Monica Sep 01 '20 at 06:44
  • 3
    Why do you call the variable `numberoffilesread` if it holds the number of bytes read? – the busybee Sep 01 '20 at 06:54
  • Thank you for your comments. Yes, my file has opened successfully. Still returns 0 as number of bytes read :( – thefailagent Sep 01 '20 at 07:17
  • 1
    Maybe `errno` shows the error that's occuring. – Paul Hankin Sep 01 '20 at 07:21
  • [`%zu` is the format specifier for `size_t`](https://stackoverflow.com/q/2524611/995714) – phuclv Sep 01 '20 at 07:32
  • 2
    @thefailagent How do you know the file has been opened successfully? You don't check this in your code, or you didn't post the code you're running... – Jabberwocky Sep 01 '20 at 07:36
  • Yes, this is not the full code. It's an abstract of a code, but in the full code i've included a if loop specifying that the file pointer should not be equal to NULL. – thefailagent Sep 01 '20 at 08:20
  • 1
    `if` is not a loop. – Gerhardh Sep 01 '20 at 08:41
  • is argv[1] well set? – rhaport Sep 01 '20 at 08:52
  • @thefailagent Are you sure the file you're trying to open isn't empty? Is the file you're trying to open actually the file you think it is? Did you check if the `bytes` buffer contains the first 512 (or whatever) bytes of the file you try to open? Did you run this with your favorite debugger? – Jabberwocky Sep 01 '20 at 08:56
  • 3
    Is **the code you are showing** actually reproducing the problem? Could you make the example actually self-contained, so it does not rely on command line arguments etc.? Right now this question is not answerable as the problem is not reproducable. – DevSolar Sep 01 '20 at 09:14
  • According to the man page, if an error occurs, or the end of the file is reached, the return value is a short item count **(or zero)**. fread() does not distinguish between end-of-file and error, and callers must use feof(3) and ferror(3) to determine which occurred. So, you need to add some diagnostics to your code and read the error codes and messages – rhaport Sep 01 '20 at 15:51

1 Answers1

1

here it seems ok

I tried it here and it worked with a local file. Then I tried this card.raw and it seems ok too. First block is only zeros, 2nd has a surprise, and then it goes on with data.

second block

  • 3rd block seems to be a valid jpeg signature...

enter image description here

  • I did not change your code except to display the data
  • compiled just under CL 19.27. No religious discussion here, please.
  • the code just goes reading as long there is data... waits for a key between blocks

here is the code

#include <ctype.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
//#include <cs50.h>

int main(int argc, char** argv)
{
    // Declaring a new type 
    typedef uint8_t BYTE;

    // Declaring an array of bytes, in which I want to read 512 bytes
    BYTE bytes[512];

    FILE* rawbytes = fopen("card.raw", "rb");
    if (rawbytes == NULL) return 1;
    // ok file is open
    size_t numberofbytesread = 0;
    size_t block = 0;
    char ch;
    while ((numberofbytesread = fread(bytes, 1, 512, rawbytes)) > 0)
    {
        printf("\n%zu bytes read:\n\n\t000    ", numberofbytesread);
        int col = 0;
        for (size_t i = 0; i < numberofbytesread; i += 1)
        {
            if(isprint(bytes[i]))
                printf("%2c  ", bytes[i]);
            else
                printf("%02X  ", bytes[i]);
            col += 1;
            if (col % 16 == 0) printf("\n\t%3d    ",i+1);
        };  // for()
        if (col % 16 == 0) printf("\n");
        block += 1;
        printf("Block: %zd. Press ENTER \n", block); 
        ch = fgetc(stdin);
    };
    fclose(rawbytes);
}
arfneto
  • 1,227
  • 1
  • 6
  • 13
  • Thank you for your comment! I'm glad that there's nothing fundamentally wrong with the code. Is there a reason why my fread outputs 0 every time that I call it? – thefailagent Sep 03 '20 at 01:21
  • 1
    It is strange. I used your code. Just changed the _output_ in order to see the data. Did you run the program as I wrote, just in case? I use MSVC under Windows 10 – arfneto Sep 03 '20 at 02:15
  • I forgot update this! As per the compiler warnings, I had to replace %3d from "t%3d" on 32:53 to %3lu. I don't know what all that means, but I guess it's some minor interface difference between C and C++. It worked like a charm! Thank you. – thefailagent Sep 04 '20 at 03:11
  • 1
    It is funny someone flag this question as in need of debugging details. There is the code, the symptoms AND the input file is available, although as a link to a small binary file. Maybe the author should ship his computer also, in order for others to have something reproducible. In my lab I could reproduce the error, but this really invalidades the question? – arfneto Sep 04 '20 at 14:06
  • Thank you for your support and answer. I tried to provide everything I could provide to make this reproducible and do not see how I've inconvenienced anyone enough for them to close the question! – thefailagent Sep 10 '20 at 02:53
  • Neither do I. Often I think that some star-reviewers on SO are a bit pedantic on pointing things as off-topic or not-reproducible or picking on some imho very less relevant issues. In some sense also they seem not to welcome beginners, up to a point that I found posts of people apologizing for posting in this site without noticing Stack Overflow is not for beginners. And by the other side sometimes things in the professional or academic world are not easily reproducible, but it happens once a week in production and let people crazy – arfneto Sep 10 '20 at 03:54