I am working on CS50 Recovery and I am unable to get the program to check the JPEG starting header.
I used debug50 and added a couple print statements to try and find the problem. Every time I run the program, it prints out "No Output File 2" meaning no outfile is created, and the IsJPEG boolean check is skipped.
Upon further debugging it seems that the buffer is 0'\000\ all along, so I suspect nothing is written into the buffer, causing the program to skip the boolean check (which trigger fopen) and hence causing it to break.
However, I struggle to find the reason why nothing is written into buffer.
Please help and thank you!
#include <stdio.h>
#include <stdlib.h>
#include <cs50.h>
#include <stdint.h>
typedef uint8_t BYTE;
bool isJPEG(BYTE buffer[]);
int main(int argc, char *argv[])
{
BYTE buffer[512];
int fileCounter = 0;
char filename[8];
if (argc != 2)
{
printf("%s\n", "Usage: ./recovery file");
return 1;
}
FILE* infile = fopen(argv[1], "r");
if (infile == NULL)
{
printf("%s\n", "Error: File Not Found");
return 1;
}
FILE* outfile;
while (fread(buffer, 512, 1, infile))
{
if (isJPEG(buffer))
{
if (fileCounter == 0)
{
sprintf(filename, "%03i.jpg", fileCounter++);
outfile = fopen(filename, "w");
printf("%s\n", "Bool 1");
}
else
{
fclose(outfile);
sprintf(filename, "%03i.jpg", fileCounter++);
outfile = fopen(filename, "w");
printf("%s\n", "Bool 2");
}
if (outfile == NULL)
{
printf("%s\n", "No Output File 1");
return 1;
}
fwrite(buffer, 512, 1, outfile);
}
else
{
if (outfile == NULL)
{
printf("%s\n", "No Output File 2");
return 1;
}
fwrite(buffer, 512, 1, outfile);
}
}
fclose(outfile);
fclose(infile);
}
bool isJPEG(BYTE buffer[])
{
return buffer[0] == 0xff && buffer[1] == 0xd8 && buffer[2] == 0xff && (buffer[3] & 0xf0) == 0xe0;
}
It prints "No output file 2" because it is told to so. When the script is running for the first time, execution is falling into else statement of if (isJPEG(buffer)) where it checks if outfile is NULL. It is indeed NULL because it is pointing to nothing and there No output file 2 is printed. Instead, it should be checked if the outfile is pointing to a file, only then we should write on it. I corrected the script as following;
while (fread(buffer, 512, 1, infile))
{
if (isJPEG(buffer))
{
if (fileCounter == 0)
{
sprintf(filename, "%03i.jpg", fileCounter++);
outfile = fopen(filename, "w");
printf("%s\n", "Bool 1");
}
else
{
fclose(outfile);
sprintf(filename, "%03i.jpg", fileCounter++);
outfile = fopen(filename, "w");
printf("%s\n", "Bool 2");
}
if (outfile != NULL)
{
fwrite(buffer, 512, 1, outfile);
}
}
else
{
if (outfile != NULL)
{
fwrite(buffer, 512, 1, outfile);
}
}
}
Related
So I'm trying CS50 Recover exercise (where you need to search for jpg files in a memory card and whenever you find one- you open a new file and write the jpg found to the new file). My code compiles and returns 51 jpegs instead of only 50 and all of them are incorrect. Please, I need some cues on what to focus at and fix/replace.
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
typedef uint8_t BYTE;
int main(int argc, char *argv[])
{
// Check for valid usage
if ( argc != 2)
{
printf("Usage: ./recover IMAGE\n");
return 1;
}
// Check for valid image
FILE *image = fopen(argv[1], "r");
if (image == NULL)
{
return 1;
}
BYTE buffer[512];
int i = 0;
char new_image[8];
FILE *output;
FILE *output1;
while (fread (buffer, 1, 512, image) == 512)
{
// IF Start of a JPEG
if (buffer[0] == 0xff && buffer[1] == 0xd8 && buffer[2] == 0xff && ((buffer[3] & 0xf0) == 0xe0))
{
sprintf(new_image, "%03i.jpg", i);
//if first JPEG
if ( i == 0)
{
output = fopen(new_image, "w");
fwrite(buffer, 512, 1, output);
i++;
}
// if not first JPEG
else
{
fclose(output);
sprintf(new_image, "%03i.jpg", i);
output1 = fopen(new_image, "w");
fwrite(buffer, 1, 512, output1);
fclose(output1);
i++;
}
}
// if not start of a JPEG
else
{
output = output1 = fopen(new_image, "w");
fwrite(buffer, 1, 512, output);
}
}
fclose(image);
}
I'm trying to solve this problem which consists of reading data from a "memory card" and write it into new readable jpg files.
I'm getting 50 files named correctly as far as I can tell but their data is incorrect. to me it looks like it should be writing into each jpg the data read into the buffer from the card or argv[1] but I'm guessing I'm missing something and I can't figure out what.
this is what I wrote so far:
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
typedef uint8_t BYTE;
int is_jpg(BYTE(buffer[]))
{
if (buffer[0] == 0xff && buffer[1] == 0xd8 && buffer[2] == 0xff && (buffer[3] & 0xe0) == 0xe0)
{
return 1;
}
else
{
return 0;
}
}
int main(int argc, char *argv[])
{
BYTE buffer[512];
//checks argument validity
if (argc != 2)
{
printf("Usage: ./recover image\n");
return 1;
}
FILE *file = fopen(argv[1], "r");
//printf("continuing program\n");
//checks if the file exists
if (file == NULL)
{
printf("No file found\n");
return 2;
}
int file_count = 0;
char file_name[8];
//sprintf(file_name, "%03d.jpg", file_count);
FILE *image;
while (fread(buffer, 512, 1, file) == 1)
{
if (is_jpg(buffer) == 1)
{
if (file_count != 0)
{
fclose(image);
}
sprintf(file_name, "%03d.jpg", file_count);
image = fopen(file_name, "w");
fread(&buffer, 512, 1 , file);
fwrite(&buffer, 512, 1, image);
file_count++;
}
else if (file_count > 0)
{
fwrite(buffer, 512, 1, image);
}
//fwrite(&buffer, 512, 1, image);
}
}
When you detect the header, you do an extra fread [after the image = fopen(file_name, "w"); call].
You want to write the header to the output file/stream. But, the extra fread trashes the header data and the first block of the file is data and not the header as you desire.
You only want the fread at the top of the loop.
I'm always getting a segfault when trying to run the code.
I think it is caused by the last lines fclose(file) and fclose(img), but I don't really seem to understand why exactly.
If I delete both lines nothing happens.
Could someone please explain to me why segfault is called and why it is not creating new .jpg's?
(I have to implement a program that recovers JPEGs from a forensic image)
https://cs50.harvard.edu/college/2020/fall/psets/4/recover/
#include <stdlib.h>
#include <stdint.h>
#include <cs50.h>
int main(int argc, char *argv[])
{
//open file
FILE *file = fopen(argv[1], "r");
//promting user
if(argc != 2)
{
printf("Usage: ./recover image\n");
return 1;
}
else if (file == NULL)
{
printf("Empty file.\n");
return 2;
}
int i = 0;
int found = 0;
unsigned char buffer[512];
FILE *img = NULL;
while (fread(buffer, 512, 1, file))
{
//start of new Jpeg?
if (buffer[0] == 0xff && buffer[1] == 0xff && buffer[2] == 0xff && (buffer[3] & 0xf0) == 0xe0)
{
//close file if found
if(found == 1)
{
fclose(img);
}
// open new one
else
{
found = 1;
}
char filename[8];
sprintf(filename, "%03i.jpg", i);
img = fopen(filename, "w");
i++;
}
if(found == 1)
{
fwrite(buffer, 512, 1, img);
}
}
fclose(file);
fclose(img);
return 0;
}
I have been trying to find out what is the issue with my code for hours. I referred to other people's code but I still don't know what's wrong. The code compiles fine but the debugger says that the segmentation fault occurs at line 44 (below the comment). Suggestions to improve my code are welcome too. Please help and thank you.
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
typedef uint8_t BYTE;
int main(int argc, char *argv[])
{
if (argc != 2)
{
printf("Usage: ./recover image\n");
return 1;
}
FILE *f = fopen(argv[1],"r");
if (!f)
{
return 2;
}
BYTE buffer[512];
FILE* img = NULL;
int i = 0;
while (fread(buffer, 512, 1, f) == 1)
{
if (buffer[0] == 0xff && buffer[1] == 0xd8 && buffer[2] == 0xff
&& (buffer[3] & 0xf0) == 0xe0)
{
//create jpeg
char filename[8];
if (img != NULL)
{
fclose(img);
i++;
sprintf(filename, "%03i.jpg",i);
img = fopen(filename, "w");
fwrite(buffer, 512 , 1, img);
}
else
{
sprintf(filename, "%03i.jpg",i);
img = fopen(filename, "w");
//error in the line below :(
fwrite(buffer, 512 , 1, img);
}
}
else if (i > 0)
{
fwrite(buffer, 512 , 1, img);
}
}
fclose(img);
fclose(f);
}
It looks like the most likely failure reason for that line you call out, is that the file handle could be invalid. Hence the first thing I would be doing is checking that every file opens correctly, something like:
img = fopen(filename, "w");
if (img == NULL) {
printf("Error opening file '%s'\n", filename);
exit(1);
}
It's generally a good idea to check for failure conditions in functions than can fail, and this also includes the fwrite calls:
if (fwrite(buffer, 512 , 1, img) != 1) {
printf("Error writing to file\n");
exit(1);
}
I'm having problems trying to execute the following code correctly. The problem is that I am creating the exact number of JPEGs, and they seem to open correctly, except there is no image being shown. I'm doing recover.c of Pset4 in the course CS50.
/**
* A file that recovers lost JPEGs
*/
#include <stdio.h>
#include <stdlib.h>
#include <cs50.h>
#include <stdint.h>
#define BLOCK 512
int main(int argc, char *argv[])
{
// ensure proper usage
if (argc != 2)
{
fprintf(stderr, "Usage: ./recover image\n");
return 1;
}
// remember filenames
char *infile = argv[1];
// open file
FILE* inptr = fopen(infile, "r");
if (inptr == NULL)
{
fprintf(stderr, "Could not open %s.\n", infile);
return 2;
}
FILE* outptr;
uint8_t buffer[512];
int count = 0;
while (fread(buffer, BLOCK, 1, inptr))
{
if (buffer[0] == 0xff && buffer[1] == 0xd8 && buffer[2] == 0xff
&& (buffer[3] == 0xe0 || buffer[3] == 0xe1))
{
char filename[8];
sprintf(filename, "%03d.jpg", count);
outptr = fopen(filename, "w");
count++;
fwrite(&buffer, BLOCK, 1, outptr);
if (outptr == NULL)
{
fclose(inptr);
fprintf(stderr, "Could not create %s.\n", filename);
return 3;
}
}
}
fclose(outptr);
fclose(inptr);
return 0;
}
There's no way the images open correctly, since you only ever copy at most 512 bytes into each file, and I'm going to assume most images are larger than that.
This code:
outptr = fopen(filename, "w");
must go outside the while(fread()) loop, you only want to open each output file once, not once per read block.
Also, the return value of fread() is very important here, and I/O should be binary.
Nevermind, I have fixed the code and found the answer to my problem. Here's the code if anyone's interested: Thanks to everyone who helped!
/**
* A file that recovers lost JPEGs
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#define BLOCK 512
int main(int argc, char *argv[])
{
// ensure proper usage
if (argc != 2)
{
fprintf(stderr, "Usage: ./recover image\n");
return 1;
}
// remember filenames
char *infile = argv[1];
// open file
FILE* inptr = fopen(infile, "r");
if (inptr == NULL)
{
fprintf(stderr, "Could not open %s.\n", infile);
return 2;
}
FILE* outptr;
uint8_t buffer[512];
int count = 0;
// find lost images and write to outfile
while (fread(buffer, BLOCK, 1, inptr))
{
if (buffer[0] == 0xff && buffer[1] == 0xd8 && buffer[2] == 0xff
&& (buffer[3] == 0xe0 || buffer[3] == 0xe1))
{
char filename[8];
sprintf(filename, "%03d.jpg", count);
outptr = fopen(filename, "w");
count++;
if (outptr == NULL)
{
fclose(inptr);
fprintf(stderr, "Could not create %s.\n", filename);
return 3;
}
}
if (outptr != NULL)
{
fwrite(&buffer, BLOCK, 1, outptr);
}
}
fclose(outptr);
fclose(inptr);
return 0;
}