Read bytes (chars) from buffer - c

I'm working on steganography program in Java. But I got advice that I be able to resolve this task better in C program. I would like to try it, but I'm pretty bad in C programing. For now I would like to read one gif file and find byte which is used as image separator (0x2c from GIF format).
I tried to write this program:
int main(int argc, char *argv[])
{
FILE *fileptr;
char *buffer;
long filelen = 0;
fileptr = fopen("D:/test.gif", "rb"); // Open the file in binary mode
fseek(fileptr, 0, SEEK_END); // Jump to the end of the file
filelen = ftell(fileptr); // Get the current byte offset in the file
rewind(fileptr); // Jump back to the beginning of the file
buffer = (char *)malloc((filelen+1)*sizeof(char)); // Enough memory for file + \0
fread(buffer, filelen, 1, fileptr); // Read in the entire file
fclose(fileptr); // Close the file
int i = 0;
for(i = 0; buffer[ i ]; i++)
{
if(buffer[i] == 0x2c)
{
printf("Next image");
}
}
return 0;
}
Could someone give me advice how to repair my loop?

Could someone give me advice how to repair my loop?
Option 1: Don't depend on the terminating null character.
for(i = 0; i < filelen; i++)
{
if(buffer[i] == 0x2c)
{
printf("Next image");
}
}
Option 2: Add the terminating null character before relying on it. This is potentially unreliable since you are reading a binary file that could have embedded null characters in it.
buffer[filelen] = '\0';
for(i = 0; buffer[ i ]; i++)
{
if(buffer[i] == 0x2c)
{
printf("Next image");
}
}

Similar to the 'for()' based answer, if you only need to check for a specific byte (0x2c), you can simply do something like the following (and not worry about null in the byte stream), using while().
i = 0;
while(i < filelen)
{
if(buffer[i++] == 0x2c)
{
printf("Next image");
}
}

Related

how do i make operations on a specific line in a text file in c?

void main(void)
{
FILE* textfile;
char line[1000];
textfile = fopen("omar.txt", "r");
if (textfile == NULL)
return 1;
while (fgets(line, 1000, textfile)) {
printf(line);
}
fclose(textfile);
}
so this code prints the whole content of a text file , what should I do to read the third line in the file for example ?
To read the nth line in a file you can do something like this
int i = 0;
while (fgets(line, 1000, textfile)) {
i++;
if (i == n) {
// do stuff with nth line
break;
}
}
This approach uses a counter to count until the nth iteration is reached. Once it is, you can do what you need to do with the nth line.
Also this may be unrelated but you should never use printf without a format specifier as you have in printf(line);. This can be dangerous and could be used by an attacker to exploit the program. I would recommend that in your case puts(line); is a better alternative.
For example:
int readNthLine(FILE *fi, char *buff, size_t buffsize, size_t line)
{
fseek(fi, 0, SEEK_SET);
{
for(size_t cline = 0; cline < line; cline++)
{
if(!fgets(buff, buffsize, fi)) return -1;
}
}
return 0;
}
This very simple function will work only if the size of the buffer is larger than the length of the longest line in the file.
Of course, you should check the result of any I/O operation.

Reading text file into an array in C

I want to parse a .txt file into a 1D array in C. I'm using the fgets function to read the contents of the file into the array("waveform" as the array into which the file contents are to be stored - defined as a "char"). The saved values need to be saved into a new array as integer values. I am not sure where I am going wrong.
P.S: I am new to programming in C, please bear with me :)
Please ignore the indexing issues, done due to pasting
int main(){
int a, win[10];
FILE *filename = fopen("testFile.txt","r");
char waveform[10];
if (filename == NULL)
{
printf("Error opening file.\n");
exit(8);
}
for(int i =0;1;i++){
if(fgets(waveform[i], 10, filename) == NULL);
break;
if(i < 10)
{
a = atoi(waveform[i]);
win[i] = a;
}
}
fclose(filename);
return 0;
}
Compiler errors - image embedded
Data in testFile.txt:
1 to 10 in a row vector.
You are on the right track. Here is my contribution on the topic:
Open the file (fopen)
Count number of lines (getc and rewind)
Read all lines into array (getline)
Free memory and close file (free and fclose)
Code example:
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char *argv[])
{
// Open File
const char fname[] = "testFile.txt";
FILE *fp = fopen(fname, "r");
if( !fp )
goto error_open_file;
printf("Opened file: %s\n", fname);
// Count Lines
char cr;
size_t lines = 0;
while( cr != EOF ) {
if ( cr == '\n' ) {
lines++;
}
cr = getc(fp);
}
printf("Number of lines: %ld\n", lines);
rewind(fp);
// Read data
{// 'goto' + data[lines] causes error, introduce block as a workaround
char *data[lines];
size_t n;
for (size_t i = 0; i < lines; i++) {
data[i] = NULL;
size_t n = 0;
getline(&data[i], &n, fp);
if ( ferror( fp ) )
goto error_read_file;
}
for (size_t i = 0; i < lines; i++) {
printf("%s", data[i]);
free(data[i]);
}
}
// Close File
fclose(fp);
return 0;
error_read_file:
perror("fopen ");
return 1;
error_open_file:
perror("getline ");
return 2;
}
There are several errors in this loop
for(int i =0;1;i++){
if(fgets(waveform[i], 10, filename) == NULL);
break;
if(i < 10)
{
a = atoi(waveform[i]);
win[i] = a;
}
}
For starters there is a semicolon after the if statement
if(fgets(waveform[i], 10, filename) == NULL);
^^^
Secondly the fgets call
fgets(waveform[i], 10, filename)
^^^
is invalid because the type of the expression waveform[i] is char.
And correspondingly this statement
a = atoi(waveform[i]);
is also invalid.
There must be at least
fgets( waveform, 10, filename)
and
a = atoi( waveform );
I suppose that each line of the file contains exactly one number. (Otherwise you should use for example sscanf to extract numbers from a line using an internal additional loop.)
The loop can look like
int i = 0;
for ( ; i < 10 && fgets( waveform, 10, filename) != NULL; i++ )
{
a = atoi( waveform );
win[i] = a;
}
After the loop the variable i will contain the actual number of elements of the array win.
Pay attention to that the name filename is not good for a pointer of the type FILE *. File name is the string "testFile.txt" in your code.
If you want to use the fgets() function you don't have to put it into a loop. Indeed, the second argument of fgets() is the number of elements you want to read.
I would have put the fgets() into a singl-line instruction, and then loop from 0 to 10 to make the conversion from char to int with the atoi() function.
Moreover, you have a ; at the end of your if() statement, so you'll execute it not in the way you want.

Find end of text in a text file padded with NULL characters in C [duplicate]

file looks like this:
abcd
efgh
ijkl
I want to read the file using C so that it read the last line first:
ijkl
efgh
abcd
I cannot seem to find a solution that does not use an array for storage. Please help.
edit0:
Thanks for all the answers. Just to let you know, I am the one creating this file. So, can I create in a way its in the reverse order? Is that possible?
It goes like this:
Seek to one byte before the end of the file using fseek. There's no guarantee that the last line will have an EOL so the last byte doesn't really matter.
Read one byte using fgetc.
If that byte is an EOL then the last line is a single empty line and you have it.
Use fseek again to go backwards two bytes and check that byte with fgetc.
Repeat the above until you find an EOL. When you have an EOL, the file pointer will be at the beginning of the next (from the end) line.
...
Profit.
Basically you have to keep doing (4) and (5) while keeping track of where you were when you found the beginning of a line so that you can seek back there before starting your scan for the beginning of the next line.
As long as you open your file in text mode you shouldn't have have to worry about multibyte EOLs on Windows (thanks for the reminder Mr. Lutz).
If you happen to be given a non-seekable input (such as a pipe), then you're out of luck unless you want to dump your input to a temporary file first.
So you can do it but it is rather ugly.
You could do pretty much the same thing using mmap and a pointer if you have mmap available and the "file" you're working with is mappable. The technique would be pretty much the same: start at the end and go backwards to find the end of the previous line.
Re: "I am the one creating this file. So, can I create in a way its in the reverse order? Is that possible?"
You'll run into the same sorts of problems but they'll be worse. Files in C are inherently sequential lists of bytes that start at the beginning and go to the end; you're trying to work against this fundamental property and going against the fundamentals is never fun.
Do you really need your data in a plain text file? Maybe you need text/plain as the final output but all the way through? You could store the data in an indexed binary file (possibly even an SQLite database) and then you'd only have to worry about keeping (or windowing) the index in memory and that's unlikely to be a problem (and if it is, use a "real" database); then, when you have all your lines, just reverse the index and away you go.
In pseudocode:
open input file
while (fgets () != NULL)
{
push line to stack
}
open output file
while (stack no empty)
{
pop stack
write popped line to file
}
The above is efficient, there is no seek (a slow operation) and the file is read sequentially. There are, however, two pitfalls to the above.
The first is the fgets call. The buffer supplied to fgets may not be big enough to hold a whole line from the input in which case you can do one of the following: read again and concatenate; push a partial line and add logic to the second half to fix up partial lines or wrap the line into a linked list and only push the linked list when a newline/eof is encountered.
The second pitfall will happen when the file is bigger than the available ram to hold the stack, in which case you'll need to write the stack structure to a temporary file whenever it reaches some threshold memory usage.
The following code should do the necessary inversion:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
FILE *fd;
char len[400];
int i;
char *filename = argv[1];
int ch;
int count;
fd = fopen(filename, "r");
fseek(fd, 0, SEEK_END);
while (ftell(fd) > 1 ){
fseek(fd, -2, SEEK_CUR);
if(ftell(fd) <= 2)
break;
ch =fgetc(fd);
count = 0;
while(ch != '\n'){
len[count++] = ch;
if(ftell(fd) < 2)
break;
fseek(fd, -2, SEEK_CUR);
ch =fgetc(fd);
}
for (i =count -1 ; i >= 0 && count > 0 ; i--)
printf("%c", len[i]);
printf("\n");
}
fclose(fd);
}
The following works for me on Linux, where the text file line separator is "\n".
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void readfileinreverse(FILE *fp)
{
int i, size, start, loop, counter;
char *buffer;
char line[256];
start = 0;
fseek(fp, 0, SEEK_END);
size = ftell(fp);
buffer = malloc((size+1) * sizeof(char));
for (i=0; i< size; i++)
{
fseek(fp, size-1-i, SEEK_SET);
buffer[i] = fgetc(fp);
if(buffer[i] == 10)
{
if(i != 0)
{
counter = 0;
for(loop = i; loop > start; loop--)
{
if((counter == 0) && (buffer[loop] == 10))
{
continue;
}
line[counter] = buffer[loop];
counter++;
}
line[counter] = 0;
start = i;
printf("%s\n",line);
}
}
}
if(i > start)
{
counter = 0;
for(loop = i; loop > start; loop--)
{
if((counter == 0) && ((buffer[loop] == 10) || (buffer[loop] == 0)))
{
continue;
}
line[counter] = buffer[loop];
counter++;
}
line[counter] = 0;
printf("%s\n",line);
return;
}
}
int main()
{
FILE *fp = fopen("./1.txt","r");
readfileinreverse(fp);
return 0;
}
Maybe , The does the trick , It reverse content of the file in whole
just like a string
Define a variable of type string with size of your file
Get Contents of the file and store in the variable
Use strrev() to reverse the string.
You can later on display the output or even write it to a file. The code goes like this:
#include <stdio.h>
#include <String.h>
int main(){
FILE *file;
char all[1000];
// give any name to read in reverse order
file = fopen("anyFile.txt","r");
// gets all the content and stores in variable all
fscanf(file,"%[]",all);
// Content of the file
printf("Content Of the file %s",all);
// reverse the string
printf("%s",strrev(all));
fclose(file);
return 0;
}
I know this question has been awnsered, but the accepted awnser does not contain a code snippet and the other snippets feel too complex.
This is my implementation:
#include <stdio.h>
long file_size(FILE* f) {
fseek(f, 0, SEEK_END); // seek to end of file
long size = ftell(f); // get current file pointer
fseek(f, 0, SEEK_SET); // seek back to beginning of file
return size;
}
int main(int argc, char* argv[]) {
FILE *in_file = fopen(argv[1], "r");
long in_file_size = file_size(in_file);
printf("Got file size: %ld\n", in_file_size);
// Start from end of file
fseek(in_file, -1, SEEK_END); // seek to end of file
for (int i = in_file_size; i > 0; i--) {
char current_char = fgetc(in_file); // This progresses the seek location
printf("Got char: |%c| with hex: |%x|\n", current_char, current_char);
fseek(in_file, -2, SEEK_CUR); // Go back 2 bytes (1 to compensate)
}
printf("Done\n");
fclose(in_file);
}

Program Segfaults in between 2 printf()'s

hope someone can assist. I had this program running perfectly, moved a few lines of code from one function to another and it all fell apart.
I've included a snippet below from the top of the function until segfault. It happily outputs "did we get here?" but not the next statement, I've spent so many hours trying to figure this that I can't remember the working build I had to begin with
It (at least the section below) is supposed to copy a whole textfile to a string
Morals of the story: working code is better than 'correct' code, always copy working code before you try to tweak it.
void validateFile(FILE* file, char** menuStore, char** submenuStore)
{
char* temp = NULL;
size_t size;
boolean flag = true;
char first;
/*Loop Counter*/
int i;
fseek(file, 0, SEEK_END);
size = ftell(file) * sizeof(char);
fseek(file, 0, SEEK_SET);
if ((temp = malloc(size)) == NULL)
{
printf("\nUnable to allocate Memory, Program exiting");
exit(EXIT_FAILURE);
} else
{
for (i = 0; i < (size / sizeof(char)); i++)
{
temp[i] = fgetc(file);
}
printf("\n did we get here?");
printf("\nFile loaded, validating...");
While reading from a file you should not use loop like this-
for (i = 0; i < (size / sizeof(char)); i++)
{
temp[i] = fgetc(file);
}
You should check for EOF condition while reading from a file-
i=0;
while((temp[i]=fgetc(file))!=EOF)
i++;
and make end of the string to \0. That is the better way to do.
temp[i]='\0';

read file backwards (last line first)

file looks like this:
abcd
efgh
ijkl
I want to read the file using C so that it read the last line first:
ijkl
efgh
abcd
I cannot seem to find a solution that does not use an array for storage. Please help.
edit0:
Thanks for all the answers. Just to let you know, I am the one creating this file. So, can I create in a way its in the reverse order? Is that possible?
It goes like this:
Seek to one byte before the end of the file using fseek. There's no guarantee that the last line will have an EOL so the last byte doesn't really matter.
Read one byte using fgetc.
If that byte is an EOL then the last line is a single empty line and you have it.
Use fseek again to go backwards two bytes and check that byte with fgetc.
Repeat the above until you find an EOL. When you have an EOL, the file pointer will be at the beginning of the next (from the end) line.
...
Profit.
Basically you have to keep doing (4) and (5) while keeping track of where you were when you found the beginning of a line so that you can seek back there before starting your scan for the beginning of the next line.
As long as you open your file in text mode you shouldn't have have to worry about multibyte EOLs on Windows (thanks for the reminder Mr. Lutz).
If you happen to be given a non-seekable input (such as a pipe), then you're out of luck unless you want to dump your input to a temporary file first.
So you can do it but it is rather ugly.
You could do pretty much the same thing using mmap and a pointer if you have mmap available and the "file" you're working with is mappable. The technique would be pretty much the same: start at the end and go backwards to find the end of the previous line.
Re: "I am the one creating this file. So, can I create in a way its in the reverse order? Is that possible?"
You'll run into the same sorts of problems but they'll be worse. Files in C are inherently sequential lists of bytes that start at the beginning and go to the end; you're trying to work against this fundamental property and going against the fundamentals is never fun.
Do you really need your data in a plain text file? Maybe you need text/plain as the final output but all the way through? You could store the data in an indexed binary file (possibly even an SQLite database) and then you'd only have to worry about keeping (or windowing) the index in memory and that's unlikely to be a problem (and if it is, use a "real" database); then, when you have all your lines, just reverse the index and away you go.
In pseudocode:
open input file
while (fgets () != NULL)
{
push line to stack
}
open output file
while (stack no empty)
{
pop stack
write popped line to file
}
The above is efficient, there is no seek (a slow operation) and the file is read sequentially. There are, however, two pitfalls to the above.
The first is the fgets call. The buffer supplied to fgets may not be big enough to hold a whole line from the input in which case you can do one of the following: read again and concatenate; push a partial line and add logic to the second half to fix up partial lines or wrap the line into a linked list and only push the linked list when a newline/eof is encountered.
The second pitfall will happen when the file is bigger than the available ram to hold the stack, in which case you'll need to write the stack structure to a temporary file whenever it reaches some threshold memory usage.
The following code should do the necessary inversion:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
FILE *fd;
char len[400];
int i;
char *filename = argv[1];
int ch;
int count;
fd = fopen(filename, "r");
fseek(fd, 0, SEEK_END);
while (ftell(fd) > 1 ){
fseek(fd, -2, SEEK_CUR);
if(ftell(fd) <= 2)
break;
ch =fgetc(fd);
count = 0;
while(ch != '\n'){
len[count++] = ch;
if(ftell(fd) < 2)
break;
fseek(fd, -2, SEEK_CUR);
ch =fgetc(fd);
}
for (i =count -1 ; i >= 0 && count > 0 ; i--)
printf("%c", len[i]);
printf("\n");
}
fclose(fd);
}
The following works for me on Linux, where the text file line separator is "\n".
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void readfileinreverse(FILE *fp)
{
int i, size, start, loop, counter;
char *buffer;
char line[256];
start = 0;
fseek(fp, 0, SEEK_END);
size = ftell(fp);
buffer = malloc((size+1) * sizeof(char));
for (i=0; i< size; i++)
{
fseek(fp, size-1-i, SEEK_SET);
buffer[i] = fgetc(fp);
if(buffer[i] == 10)
{
if(i != 0)
{
counter = 0;
for(loop = i; loop > start; loop--)
{
if((counter == 0) && (buffer[loop] == 10))
{
continue;
}
line[counter] = buffer[loop];
counter++;
}
line[counter] = 0;
start = i;
printf("%s\n",line);
}
}
}
if(i > start)
{
counter = 0;
for(loop = i; loop > start; loop--)
{
if((counter == 0) && ((buffer[loop] == 10) || (buffer[loop] == 0)))
{
continue;
}
line[counter] = buffer[loop];
counter++;
}
line[counter] = 0;
printf("%s\n",line);
return;
}
}
int main()
{
FILE *fp = fopen("./1.txt","r");
readfileinreverse(fp);
return 0;
}
Maybe , The does the trick , It reverse content of the file in whole
just like a string
Define a variable of type string with size of your file
Get Contents of the file and store in the variable
Use strrev() to reverse the string.
You can later on display the output or even write it to a file. The code goes like this:
#include <stdio.h>
#include <String.h>
int main(){
FILE *file;
char all[1000];
// give any name to read in reverse order
file = fopen("anyFile.txt","r");
// gets all the content and stores in variable all
fscanf(file,"%[]",all);
// Content of the file
printf("Content Of the file %s",all);
// reverse the string
printf("%s",strrev(all));
fclose(file);
return 0;
}
I know this question has been awnsered, but the accepted awnser does not contain a code snippet and the other snippets feel too complex.
This is my implementation:
#include <stdio.h>
long file_size(FILE* f) {
fseek(f, 0, SEEK_END); // seek to end of file
long size = ftell(f); // get current file pointer
fseek(f, 0, SEEK_SET); // seek back to beginning of file
return size;
}
int main(int argc, char* argv[]) {
FILE *in_file = fopen(argv[1], "r");
long in_file_size = file_size(in_file);
printf("Got file size: %ld\n", in_file_size);
// Start from end of file
fseek(in_file, -1, SEEK_END); // seek to end of file
for (int i = in_file_size; i > 0; i--) {
char current_char = fgetc(in_file); // This progresses the seek location
printf("Got char: |%c| with hex: |%x|\n", current_char, current_char);
fseek(in_file, -2, SEEK_CUR); // Go back 2 bytes (1 to compensate)
}
printf("Done\n");
fclose(in_file);
}

Resources