C: Writing and Reading a string to and from a binary file
You are doing wrong while reading.
you have put the & for the pointer variable that's why it gives segmentation fault.
I removed that it works fine and it returns Hello correctly.
int count = fread(drumReadString, sizeof(char), stringLength, fp);
How to write inputs into a binary file and read it in c?
I was wrong at writing into bin file and also reading from it.
First of all I need to thank to @lulle.
- As he mentioned in comments I changed
char*
in struct intochar
arrays.
char initials[80], name[250], email[100], acc_type[25];
And I also change file mode. I use
ab
to writing snippet. Andrb
in reading snippet.And I changed my writing snippet.
Here I looped over 12 times, this wrote every record 12 time. Sad ah?
This happened because I used just address of struct &new_acc
in fwrite
. If you use just address of a struct in fwrite`` or
fread``` it will write your whole struct. That's what happened to me. I wrote the whole struct 12 time.
for (int i = 0; i <= 12; ++i) // Looping 12 times
fwrite(&new_acc, sizeof(new_acc), 1, fp); // writting to file
So instead of looping I changed it into this
fwrite(&new_acc, sizeof(new_acc), 1, fp); \\ This line will write whole struct
But if you want to use members of struct instead of a whole struct, you are free to use a loop. Here is a example. This example is same as above one. But remember to use i
or any variable that you used in for
loop when writing to file. Instead of i
, if you used member name, It will also write 12 times (or as far as you are looping...)
for (int i = 0; i <= 12; ++i) // Looping 12 times
fwrite(&new_acc.[i], sizeof(new_acc.[i]), 1, fp); // writting to file
- And the same thing happened to reading part (I guess...).
So I changed the code snippet like below
FILE *fp;
fp = fopen("employees", "rb");
if (fp == NULL)
puts("Cannot open a file...");
int i = 0;
while(fread(&new_acc, sizeof(new_acc), 1, fp) != 0){ /* use fread one time */
printf("%d\n", new_acc.acc_num);
printf("%s\n", new_acc.name);
printf("%s\n", new_acc.initials);
printf("%s\n", new_acc.birth_day);
printf("%s\n", new_acc.address);
printf("%d\n", new_acc.phone);
printf("%s\n", new_acc.id_num);
printf("%s\n", new_acc.occupation);
printf("%s\n", new_acc.email);
printf("%s\n", new_acc.acc_type);
printf("%d\n", new_acc.balance);
++i;
}
fclose(fp);
Writing strings to binary files in C
This code is incorrect:
char *str;
fread(str, 6, 1, fp);
printf("Got str: %s\n", str);
char *str;
creates an uninitialized character pointer. Where's the memory that it points to?
char str[ 7 ];
fread(str, sizeof( str ) - 1, 1, fp);
str[ sizeof( str ) - 1 ] = '\0';
printf("Got str: %s\n", str);
would be better, although it still doesn't check the return value from fread()
to ensure data is actually read.
c++ - properly writing std::string to binary file
Your code can be written as
ofstream file1("lastServers.bin", ios::out | ios::binary);
if (file1.good()) {
file1.write(ip.c_str(), ip.size());
file1.write(port.c_str(), port.size());
file1.close();
}
else {
std::cout << "file error write" << endl;
}
string::c_str() returns a const pointer to the text in the string.
string::size() returns the number of characters in the string.
You don't need to concatenate the data before writing to the file, writing one then the other has the same result.
If you wanted to write C type code rather than C++, you can use strlen(p_IP) to get the length of the IP string rather than using sizeof.
The sizeof operator gives you the size of the class instance, i.e. the size of the object BUT the string object's size is never affected by the size of the string it manages.
In C++, objects that manage something (think strings managing characters, containers managing their contents, etc.) usually have a method to determine the size of what they're managing. For std::string and other STL containers that method is size().
Note that writing these strings in this format means you can't tell where one string ends and another one starts. Two options to consider are using a terminating character that you know won't appear in any strings, or writing the length of the string to the file before the text of the string itself. I won't elaborate here as it was not asked in the original question.
C program reading and writing to binary files
The primary problem is with your open()
call. You are attempting to open the file as both read-only and write-only at the same time. From man 2 open:
The argument flags must include one of the following access
modes:O_RDONLY
,O_WRONLY
, orO_RDWR
.
Refactoring your code as follows works fine.
char data[100];
int fd = open ("gifts.dat", O_CREAT | O_WRONLY);
int n = 0;
if ((strcmp(argv[1],"new")) == 0) {
for (int i = 2; i < argc; i = i+2){
int number = atoi (argv[i+1]);
strcpy (data, argv[i]);
int length = strlen(data) + 1;
write (fd, &length, sizeof(int));
write (fd, data, length);
write (fd, &number, sizeof(int));
n++;
}
}
else{
printf("Not worked");
}
close (fd);
fd = open ("gifts.dat", O_CREAT | O_RDONLY);
for (int k = 0; k < n; k++){
int length;
char name[100];
int money;
read (fd, &length, sizeof(int));
read (fd, name, length);
read (fd, &money, sizeof(int));
printf("%10s: %.2d\n", name, money);
}
close (fd);
Example Use/Output
$ ./bin/readwrite_bin new patel 200 Ram 500
patel: 200
Ram: 500
Additionally, you must validate all opens, reads, writes (and close - after write) by checking the return of each call to ensure is succeeds, or handle any error if it fails. You should replace atoi()
with at minimum sscanf()
or better strtol()
as atoi()
provides zero error detection and will happily accept atoi ("my cow");
Let me know if you have further questions.
Writing/Reading strings in binary file-C++
When reading the data back in you should do something like the following:
int result;
file.read(reinterpret_cast<char*>(&result), sizeof(int));
This will read the bytes straight into the memory of result
with no implicit conversion to int. This will restore the exact binary pattern written to the file in the first place and thus your original int
value.
Writing in binary files C programming with spaces
The problem is in the way that you read the input. scanf()
will stop as soon as it meets a whitespace. As a result name
will store only "Ivan". fgets()
can come in handy here.
Change this:
scanf("%s",name);
to this:
fgets(name, sizeof(name), stdin); // read the line (including the newline from the user's enter hit
name[strlen(name) - 1] = '\0'; // overwrite the newline
and you should get this:
Georgioss-MacBook-Pro:~ gsamaras$ gcc -Wall main.c
Georgioss-MacBook-Pro:~ gsamaras$ ./a.out
Enter client's name:
Ivan Petrov Petrov
Ivan Petrov Petrov
after printing your string like this printf("%s\n", name);
.
Related Topics
Compiling a Win32 Gui App (Without a Console) Using Mingw and Eclipse
Structured Binding with [[Maybe_Unused]]
Set All Bytes of Int to (Unsigned Char)0, Guaranteed to Represent Zero
Counting the Number of Occurrences of a String Within a String
C Function Pointers with C++11 Lambdas
How to Support Both Ipv4 and Ipv6 Connections
Multiple Implicit Conversions on Custom Types Not Allowed
C++ Boost: What's the Cause of This Warning
Lifetime of Lambda Objects in Relation to Function Pointer Conversion
Member Fields, Order of Construction
Can't Modify Char* - Memory Access Violation
Using Bts Assembly Instruction with Gcc Compiler
Operator Overload Which Permits Capturing with Rvalue But Not Assigning To
C++ Visual Studio "Non-Standard Syntax; Use '&' to Create a Pointer to Member"