I wrote a program to test writing a char[128] array to file using write() function in C. The following is my code, however, after writing, I can see that the string "testseg" is followed by a "d" or "È" in the testFile.txt file. Is this a proper way of writing char[] array to file?
int main()
{
char pathFile[MAX_PATHNAME_LEN];
sprintf(pathFile, "testFile.txt");
int filedescriptor = open(pathFile, O_RDWR | O_APPEND | O_CREAT, 0777);
int num_segs = 10;
int mods = 200;
const char *segname = "testseg"; /* */
char real_segname[128];
strcpy(real_segname, segname);
write(filedescriptor, &num_segs, sizeof(int));
write(filedescriptor, real_segname, strlen(real_segname));
printf("real_segname length is %d \n", (int) strlen(real_segname));
write(filedescriptor, &mods, sizeof(int));
close(filedescriptor);
return 0;
}
...writing a char[128] array to file ...I can see that the string "testseg" ...
is a contradiction.
In C, a string is an array of char followed by and including a '\0' and
a char[128] is a fixed 128 char in length.
When code does write(filedescriptor, real_segname, strlen(real_segname));, it does neither. It is not writing a C string, 7 char of "testseg" terminated with a '\0'. Instead it just wrote the 7 char and no terminating '\0'. Neither did it write 128 char.
One could instead perform write(filedescriptor, real_segname, strlen(real_segname)+1); to write the 7 char and the terminating '\0'. Or write the length and then the interesting parts of the arry. Or write the entire 128 char array`. Need to identify how you want to read data back and other coding goals to well advise.
As #SGG suggests, the unusually char are simply the result of write(filedescriptor, &mods, sizeof(int)); and are not part of your unterminated array.
after writing, I can see that the string "testseg" is followed by a "d" or "È" in the testFile.txt file
Why it is showing "d" or "È"??
Only try below write function (in your code, comment remaining write calls except below call)
write(filedescriptor, &mods, sizeof(int));
Now see the contents of testFile.txt (cat testFile.txt). It shows some junk value(s).
Because, all .txt files will show you in the form of ASCII text format. It converts every byte into ASCII charcter. String and characters you're writing in ASCII format and reading them as ASCII. So no problem. But here you're writing mods and num_segs as integers and reading them as ASCII format. So you got those junk values.
Is this a proper way of writing char[] array to file?
Yes, according to man pages you're writing them in proper way. And please make sure to validate your function calls(write). Where to write, what to write in a file depends upon your requirement.
Related
Here is a minimal "working" example:
#include <stdio.h>
#include <stdlib.h>
int main (int argc, char* argv[])
{
int num = 10;
FILE* fp = fopen("test.txt", "r"); // test.txt contains character sequence
char* ptr = (char*) malloc(sizeof (char)*(num+1)); // +1 for '\0'
fread(ptr, sizeof(char), num, fp); // read bytes from file
ptr[num] = '\0';
printf("%s\n", ptr); // output: ´╗┐abcdefg
free(ptr);
fclose(fp);
return 0;
}
I would like to read some letters from a text file, containing all letters from the alphabet in a single line. I want my array to store the first 10 letters, but the first 3 shown in the output are weird symbols (see the comment at the printf statement).
What am I doing wrong?
The issue is that your file is encoded using UTF-8. While UTF-8 is backwards-compatible with ASCII (which is what your code will be using) there are many differences.
In particular, many programs will put a BOM (Byte Order Mark) symbol at the start of the file to indicate which direction the bytes go. If you print the BOM using the default windows code page, you get the two symbols you saw.
Whatever program you used to create your text file was automatically inserting that BOM at the start of the file. Notepad++ is notorious for doing this. Check the save options and make sure to save either as plain ASCII or as UTF-8 without BOM. That will solve your problem.
I'm trying to get aquainted with system calls and C. I'm trying to read a file and write all the contents to the command line. I'm trying
int handle = open("./test.txt", O_RDONLY, O_TEXT);
char buf[1];
lseek(handle, 0, SEEK_SET);
while (0 != read(handle, buf, 1)) {
printf(*buf);
}
This ALMOST works, except that it adds some gibberish characters after each character read from the file. For example if the file contains asd asd this writes a:_s:_d:_ :_a:_s:_d to the console. Any idea why? How can I fix it?
You code should produce warnings on most modern compilers. Because printf() doesn't accept a char. Since you are reading the file char by char, you can instead use putchar() to print on the stdout.
while (read(handle, buf, 1) == 1) {
putchar(buf[0]);
}
Every string has to end with the \0 (null) character.
So try to make your buffer size 2, and just before printf do buf[1] = '\0';
In general when you read wcnt (type ssize_t) number of chars you do buf[wcnt] = '\0';
Also your printf is not syntaxed correctly safely!
printf("%s", buf);
Edit: As mentioned in other answers and comments (I will not add it since I did not propose it first), you can just print a char in this case.
I am trying to read a file in C. But when I read, and write it to stdout it prints # also which there is no in my file. What is the reason?
#include <stdio.h>
int main() {
FILE *fp;
int br;
char buffer[10];
int i;
fp = fopen("a.txt","r");
while(1) {
br = fread(buffer,1,10,fp);
printf("%s",buffer);
if (br==0)
break;
}
}
Output:
1234567891#2345678912#3456789
12#3456789
12#
The file:
123456789123456789123456789
Your fread call reads up to 10 bytes correctly, but printf with %s requires string to be null terminated. You can fix it by increasing size of the buffer to be 11 bytes and after every call to fread write zero at the end of data, i.e. buffer[br] = 0;.
The other way to go is to tell printf what is the size of your data by calling printf("%.*s", br, buffer);. You don't need to modify your buffer array then.
Dynamically allocate your buffer and have it be initialized to zeros like this:
char *buffer = calloc(1, 11);
<do your read loop>
free(buffer)
This way you get the zero byte at the end which will terminate the string when printing it. When C prints a string it expects it to be terminated by a NULL (or 0) byte.
I am completely new to C and need help with this badly.
Im reading a file with fopen(), then obtaining the contents of it using fgetc(). What I want to know is how I can access the line fgetc() returns so if I can put the 4th - 8th characters into a char array. Below is an example I found online but am having a hard time parsing the data returns, I still don't have a firm understanding of C and don't get how an int can be used to store a line of characters.
FILE *fr;
fr = fopen("elapsed.txt", "r");
int n = fgetc(fr);
while(n!= EOF){
printf("%c", n);
n = fgetc(fr);
} printf("\n");
Here
1 first open the file
2 get size of file
3 allocated size to character pointer
4 and read data from file
FILE *fr;
char *message;
fr = fopen("elapsed.txt", "r");
/*create variable of stat*/
struct stat stp = { 0 };
/*These functions return information about a file. No permissions are required on the file itself*/
stat("elapsed.txt", &stp);
/*determine the size of data which is in file*/
int filesize = stp.st_size;
/*allocates the address to the message pointer and allocates memory*/
message = (char *) malloc(sizeof(char) * filesize);
if (fread(message, 1, filesize - 1, fr) == -1) {
printf("\nerror in reading\n");
/**close the read file*/
fclose(fr);
/*free input string*/
free(message);
}
printf("\n\tEntered Message for Encode is = %s", message);
PS Dont Forget to Add #include <sys/stat.h>.
You're not retrieving a line with fgetc. You are retrieving one character at a time from the file. That sample keeps retrieving characters until the EOF character is encountred (end of file). Look at this description of fgetc.
http://www.cplusplus.com/reference/clibrary/cstdio/fgetc/
On each iteration of the while loop, fgetc will retrieve a single character and place it into the variable "n". Something that can help you with "characters" in C is to just think of it as one byte, instead of an actual character. What you're not understanding here is that an int is 4 bytes and the character is 1 byte, but both can store the same bit pattern for the same ASCII character. The only different is the size of the variable internally.
The sample you have above shows a printf with "%c", which means to take the value in "n" and treat it like an ASCII character.
http://www.cplusplus.com/reference/clibrary/cstdio/printf/
You can use a counter in the while loop to keep track of your position to find the 4th and 8th value from the file. You should also think about what happens if the input file is smaller than your maximum size.
Hope that helps.
Ok look at it as box sizes I could have a 30cm x 30cm box that can hold 1 foam letter that I have. Now the function I am calling a function that 'could' return a 60cm x 60cm letter but it 99% likely to return a 30cm x 30cm letter because I know what its reading - I know if I give it a 60cm x 60cm box the result will always fit without surprises.
But if I am sure that the result will always be a 30cm x 30cm box then I know I can convert the result of a function that returns aa 60cm x 60cm box without losing anything
I want to store strings in a binary file, along with a lot of other data, im using the code below (when i use it for real the strings will be malloc'd) I can write to the file. Ive looked at it in a hex editor. Im not sure im writing the null terminator correctly (or if i need to). when i read back out i get the same string length that i stored, but not the string. what am i doing wrong?
FILE *fp = fopen("mybinfile.ttt", "wb");
char drumCString[6] = "Hello\0";
printf("%s\n", drumCString);
//the string length + 1 for the null terminator
unsigned short sizeOfString = strlen(drumCString) + 1;
fwrite(&sizeOfString, sizeof(unsigned short), 1, fp);
//write the string
fwrite(drumCString, sizeof(char), sizeOfString, fp);
fclose(fp);
fp = fopen("mybinfile.ttt", "rb");
unsigned short stringLength = 0;
fread(&stringLength, sizeof(unsigned short), 1, fp);
char *drumReadString = malloc(sizeof(char) * stringLength);
int count = fread(&drumReadString, sizeof(char), stringLength, fp);
//CRASH POINT
printf("%s\n", drumReadString);
fclose(fp);
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);
I see a couple of issues, some problematic, some stylistic.
You should really test the return values from malloc, fread and fwrite since it's possible that the allocation can fail, and no data may be read or written.
sizeof(char) is always 1, there's no need to multiply by it.
The character array "Hello\0" is actually 7 bytes long. You don't need to add a superfluous null terminator.
I prefer the idiom char x[] = "xxx"; rather than specifying a definite length (unless you want an array longer than the string of course).
When you fread(&drumReadString ..., you're actually overwriting the pointer, not the memory it points to. This is the cause of your crash. It should be fread(drumReadString ....
A couple of tips:
1
A terminating \0 is implicit in any double quote string, and by adding an additional at the end you end up with two. The following two initializations are identical:
char str1[6] = "Hello\0";
char str2[6] = { 'H', 'e', 'l', 'l', 'o', '\0', '\0'};
So
char drumReadString[] = "Hello";
is enough, and specifying the size of the array is optional when it is initialized like this, the compiler will figure out the required size (6 bytes).
2
When writing a string, you might just as well just write all characters in one go (instead of writing one by one character sizeOfString times):
fwrite(drumCString, sizeOfString, 1, fp);
3
Even though not so common for a normal desktop pc scenario, malloc can return NULL and you will benefit from developing a habbit of always checking the result because in embedded environments, getting NULL is not an unlikely outcome.
char *drumReadString = malloc(sizeof(char) * stringLength);
if (drumReadString == NULL) {
fprintf(stderr, "drumReadString allocation failed\n");
return;
}
You don't write the terminating NUL, you don't need to but then you have to think about adding it when reading. ie malloc stringLength + 1 char, read stringLength chars and add a \0 at the end of what has been read.
Now the usual warning: if you are writing binary file the way you are doing here, you have lots of unstated assumptions which make your format difficult to port, sometimes even to another version of the same compiler -- I've seen default alignment in struct changes between compiler versions.
Some more to add to paxdiablo and AProgrammer - if you are going to use malloc in the future, just do it from the get go. It's better form and means you won't have to debug when switch over.
Additionally I'm not fully seeing the use of the unsigned short, if you are planning on writing a binary file, consider that the unsigned char type is generally of size byte, making it very convenient for that purpose.
You Just remove your &drumReadString in the fread function.You simply use drumReadString in that function as ganesh mentioned.Because,drumReadString is an array.Array is similar to pointers which point to the memory location directly.