Reasons why fgetc() and/or fputc() is inconsistent [closed] - c

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
Given the following snippet, fin containing random text with data always following a command:
#define COMMANDSIZE 16
#define DATASIZE 128
int i, j, k, ch;
char command[COMMANDSIZE];
char data[DATASIZE];
FILE* fin;
FILE* fout;
fin = fopen("input.txt", "r");
fout = fopen("output.txt", "w");
fseek(fout, 0, SEEK_SET);
while ((ch = fgetc(fin)) != EOF)
{
for (i = 0; i < sizeof(command); i++) //obtain command from input stream
{
command[i] = fgetc(fin) & 0xff;
}
for (j = 0; j < sizeof(data); j++) //obtain data from input stream
{
data[j] = fgetc(fin) & 0xff;
}
for (k = 0; k < sizeof(data); k++) //write data to output stream
{
fseek(fout, /* computed block address */, SEEK_CUR);
fputc(data[k], fout);
}
}
fclose(fout);
fclose(fin);
Comparing the input and output file, some data in the input file did not carry over. Thus, I tried doing the above with while(1), and again, some data in the input file did not carry over, but it wasn't the same data as using while((ch = fgetc(fin)) != EOF), and there was not an intersect (some overlap) between the different output files.
How can I ensure all data from the input file is written to the output file? Does this have to do with fgetc() and/or fputc()?

A few things are not clear to me here.
while ((ch = fgetc(fin)) != EOF)
Do you intend to throw away the character you just read?
fseek(fout, 1, SEEK_CUR);
Why are you skipping ahead one byte? Writing will advance the file automatically. I don't think you want to advance the file position twice.

I would do something like this instead:
char command[COMMANDSIZE];
char data[DATASIZE];
FILE* fin;
FILE* fout;
fin = fopen("input.txt", "rb");
fout = fopen("output.txt", "wb");
while (fread(command, sizeof(command), 1, fin) != EOF)
{
if (fread(data, sizeof(data), 1, fin) != EOF)
{
fseek(...); /* Seek to the block where current data should be written */
fwrite(data, sizeof(data), 1, fout);
}
}

Related

Reading and printing the last number of integers from a binary file to the console [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed last year.
Improve this question
int read_last_ints(const char *file_name, int num_ints)
{
FILE *fp = fopen(file_name, "r");
if (fp == NULL)
{
return 1;
}
int integers;
long int size;
size_t nread;
fseek(fp, 0, SEEK_END);
size = ftell(fp);
rewind(fp);
size = size - num_ints;
fseek(fp, size, SEEK_SET);
while ((nread = fread(&integers, 1, sizeof(int), fp)) > 0)
{
printf("%d\n", integers);
}
fclose(fp);
return 0;
}
I am trying to create a function that reads the last integers from a binary file, however my code doesn't work as intended. When I try to test my code, it produces random numbers that don't make sence. If anyone has any advice, please share it. Thank you.
You need to position backwards from the end of the file by the size of num_ints integers.
A minimalist change to your code is:
int read_last_ints(const char *file_name, int num_ints)
{
FILE *fp = fopen(file_name, "r");
if (fp == NULL)
{
return 1;
}
int integers;
long int size;
size_t nread;
fseek(fp, 0, SEEK_END);
size = ftell(fp);
rewind(fp);
size = size - sizeof(int) * num_ints; /* MNC — minimum necessary change */
fseek(fp, size, SEEK_SET);
while ((nread = fread(&integers, 1, sizeof(int), fp)) > 0)
{
printf("%d\n", integers);
}
fclose(fp);
return 0;
}
However, you can make use of the SEEK_END option more effectively. You should probably also use "rb" instead of "r" to read a binary file. Using "rb" is crucial on Windows; it is harmless on Unix-like systems (because the C standard mandates support for "rb", even though it is not necessary on Unix). This code also renames the variable integers to the singular integer.
int read_last_ints(const char *file_name, int num_ints)
{
FILE *fp = fopen(file_name, "r");
if (fp == NULL)
{
return 1;
}
int integer;
size_t nread;
fseek(fp, -(long)(num_ints * sizeof(int)), SEEK_END);
while ((nread = fread(&integer, 1, sizeof(int), fp)) > 0)
{
printf("%d\n", integer);
}
fclose(fp);
return 0;
}
This saves a call to fseek(), ftell() and rewind(). The rewind() was always superfluous, but you don't need to know the actual size of the file. The fseek() call simply seeks to the relevant number of bytes before the end of the file. You'd only have problems if the file is not big enough to hold that many integers (and it would just do its best, seeking to the start and reading as much as possible).

CS50 recover doesn't output any images

I'm working on the recover program of the CS50 course. Here are the instructions:
Implement your program in a file called recover.c in a directory called recover.
Your program should accept exactly one command-line argument, the name of a forensic image from which to recover JPEGs.
If your program is not executed with exactly one command-line argument, it should remind the user of correct usage, and main should
return 1.
If the forensic image cannot be opened for reading, your program should inform the user as much, and main should return 1.
Your program, if it uses malloc, must not leak any memory.
I think my code is supposed to work, but it doesn't. In fact, it doesn't output any images at all! Here's the code:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
FILE * pFile = NULL;
unsigned char *buffer = malloc(512);
char* filename = NULL;
int filenumber = 0;
//If user didn't print 2 items
if(argc != 2)
{
printf("Usage: ./recover image\n");
return 1;
}
//Open the file
pFile = fopen(argv[1], "r");
if (!pFile)
{
fprintf(stderr, "File cannot be opened\n");
return 2;
}
int j=0;
// checking the card by 512b chunks
//loop (i=0, i++);
while (pFile)
{
int i =0;
i++;
//k=fread (buffer, 512, i, *file);
int k = fread(buffer, 512, i, pFile);
// if 512 byte block is jpeg, make new jpeg file
if (buffer[0] == 0xff && buffer[1] == 0xd8 && buffer[2] == 0xff && (buffer[3] & 0xf0) == 0xe0)
{
// if it's not the first file, we should close the last one
if (filename != NULL)
{
fclose(pFile);
}
//sprintf
sprintf(filename, "%03i.jpg", 2);
//FILE = fopen (W)
pFile = fopen(filename, "w");
// fwrite (buffer, 512, j, *file1)
fwrite (buffer, 512, j, pFile);
//j=j+1
j = j + 1;
}
// if k<512 - end of the loop
if (k < 512)
{
return 0;
}
}
free(buffer);
}
I don't understand it, but I see no new files or JPEGs pop-up in my files. When I try to double-click on the file, which is called card.raw, it doesn't let me open it.
You have a load of problems. Running your code in a debugger should reveal most of them within a second.
Let's take a look:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
FILE * pFile = NULL;
unsigned char *buffer = malloc(512);
char* filename = NULL; <<==== You never allocate any memory for this. Use an array.
int filenumber = 0;
//If user didn't print 2 items
if(argc != 2)
{
printf("Usage: ./recover image\n");
return 1;
}
//Open the file
pFile = fopen(argv[1], "r");
if (!pFile)
{
fprintf(stderr, "File cannot be opened\n");
return 2;
}
int j=0;
// checking the card by 512b chunks
//loop (i=0, i++); <<== No information provided by this comment.
while (pFile) <<== pFile is your input file. This should never change. ???
{
int i =0;
i++;
//k=fread (buffer, 512, i, *file); <<== Useless comment. Nearly same as code below but causes compiler error
int k = fread(buffer, 512, i, pFile); <<== i is always 1 and must be 1. Don't use variable.
<<== BTW: You should check k **before** using the buffer.
// if 512 byte block is jpeg, make new jpeg file
if (buffer[0] == 0xff && buffer[1] == 0xd8 && buffer[2] == 0xff && (buffer[3] & 0xf0) == 0xe0)
{
// if it's not the first file, we should close the last one
if (filename != NULL)
{
fclose(pFile); <<== Yikes!!! This is your input file.
}
//sprintf <<== Yes, that's obvious. Useless comment.
sprintf(filename, "%03i.jpg", 2); <<== Yikes!! You never allocate memory. NULL pointer!!
<<== Why do you always print 2? you have a counter.
//FILE = fopen (W) <<== Again no useful information in comment
pFile = fopen(filename, "w"); <<== Feed NULL into fopen and kill pFile.
// fwrite (buffer, 512, j, *file1) <<== you know what I mean...
fwrite (buffer, 512, j, pFile); <<== You only have 1 buffer, why write j blocks?
//j=j+1 <<== obvious
j = j + 1;
}
// if k<512 - end of the loop
if (k < 512) <<== fread returns number of elements, i.e. 1, not number of bytes.
{
<< you return without
- closing files
- freeing buffer
return 0;
}
<<== Now you go back to top of the loop and want to read next block from your raw file but pFile was killed in the loop.
}
free(buffer);
}

trying to read a file

basically trying to make an anti virus but all I get when trying to read the infected file into a buffer is EOF... it's a jpg and I have no idea how to fix this
about the file functions I'm allowed to use:
fread/fwrite
fgets
fputs
fclose
fopen
fgetc
fputc
fscanf
fprintf
int fullScan(FILE* sign, FILE* infected);
char* getFile(FILE* file);
int main(int argc, char** argv)
{
FILE* sign = fopen("KittenVirusSign", "rb");
FILE* infected = fopen("kitten_frog.jpg", "rb");
int j = 0;
if (infected == NULL)
{
printf("couldn't open the file (suspicious file)");
return -1;
}
if (sign == NULL)
{
printf("couldn't open the file (virus signature)");
return -1;
}
j = fullScan(sign, infected);
return 0;
}
int fullScan(FILE* sign, FILE* infected)
{
char* sign_c = NULL;
char* infec_c = NULL;
int infect_res = -1;
int sign_len = 0;
int infec_len = 0;
int i = 0;
int j = 0;
sign_c = getFile(sign);
infec_c = getFile(infected);
while (1)
{
if (*(infec_c + i) == *(sign_c + j))
{
infect_res = 1;
if (*(sign_c + j) == EOF)
{
break;
}
else if (*(infec_c + i) == EOF)
{
infect_res = -1;
break;
}
i++;
j++;
continue;
}
else if (*(infec_c + i) != *(sign_c + j))
{
if (*(infec_c + i) == EOF || *(sign_c + j) == EOF)
{
break;
}
i++;
j = 0;
infect_res = -1;
}
}
fclose(infected);
free(sign_c);
free(infec_c);
return infect_res;
}
char* getFile(FILE* file)
{
char* buffer;
long filelen;
int i;
fseek(file, 0, SEEK_END);
filelen = ftell(file);
fseek(file, 0, SEEK_SET);
buffer = (char *)malloc((filelen + 1)*sizeof(char));
for (i = 0; i < filelen; i++)
{
fread(buffer + i, sizeof(char), 1, file);
}
return buffer;
}
EOF is a special integer value returned by some input functions to indicate that the end of the file has been reached, but it is not part of the file data. Your fread() will therefore never store an EOF character into the input buffer you provided. However, if your C implementation features signed default chars, as many do, then there is a char value that is numerically equal to EOF (usually -1).
If either file happens to contain that byte, then your code will misinterpret it as designating the end of that file. If it happens to be the first byte in either file then the program will misinterpret the file as being empty.
Since you are analyzing binary files,
I recommend using buffers of unsigned char rather than default char.
All possible byte values can appear in the file data, so you cannot identify the end of the data by the value of any byte within.
Probably, getFile() should return a struct that contains both a pointer to the buffer and its size.
As other answer suggested, you should also send the file length and iterate over that, rather than waiting for a EOF.
Also, in your getFile() function, when you determine the length of the file you don't have to read byte by byte, you can just send the filelen to fread() like so
fread(buffer, sizeof(char), filelen, file);
fread now reads filelen elements of data each the size of a char (you can write 1 instead) from the stream file to buffer.

Get number line of file text in c [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
How do get number line of file text on c ?. Help me .
Get sum number line.
I want read a file text.
EX:
for( line = 0; line < sumline; line ++) {
printf("char in line");
}
In case i understood the question :
#include <stdio.h>
#include <string.h>
main()
{
FILE *fp;
char * line;
size_t len = 0;
ssize_t read;
int lines = 0;
fp = fopen("input.txt", "r");
if( fp != NULL ){
while ((read = getline(&line, &len, fp)) != -1){
lines ++;
printf("%s\n", line);
}
fclose(fp);
}
printf("number of lines : %d\n", lines);
}
to count how many lines in your file
Try this:
`int lines = 0;
while ((read = getline(&line, &len, fp)) != -1) {
lines++;
}
cout << lines << endl;`
You can use the following function to get the number of lines inside a file.
#include <stdio.h>
// get the number of lines inside file
int getLineCnt(char *pcFileName) {
FILE *fp;
int lines=0;
fp = fopen(pcFileName, "r");
if(fp == NULL) { return -1; }
while (EOF != (fscanf(fp, "%*[^\n]"), fscanf(fp, "%*c"))) {
++lines;
}
io_fclose(fp);
return lines; ///\ retval number of lines
}

Reading a .bmp image with fread()

I am trying to read a .bmp image and write the data into a text file. Code is running fine but the problem is, it cannot read whole image once so I have to call fread() function many times. While doing this my code is repeatedly storing the first read data into the text file. What changes do I have to do in order to read the whole image properly? Below is my code snippet.
int size = width * height;
unsigned char* data = new unsigned char[size];
filename = "image.bmp";
fname = "image_data.txt";
FILE* f = fopen(filename, "rb");
FILE *fp = fopen(fname, "w");
while(totalBytes < size)
{
readsize = fread(data, sizeof(unsigned char), size, f);
totalBytes += readsize;
for(i = 0; i < readsize; i++)
{
fprintf(fp, "%d", data[i]);
if((i % width) == 0 && i != 0)
fprintf(fp, "\n");
}
fseek(f, readsize, SEEK_SET);
readsize = 0;
}
Your fseek call is wrong. After the fread call the file position will be behind the read data, so you can just read on without seeking.
What happened before was that you read X bytes, did an unnecessary but harmless fseek to file position X, then read Y bytes, but did a harmful fseek back to file position X, so you kept reading the same data again.
while(totalBytes < size)
{
readsize=fread(data, sizeof(unsigned char), size, f);
totalBytes+=readsize;
for(i = 0; i < readsize; i++)
{
fprintf(fp,"%d",data[i]);
if((i % width)== 0 && i!=0)
fprintf(fp,"\n");
}
}

Resources