Opening binary files in C - c

I'm trying to open a binary file and read the contents for a class assignment. Even after doing research, I'm having trouble getting anything to appear while attempting open and prints contents of a binary file. I'm not even sure what I should be getting, how to check that it's right but I know that nothing (which is what I'm currently getting) is bad. Here's the code I got from searching on this site
#include<stdio.h>
int main()
{
FILE *ptr_myfile;
char buf[8];
ptr_myfile = fopen("packets.1","rb");
if (!ptr_myfile)
{
printf("Unable to open file!");
return 1;
}
fread(buf, 1, 8, ptr_myfile);
printf("First Character: %c", buf[0]);
fclose(ptr_myfile);
return 0;
}
When this prints, I get "First Character: " with nothing else printed. Maybe it doesn't print normally in terminal? I'm not sure, any help would be greatly appreciated, thanks

If it's a binary file, it's very likely that its contents don't print particularly well as text (that's what makes a binary a binary file). Instead of printing as characters try printing as hexadecimal numbers:
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
int main()
{
FILE *ptr_myfile;
char buf[8];
ptr_myfile = fopen("packets.1","rb");
if (!ptr_myfile)
{
printf("Unable to open file!");
return 1;
}
size_t rb;
do {
rb = fread(buf, 1, 8, ptr_myfile);
if( rb ) {
size_t i;
for(i = 0; i < rb; ++i) {
printf("%02x", (unsigned int)buf[i]);
}
printf("\n");
}
} while( rb );
fclose(ptr_myfile);
return 0;
}

First, you need to check how much data you have in the buffer. fread returns length; if it is zero, accessing buf[0] is not legal.
Not all characters are printable You can see what data you are getting if you print the character code of c, rather than c itself. Use %d for that.
size_t len = fread(buf, 1, 8, ptr_myfile);
if (len != 0) {
printf("First Character: '%c', code %d", buf[0], buf[0]);
} else {
printf("The file has no data\n");
}

Related

C: writing content of array to txt file

im trying to implement the number guessing game. The game itself works fine. But now I want to add a function which safes the score of the last game (Number of trys and guessed number) in the leaderboard.txt file.
I haven't finished the saveScore method yet, I don't need help with implementing the rest. I wan't to read the data from the file, add the new line and sort it from least to most trys. But I only wan't to save the top 10 of all time.
I need some help to get the following code running. One problem is the code doesn´t even terminate.
I think all the problems are within the saveScore method. (line 18 -25)
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define max_length 300
void saveScore(int guess, int randNumber) {
FILE *datei;
datei = fopen("leaderboard.txt", "wb");
char lines[max_length];
char leaderboard[10][max_length];
int line = 0;
while (fgets(leaderboard[line], sizeof(lines), datei) != NULL){
line++;
}
leaderboard[line][max_length] = ("%d, %d", guess, randNumber);
fwrite(leaderboard, sizeof(char), sizeof(leaderboard), datei);
fclose(datei);
}
void startGame(){
int guess = 1;
int randNumber;
int uInput;
randNumber = (rand()%100)+1;
printf("%d", randNumber);
do {
printf("Guess the number between 1-100: \n");
scanf("%d", &uInput);
if (uInput < randNumber){
printf("the number you are looking for is higher.\n");
}
else if (uInput > randNumber){
printf("the number you are looking for is lower.\n");
}
else {
printf("Jackpot it was your %d. try.", guess);
}
guess++;
} while (randNumber != uInput);
saveScore(guess, randNumber);
char playAgain = 'j';
printf("Try Again (j/n): \n");
scanf(" %c", &playAgain);
if (playAgain == 'j') {
startGame();
}
printf("Thank you for playing.");
}
int main() {
srand(time(NULL));
startGame();
return 0;
}
I appreciate any help.
Best Enno
This loop has the problem of being able to overflow leaderboard if line ever reaches 10.
while (fgets(leaderboard[line], sizeof(lines), datei) != NULL){
line++;
}
This line
leaderboard[line][max_length] = ("%d, %d", guess, randNumber);
has a few problems. [max_length] would be one past the end of the buffer, but with that said, it is not needed and the assignment as a whole is incorrect. To perform string interpolation, use a function such as sprintf.
Aside from the fact that you only open the file for writing, the primary problem is that
fwrite(leaderboard, sizeof(char), sizeof(leaderboard), datei);
will write the entire contents of leaderboard to the file. This includes the garbage values that exist towards the end of each array, after each string. fgets will then read those garbage values later.
You should stick to reading and writing binary or text, but do not mix them. If you use fgets, use fputs (or similar) to write the text. Conversely, if you use fwrite, use fread to read the binary data.
Here is a basic, cursory snippet using text functions, where we:
open the file for reading
read our lines into the array
close the file
add our new score to the array
sort our array using qsort
open the file for writing
write our lines
close the file
The trick here is leaderboard has an additional slot, so that there is always room for our newest score. After sorting, we only write at most MAX_ENTRIES entries to the file, meaning if the array is full we ignore the worst score.
#define MAX_ENTRIES 10
#define MAX_LENGTH 300
#define SAVE_FILE "leaderboard.txt"
int compare(const void *ap, const void *bp) {
const char (*a)[MAX_LENGTH] = ap;
const char (*b)[MAX_LENGTH] = bp;
int av, bv;
sscanf(*a, "%d", &av);
sscanf(*b, "%d", &bv);
return (av > bv) - (av < bv);
}
void saveScore(int guess, int randNumber) {
char leaderboard[MAX_ENTRIES + 1][MAX_LENGTH] = { 0 };
size_t entries = 0;
FILE *file = fopen(SAVE_FILE, "r");
if (file) {
while (entries < MAX_ENTRIES &&
fgets(leaderboard[entries], sizeof *leaderboard, file))
entries++;
fclose(file);
}
sprintf(leaderboard[entries], "%d %d\n", guess, randNumber);
entries++;
qsort(leaderboard, entries, sizeof *leaderboard, compare);
file = fopen(SAVE_FILE, "w");
if (file) {
for (size_t i = 0; i < entries && i < MAX_ENTRIES; i++)
fputs(leaderboard[i], file);
fclose(file);
}
}

Trying to add a text file into an array in C

I am trying to take 500 numbers in this text file and store them into an array, it keeps giving me random numbers that aren't in my text file at all. I've also changed a few things and it is saying that there is conflicting types for my fp_read
#include<stdio.h>
int ch;
int X[500];
FILE*fp_read = NULL;
fp_read = fopen("random_numbers.txt","r");
int main()
{
for(i=0;i<499;i++)
{
if(ch==EOF)
{
printf("End of File\n");
}
else
{
ch = (fgetc(fp));
X[i]=ch;
printf("%d,"X[i]);
}
}
return 0;
}
sorry for the quick answer but try to use atoi or strtol to convert the character to integer or add -48 because '0' in ascii is 48
You are interpreting the character codes of the digits used to encode the textual numbers, which is probably not at all what you want. For instance in UTF-8 the number "12" consists of the two code points 1 and 2, which encode as the two 8-bit values 49 and 50.
For line-based input, it's almost always best to read whole lines into a suitably large buffer, then parse that. That is more robust than parsing the stream itself.
Something like:
#include <stdio.h>
#include <stdlib.h>
int main()
{
FILE * const fp = fopen("random-numbers.txt", "rt");
if(fp == NULL)
{
fprintf(stderr, "**File open failed\n");
exit(1);
}
int numbers[500];
int index = 0;
char line[1024];
while(fgets(line, sizeof line, fp) != NULL)
{
if(index >= sizeof numbers / sizeof *numbers)
break;
numbers[index++] = (int) strtol(line, NULL, 10);
}
printf("Read these numbers:\n");
for (int i = 0; i < index; ++i)
printf("%d: %d\n", i, numbers[i]);
return 0;
}

Loop Problem while reading a text file in C

Hi guys i wanna read a text file word by word and count the words while doing it and then pass the words and numbers to my linked list.
But i have a loop problem. I can't escape from the infinite loop.
Here is my code:
int main()
{
char kelime[100];
char kelime2[100];
long a = 0;
FILE * dosya = fopen("oku.txt", "r");
while(1)
{
fseek(dosya,a,SEEK_CUR);
if(feof(dosya))
{
break;
}
while(fscanf(dosya, "%99[^ \n]", kelime) == 1)
{
printf("%s \n",kelime);
a = ftell(dosya);
}
while(1)
{
fscanf(dosya, "%s" , kelime2);
printf("%s \n",kelime2);
if((strcmp(kelime, kelime2))== 0)
{
// Things to do...
}
memset(kelime2,0,sizeof(kelime2));
if(feof(dosya))
{
rewind(dosya);
break;
}
}
}
fclose(dosya);
return 0;
}
To read any kind of space-delimited word, all you need is something like:
while (fscanf(dosya, "%99s", kelime) == 1)
{
// Do something with the "word" in kelime
}
The scanf family of functions all return the number of conversions it successfully made. With a single conversion specifier it can only return 1 on success, 0 if the specifier could not be matched (should never happen in this case) or -1 on error or end of file.
The loop will simply read all words in the input file until the end of the file.
Putting it together in a program that reads and print all words, it would look something like this:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
FILE *dosya = fopen("oku.txt", "r");
if (dosya == NULL)
{
perror("Could not open file");
return EXIT_FAILURE;
}
char kelime[100];
size_t counter = 0;
while (fscanf(dosya, "%99s", kelime) == 1)
{
printf("Read word #%zu: %s\n", ++counter, kelime);
}
fclose(dosya);
printf("There was a total of %zu \"words\" in the file\n", counter);
}
A little explanation for the %zu format specifier for printf:
The u is the base format (it's really %u), and stands for unsigned integer. The z prefix tells printf that the corresponding argument is really a size_t value.
The type size_t is a standard C type that is used for all kinds of sizes, counters and indexes. It's an unsigned integer of unspecified size.

Reading hex value from image in C

I'm trying to read the hex values from an image file using C. In Linux, this code works fine, but with Windows it reads only the first 334 bytes and I don't understand why.
The code to read the file is:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
void readHexFile(char* path) {
FILE *fp;
if ((fp = fopen (path, "r")) != NULL) {
struct stat st;
stat(path, &st);
int i;
int ch;
for (i = 0; i < st.st_size; i++) {
ch = fgetc(fp);
printf("%x ", ch);
}
fclose(fp);
}
else {
return NULL;
}
}
st.st_size comes from <sys/stat.h> package and contains the right value (the size, in bytes, of the image file)
This image show what my program outputs, and the actual binary content of the file it is reading:
As you see after the sequence of 17, 18, 19 there is also hex values but my program prints ffffffff repeatedly.
You opened the file in a text mode, and not as binary. Different platforms may behave differently.
In this case, Microsoft Windows decided that this plain text file ends at the first occurrence of Ctrl+Z (0x1A), and returns EOF for all fgetc afterwards.
Explicitly state that you want to open the file as binary:
fp = fopen ("yourfile", "rb");
and the problem goes away.
I think your loop should look like this:
int ch;
while (!feof(fp)) {
ch = fgetc(fp);
printf("%x ", ch);
}
It's completely unclear to me why you are using st.st_size here.
On Windows, the character 0x1A (Ctrl+Z) is the EOF character for text mode; see this question.
If you're reading from a binary file like a JPEG, you should do so with first opening the file as binary (fopen mode "rb"), then fread into a pre-allocated buffer, the size of which you would determine with ftell with the file pointer at the end of the file:
size_t i, len;
char *buffer = NULL;
fp = fopen(argv[1], "rb");
if(!fp)
// handle error
fseek(fp, 0, SEEK_END);
len = ftell(fp);
rewind(fp);
buffer = malloc(len + 1);
if(!buffer)
// handle error
fread(buffer, 1, len, fp);
for(i = 0; i < len; i++)
{
printf("%.2X ", buffer[i]);
}
free(buffer);
buffer = NULL;

Binary Translation

#include <stdio.h>
int main() {
unsigned char data[1];
FILE *f = fopen("bill.jpg", "rb");
while (!feof(f)) {
if (fread(data, 1, 1, f) > 0) {
printf("0x%02x\n", data[0]);
}
}
fclose(f);
}
Is this the right? I am worried because if I view the file using hexdump, I get completely different output.
That should correctly print the first byte of the file in hex.
Check the documentation for the Hexdump utility used, or tell us which platform is being used. Some dump utilities display the bytes in reverse order on each line to make little-endian reading somewhat more intuitive—once you understand what it is doing.
I'm sorry, but no -- while (!feof(f)) is essentially always wrong -- it'll typically appear to read the last item in the file twice. Here's a reasonably usable hex dumper I wrote a few years ago:
/* public domain by Jerry Coffin, tested with MS C 10.0 and BC 4.5
*/
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv) {
unsigned long offset = 0;
FILE *input;
int bytes, i, j;
unsigned char buffer[16];
char outbuffer[60];
if ( argc < 2 ) {
fprintf(stderr, "\nUsage: dump filename [filename...]");
return EXIT_FAILURE;
}
for (j=1;j<argc; ++j) {
if ( NULL ==(input=fopen(argv[j], "rb")))
continue;
printf("\n%s:\n", argv[j]);
while (0 < (bytes=fread(buffer, 1, 16, input))) {
sprintf(outbuffer, "%8.8lx: ", offset+=16);
for (i=0;i<bytes;i++) {
sprintf(outbuffer+10+3*i, "%2.2X ",buffer[i]);
if (!isprint(buffer[i]))
buffer[i] = '.';
}
printf("%-60s %*.*s\n", outbuffer, bytes, bytes, buffer);
}
fclose(input);
}
return 0;
}

Resources