C - Printing Bin. File In Weird Symbols - c

I created a function that is successfully reading the binary file but it is not printing as I wanted.
The function:
void print_register() {
FILE *fp;
fp = fopen("data.bin", "rb");
if (fp == NULL) {
error_message("Fail to open data.bin for reading");
exit(0);
}
reg buffer;
while (EOF != feof(fp)) {
fread(&buffer, sizeof(reg), 1, fp);
printf("%s %d %d\n", buffer.name, buffer.age, buffer.id);
}
fclose(fp);
}
Note: reg is a typedef for a struct:
typedef struct registers reg;
struct registers {
char name[30];
int age;
int id;
char end;
};
Function for writing the file:
void register_new() {
system("clear");
reg buffer;
FILE *fp;
fp = fopen("data.bin", "ab");
if (fp == NULL) {
error_message("Error opening file data.bin");
exit(0);
}
write_register(buffer);
fwrite(&buffer, sizeof(reg), 1, fp);
fclose(fp);
}
Posting a printscreen of what was print to be more helpful:
As you can see on image, after the "p" (command for printing) is where should be the name, age and id of the struct.

In register_new(), you have to send the address of buffer in order for write_register() to work properly (right now you're giving it a copy of buffer).
Replace:
write_register(buffer);
with:
write_register(&buffer);
Then correct write_register to take and work with an address instead of a structure.
This might help you understand what's going on: http://fresh2refresh.com/c-programming/c-passing-struct-to-function

Your reading loop is incorrect. Don't use feof(), it can only tell is you have reached the end of file after a read attempt failed and it might not return EOF anyway, it is only specified as returning 0 or non 0. Use this instead:
while (fread(&buffer, sizeof(reg), 1, fp) == 1) {
printf("%s %d %d\n", buffer.name, buffer.age, buffer.id);
}
fread returns the number of items successfully read. Here you request to read 1 item of size sizeof(reg), if the item was read successfully, fread will return 1, otherwise it will return 0 (in case of a read error or end of file reached).
Your screenshot shows a syntax error, which you seem to have fixed now. Remove that, it is not helping.
In your function register_new, you are writing an uninitialized structure reg to the file, no wonder it does not contain anything useful when you read it back from the file. And for what it is worth, opening this file in binary mode is the correct thing to do since it contains binary data, namely the int members of the structure.
The reg passed to fwrite is indeed uninitialized. write_register gets a copy of this uninitialized structure by value, and probably modifies this copy, but this does not affect the local structure in register_new. You should modify write_register() to take a pointer to the structure. Unlike C++, there is no passing by reference in C.

Related

how check successfully write after invoke fwrite function in C?

I find this code in a website:
struct person
{
int id;
char fname[20];
char lname[20];
};
int main ()
{
FILE *outfile;
// open file for writing
outfile = fopen ("person.dat", "w");
struct person input1 = {1, "rohan", "sharma"};
// write struct to file
fwrite (&input1, sizeof(struct person), 1, outfile);
if(fwrite != 0)
printf("contents to file written successfully !\n");
return 0;
}
Is line if(fwrite != 0) correct?
Does we can compare function name itself(fwrite)?
What is value of fwrite in this case?
No, that's definitely not the correct way to do it. The correct way is this:
if(fwrite(&input1, sizeof(struct person), 1, outfile)) != 1) {
/* Error writing */
}
But in order to avoid duplicate magic numbers, this would be better:
size_t num = 1;
if(fwrite(&input1, sizeof(struct person), num, outfile)) != num) {
I find it hard to believe ANY site would publish rubbish code like that. I knew geeksforgeeks isn't very trustworthy, but this was incredibly bad. It's wrong on so many levels.
if(fwrite != 0) is a completely pointless check. If fwrite != 0 would evaluate to false, it would mean that the function call to fwrite would fail. The check basically means "Is fwrite a null pointer?" And if a library function is a null pointer, then something is REALLY wrong.
fwrite returns the number of elements written, which in this case should be one element.
I wrote a rant about Tutorialspoint earlier, but now I need to add geeksforgeeks to my list of resources I recommend to stay far, far away from.

What empty binary files contain in C

#include <stdio.h>
#include <stdlib.h>
int main(void) {
FILE *fp;
fp = fopen("clients.dat", "wb");
fclose(fp);
fp = fopen("clients.dat", "rb");
while (1) {
if (fp == EOF)
break;
else
printf("There is something inside a file");
}
fclose(fp);
return 0;
}
Here comes a question: what do empty binary files contain? should the pointer point to the EOF character? I mean: isn't it that the first and last thing in the file is EOF? OR how Can I check whether a file is empty or not?
An empty file contains nothing, it is empty. So it contains 0 bytes. EOF is not a character that is at the end of a file, it is an integer constant used as return value from some of the standard methods reading from a file to indicate end of file or some sort of error.
When you open a file you get a pointer to a FILE type back, this is what you can expect even from an empty file.
A file is not terminated the same way a string is, so there is no equivalent of a NULL character in a file, that determines when the file contents stops.
To determine whether a file you have opened and have a valid FILE pointer to is empty you can use fseek and ftell:
fseek(fp, 0, SEEK_END);
size = ftell(fp);
if (size == 0) {
// File is empty
}
Function fopen returns a pointer to a file handle of type FILE, not a pointer to any content of the file or a pointer to an EOF-character. The pointer is NULL if the file could not be opened at all, but does not indicate whether the file is empty or not.
To check if a file is empty you either (1) need to make an attempt to read bytes and handle the various results, or (2) to use fseek and ftell to move the read pointer to the end and ask then for the position.
(1)
fp=fopen("clients.dat","rb");
char buffer;
size_t bytesRead = fread(&buffer, 1, 1, fp); // try to read one byte
if(bytesRead == 1) {
printf("file contains at least one byte\n");
} else { // error handling
if (feof(fp))
printf("Attemt to read though end of file has been reached. File is empty.\n");
else if (ferror(fp)) {
perror("Error reading file.");
}
}
(2)
fp=fopen("clients.dat","rb");
fseek(fp, 0L, SEEK_END);
long size = ftell(fp);
if (size==0) {
// file is empty.
}
I'd prefer the second variant.
Here's another approach:
To check if the file is empty, you can simply read the file:
int c = fgetc(fp);
if (c == EOF)
{
// The file is empty or an error occured
if (feof(fp))
{
// Empty
}
else
{
// Error during file read
}
}
else
{
// non-empty file
}
Here comes a question what empty binary files contain ?
Empty files contain nothing, that is what makes them empty.
Regular files have a size which is not part of their data, but instead is normally a part of the directory entry or inode.
should the pointer point to the EOF character ?
No
First of all the pointer returned by fopen is NOT a pointer to the content of the file, but merely a pointer to a data structure describing the open file.
Secondly EOF is not an actual part of the file, but a special return value from the getc family of functions used to indicate that the end of file has been reached.
To test whether you are at the end of a file without reading from it you can use the feof function.

How to fix &localtime in .txt - C

I want to implement a function in my program that sends a .txt to my email with some tasks that i have to do in the day. Here's the code:
void txtCreator(){
/**file.dat and file.txt, respectively**/
FILE *fp, *fp1;
/**struct that contain the events**/
struct evento *display = (struct evento *)malloc(sizeof(struct evento));
char buffer[48];
char email_events[] = {"dd_mm.txt"};//filename.txt
char msg[]={"Nao ha eventos disponiveis para hoje!\n"};
int count=0;
time_t rawtime;
time(&rawtime);
struct tm timenow = *localtime(&rawtime);
strftime(buffer, 48, "%d_%m", &timenow);
fp = fopen(file_name, "rb");
fp1 = fopen(email_events, "w");
if(strcmp(buffer, email_events)!=0){
strcpy(email_events, buffer);
while(fread(display, sizeof(struct evento), 1, fp)==1){
if (feof(fp) || fp==NULL){
break;
}
else if(display->dia==timenow.tm_mday && display->mes==timenow.tm_mon+1){
fwrite(display, sizeof(struct evento), 1, fp1);
fprintf(fp1, "%s", "\n");
count++;
}
}
}
if(count==0){
fprintf(fp1, "%s", msg);
}
fclose(fp);
fclose(fp1);
}
Everything is working just fine, but there's two problems:
1-
strcpy(email_events, buffer);
is not working, and:
2-
when i create the .txt file, it shows like that:
test ¹0(¹€(.v™ ™­ °'¹8¹uguese_Brazil.12
it shows the event name (test) correctly, but the date is not working.
I've tried a lot of things, but nothing works.
Sorry for the bad english, not my native language.
when i create the .txt file, it shows like that:
test ¹0(¹€(.v™ ™­ °'¹8¹uguese_Brazil.12
Let's address this first: you're not writing text to your .txt file. You're writing a struct. It's going to look like garbage.
For example, let's say display->dia is 19. This means the number 19 will be written to the file, not the text 19, the number 19. Read as text, 19 is garbage. 10 is a newline. 65 is A.
If your intent is to dump the structs into a file, assuming struct evento has no pointers, you're good. In fact you probably shouldn't add a newline, it will interfere with reading the file by the size of the struct.
If your intent is to produce a human readable text file, you need to translate each piece of the struct into text. For example, if you wanted to write the day and month as text...
fprintf(fp1, "%d_%d", display->dia, display->mes);
I'll assume that going forward.
strcpy(email_events, buffer); is not working
At first glance it looks like your strcpy is backwards, it's strcpy(src, dest) and presumably you want to copy email_events into buffer: strcpy(buffer, email_events).
Looking further, your code does nothing with either buffer nor email_events after that. The strcpy is pointless.
Going even further, buffer is the month and day like 07_19. email_events is always dd_mm.txt. Those will never match. strcmp(buffer, email_events)!=0 will always be true making the if check pointless.
I'm not sure what the intent of buffer and email_events are, but it appears to be trying to create a filename based on the current date? This can be done much simpler with one better named variable outfile.
time_t rawtime;
time(&rawtime);
struct tm timenow = *localtime(&rawtime);
char outfile[20];
strftime(outfile, 20, "%d_%m.txt", &timenow);
Moving along to other problems, you don't check that fp1 opened.
You do eventually check fp but you check it after you've already read from a possibly null file pointer. If you're compiling with an address sanitizer (which you should) it will cause an error. Causing an error when using a null pointer is good, it will solve many a mystery memory problem for you.
It's much easier and robust and address sanitizer friendly to check immediately. We can also do a better job naming them to avoid confusing the input from the output: in and out.
FILE *in = fopen(file_name, "rb");
if( in == NULL ) {
perror(file_name);
exit(1);
}
And since you're reading binary with rb you should be writing binary you should be using wb. This only matters on Windows, but might as well be consistent.
FILE *out = fopen(outfile, "wb");
if( out == NULL ) {
perror(outfile);
exit(1);
}
There's no need to check feof(fp), while(fread(display, sizeof(struct evento), 1, fp)==1) will already exit the loop at end of file when it fails to read. In general, explicitly checking for the end of file leads to subtle problems.
The read/write loop is now much simpler.
while(fread(display, sizeof(struct evento), 1, in)==1){
if(display->dia==timenow.tm_mday && display->mes==timenow.tm_mon+1) {
fprintf(out, "%d_%d\n", display->dia, display->mes);
count++;
}
}
Putting it all together...
void txtCreator(){
const char *no_events_found_msg = "Nao ha eventos disponiveis para hoje!\n";
// No need to cast the result of malloc, it just invites mistakes.
struct evento *display = malloc(sizeof(struct evento));
// Generate the output filename directly, no strcmp and strcpy necessary.
time_t rawtime;
time(&rawtime);
struct tm timenow = *localtime(&rawtime);
char outfile[20];
strftime(outfile, 48, "%d_%m.txt", &timenow);
// Immediatetly make sure the files are open and error immediately.
FILE *in = fopen(file_name, "rb");
if( in == NULL ) {
perror(file_name);
exit(1);
}
FILE *out = fopen(outfile, "wb");
if( out == NULL ) {
perror(outfile);
exit(1);
}
// Now that we know the files are open, reading and writing is much simpler.
int count=0;
while(fread(display, sizeof(struct evento), 1, in)==1){
if(display->dia==timenow.tm_mday && display->mes==timenow.tm_mon+1) {
fprintf(out, "%d_%d\n", display->dia, display->mes);
count++;
}
}
if(count==0){
fprintf(out, "%s", no_events_found_msg);
}
fclose(in);
fclose(out);
}
Note that I've used a style which declares variables in place. This makes the code easier to read, limits the scope of each variable, and it avoids declaring variables which you never use.
Assuming that you are meaning to copy email_events into your buffer (since you assigned a static string), your strcpy parameters are backwards.
Below is the declaration of strcpy
char *strcpy(char *dest, const char *src);
You probably meant:
strcpy(buffer, email_events);

can't access a place in memory

I'm trying to read a binary file of 32 bytes in C, however I'm keep getting "segmentation fault (code dumped)" when I run my program,
it would be great if somebody can help me out by pointing where did I go wrong?.
my code is here below:
int main()
{
char *binary = "/path/to/myfiles/program1.ijvm";
FILE *fp;
char buffer[32];
// Open read-only
fp = fopen(binary, "rb");
// Read 128 bytes into buffer
fread (buffer, sizeof(char), 32, fp);
return 0;
}
It's because of the path. Make sure that "/path/to/myfiles/program1.ijvm" points to an existing file.
You should always check the return value of fopen.
\\Open read-only
fp = fopen(binary, "rb");
if(fp==NULL){
perror("problem opening the file");
exit(EXIT_FAILURE);
}
Notice also that you are reading 32 bytes in your buffer and not 128 as your comment says.
You must check the return result from fopen().
I'm assuming you are getting the segfault in the fread() call because your data file doesn't exist, or couldn't be opened, and you are trying to work on a NULL FILE structure.
See the following safe code:
#include <stdio.h>
#include <stdint.h>
#define SIZE_BUFFER 32
int main()
{
char *binary = "data.txt";
FILE *fp = NULL;
char buffer[SIZE_BUFFER];
// Open read-only
fp = fopen(binary, "rb");
// Read SIZE_BUFFER bytes into buffer
if( fp )
{
printf("Elements read %ld\n", fread (buffer, sizeof(char), SIZE_BUFFER, fp));
fclose(fp);
}
else
{
// Use perror() here to show a text description of what failed and why
perror("Unable to open file: ");
}
return 0;
}
When I execute this code it doesn't crash and will print the number of elements read if the file is opened or it will print "Unable to open file" if the file could not be opened.
As mentioned in the comments you should also close the file being exiting. Another thing you can do is the following:
FILE *fp = fopen(.....);
Instead of declaring and assigning in two separate steps.
There are two possible reasons
The fopen(3) function failed due to some reason, which means fp is NULL, and then you are trying to use the null-pointer in fread(3). This can crash. #OznOg has already given a subtle hint to look into this direction.
If the fopen call is a success (i.e. fp is non-NULL after calling fopen), the code can still crash because you are reading 32 chars into the variable binary, while binary has been initialized with only 30 chars.

how can I save struct in file .... C lang

I'd like to save a struct in a file.
I'd like to realize a function which makes this work.
I tried this code but it didn't work.
struct utilisateur // enregestrement pour sauvegarder les details de l utilisateur
{
char nom[20];
char prenom[20];
int place;
char depart[20];
char arrive[20];
char sexe;
int nwagon;
};
struct utilisateur utilis;
struct utilisateur *Table[48];
void crea_fich(struct utilisateur *Tutilis)
// creation un fichier, vous introduiez le nom, et le sotcker par enreg
{
FILE *f;
if (f!==0)
{
printf("error in the name of file \n");
exit(1);
}
if (f=fopen(futilis,"w")==Null){
fprint("We can't creat file \n");
exit(1);
}
else{
f=fopen("futilis.dat","wb");
fwrite(Tutilis ,sizeof(utilisateur),1,f);
}
}
No. You need to write out your data members individually, one at a time. You should not just blindly copy the memory representation of your struct into the file output buffer (which it is clear you are trying to do). Writing files that way will cause the files to non-portable (they won't be readable except on the platform that they were written), because of the endian-ness and the platform-specific padding of the struct elements.
Try this, and then if that's not doing what you want, try explaining how it differs from what you want.
void crea_fich(struct utilisateur *Tutilis)
{
FILE *f;
size_t nwritten;
f = fopen("futilis.dat","wb");
if (f == NULL)
{
fprintf(stderr, "Cannot open file for writing.\n");
exit(1);
}
nwritten = fwrite(Tutilis, sizeof Tutilis[0], 1, f);
fclose(f);
if (nwritten < 1)
{
fprintf(stderr, "Writing to file failed.\n");
exit(1);
}
}
Michael S is right; using fwrite with a struct is wildly nonportable. But let's assume you don't care about that and you want something easy to write that will work.
The problem in your code is that you've broken the Golden Rule of sizeof: never use sizeof with a type name. Instead you should use sizeof with an lvalue, and almost always with the dereference of another argument. Thus
Tutilis = malloc (sizeof (*Tutilis));
...
fwrite(Tutilis, sizeof (*Tutilis), 1, f);
If you follow this recipe it's much harder to get the size wrong.
Just a simple example :)
// your struct
struct Data
{
int first;
double second;
char third[10];
};
Then write the struct!
struct Data data = {22, 4.0, "Hi"};
FILE* output;
output = fopen("Data.dat", "wb");
fwrite(&data, sizeof(data), 1, output);
fclose(output);
Finally read the data from the file you created!
struct Data data;
FILE* input;
input = fopen("Data.dat", "rb");
fread(&data, sizeof(data), 1, input);
// you got the data from the file!
fclose(input);
Binary files are nightmares if not written and read wisely. You have to take care of a lot of things about the architecture where the file was created and where will it be read. Endianess and size of variables are the most important. Also, If you have pointers inside your struct, the pointer that will be written to the file not the actual data where the pointer points to. Sorry, I didn't edit your code because it is full of compilation errors :)
I deleted my first answer because it was so wrong, sorry :)
I realize this is an old post, but it comes up when people search for this information, so I'll give my own solution.
This is basically what I have used in one of my games. I actually have some extra library specific code in my own function for dialogs, but this is essentially it. I write data individually. I don't think I have a struct for this data, but there is no difference, just write your individual struct members separately. As mentioned, it's better this way.
// returns 1 if successful, 0 if not
int savemap(const char *map_name)
{
FILE *file = NULL;
// open the file in write binary mode
file = fopen(map_name, "wb");
// always check return values to see if it was opened okay
if(file == NULL) {
fprintf(stderr, "Error opening file for writing.\n");
return 0;
}
// write file ID, version and pills
fwrite(MAP_ID, sizeof(char), strlen(MAP_ID)+1, file);
fwrite(&MAP_VER, sizeof(unsigned char), 1, file);
fwrite(&pills, sizeof(unsigned short), 1, file);
// write the map data (unsigned int map[315])
fwrite(&map, sizeof(unsigned int), 315, file);
// never forget to close the file
fclose(file);
return 1;
}
I'd look over the symbol names first, like NULL and fprint, not to mention that weird \0. As an additional thought, you should close the file after writing to make sure it gets flushed to disk, and double check that futilis variable is a char* that contains a valid, writeable path.

Resources