odd append behaviour - c

If I have a file containing
manual
/lib/plymouth/themes/default.plymouth
/lib/plymouth/themes/spinfinity/spinfinity.plymouth
10
/lib/plymouth/themes/ubuntu-logo/ubuntu-logo.plymouth
100
and then I open it in a mode, then do
fprintf(f, "/el/derpito.plymouth\n100\n");
why is the file now containing this?
manual
/lib/plymouth/themes/default.plymouth
/lib/plymouth/themes/spinfinity/spinfinity.plymouth
10
/lib/plymouth/themes/ubuntu-logo/ubuntu-logo.plymouth
100
/el/derpito.plymouth
100
I'd expect the file to be this instead:
manual
/lib/plymouth/themes/default.plymouth
/lib/plymouth/themes/spinfinity/spinfinity.plymouth
10
/lib/plymouth/themes/ubuntu-logo/ubuntu-logo.plymouth
100
/el/derpito.plymouth
100

Perhaps there is a lonely \n or \cr stuck at the end of the file before you make the write. I wuld open it with a hex editor and see.

my first guess would be that the last character of your file (before the appending) is a newline-character, after which append appends the new line.

Related

How to write bytes individually into a file in C?

I have an array of ints where every cell is a number between 0-255 representing a byte I want to write to the output file.
I have written this simple loop:
for (int i = 0; i < len ; i++)
putc(write_buffer[i], OutputFile);
However after reviewing the output file using hex editor, I found that certain bytes have been duplicated and/or moved around within the file.
For example with the input array:
int write_buffer[10]= {137,80,78,71,13,10,26,10,0,0}
The output file contents (in decimal) are: 137 80 78 71 13 13 10 26 13 10 0 0
Does anyone have a clue as for what could be causing this?
Psychic debugging: You opened the file in text mode on Windows passing fopen with mode "wt" or, when _fmode is set to _O_TEXT, which is the default, "w", which means it's applying line ending translation, converting LF ('\n'/10) to CRLF ('\r' '\n', 13 10).
Change your fopen to pass a mode of "wb", not just "w"/"wt", so the file is operating in binary mode, and the translation won't be performed with any C stdio functions.
pts made a useful note in the comments: If you didn't open the file yourself (using stdout, or a handle opened by code you don't control), you can switch it to binary mode with setmode(fileno(OutputFile), O_BINARY); (for stdout, 1 can replace the first argument).

C - How to write new line without tampering with the existing line in output text?

I have this code
<....
Gets input from input.txt, which contains several lines
the code checks each lines, determining the usefulness by calculating BR and BL,
the 2 INT variables to detect whether the text is useful or not
....>
if (BR > BL)
//if the BR in a line is greater than the BL, I want to copy that line (from input.txt)
//and paste it to output.txt.
//So then the output.txt will only contains lines that has BR > BL
{
wr_file=fopen("output.txt", "w");
fprintf (wr_file, "%s \n", text);
}
The program can detect the BR and BL of each line correctly. But with that last code, I cant seem to properly copy the useful line from input.txt to output.txt
Lets say this is my input.txt :
1. carrot cabbage tomato
2. potato rice
3. cabbage eggplant
Supposedly, the 1st and 3rd lines are the useful ones. So the output.txt should be like this:
1. carrot cabbage tomato
3. cabbage eggplant
But instead it looked like this:
3. cabbage eggplantomato
As you can see, it did copy the 1st line, but when it has to write the 3rd line, it doesnt write it in a new line, but instead tamper with the 1st line.
Please help, how can I copy the lines correctly.
Without having MCVE, it's not possible to debug properly, but I assume, you problem is , you are calling
wr_file=fopen("output.txt", "w");
number of times, that's why your output is overwrittern and only the last write is retained. fopen() the target file only once, and keep the fwrite() in loop.
Also, you need to NULL NUL terminate your input [text] from the input file when using as a string [ex: passing to fwrite()].
It looks like the error is in the code that reads the file. When you read a line into a string, you should add a \0-character to terminate the string.
The output file is being opened in "w" mode ie the write mode, so what happens is that when you write a line it overwrites the file content.
I would recommend you to use the
wr_file=fopen("output.txt", "w");
for writing the first line and
wr_file=fopen("output.txt", "a");
for writing the remaining lines.
Update 1:
Else try this add all the data that you want to write to a string(char []) and then write that string to the respective file. Reduces the number of times the files is accessed.

How to save results of a function into text file in C

This function print the length of words with '*' called histogram.How can I save results into text file? I tried but the program does not save the results.(no errors)
void histogram(FILE *myinput)
{
FILE *ptr;
printf("\nsaving results...\n");
ptr=fopen("results1.txt","wt");
int j, n = 1, i = 0;
size_t ln;
char arr[100][10];
while(n > 0)
{
n = fscanf(myinput, "%s",arr[i]);
i++;
}
n = i;
for(i = 0; i < n - 1; i++)
{
ln=strlen(arr[i]);
fprintf(ptr,"%s \t",arr[i]);
for(j=0;j<ln;j++)
fprintf(ptr, "*");
fprintf(ptr, "\n");
}
fclose(myinput);
fclose(ptr);
}
I see two ways to take care of this issue:
Open a file in the program and write to it.
If running with command line, change the output location for standard out
$> ./histogram > outfile.txt
Using the '>' will change where standard out will write to. The issue with '>' is that it will truncate a file and then write to the file. This means that if there was any data in that file before, it is gone. Only the new data written by the program will be there.
If you need to keep the data in the file, you can change the standard out to append the file with '>>' as in the following example:
$> ./histogram >> outfile.txt
Also, there does not have to be a space between '>' and the file name. I just do that for preference. It could look like this:
$> ./histogram >outfile.txt
If your writing to a file will be a one time thing, changing standard out is probably be best way to go. If you are going to do it every time, then add it to the code.
You will need to open another FILE. You can do this in the function or pass it in like you did the file being read from.
Use 'fprintf' to write to the file:
int fprintf(FILE *restrict stream, const char *restrict format, ...);
Your program may have these lines added to write to a file:
FILE *myoutput = fopen("output.txt", "w"); // or "a" if you want to append
fprintf(myoutput, "%s \t",arr[i]);
Answer Complete
There may be some other issues as well that I will discuss now.
Your histogram function does not have a return identifier. C will set it to 'int' automatically and then say that you do not have a return value for the function. From what you have provided, I would add the 'void' before the function name.
void histogram {
The size of arr's second set of arrays may be to small. One can assume that the file you are reading from does not exceed 10 characters per token, to include the null terminator [\0] at the end of the string. This would mean that there could be at most 9 characters in a string. Else you are going to overflow the location and potentially mess your data up.
Edit
The above was written before a change to the provided code that now includes a second file and fprintf statements.
I will point to the line that opens the out file:
ptr=fopen("results1.txt","wt");
I am wondering if you mean to put "w+" where the second character is a plus symbol. According to the man page there are six possibilities:
The argument mode points to a string beginning with one of the
following sequences (possibly followed by additional characters, as
described below):
r Open text file for reading. The stream is positioned at the
beginning of the file.
r+ Open for reading and writing. The stream is positioned at the
beginning of the file.
w Truncate file to zero length or create text file for writing.
The stream is positioned at the beginning of the file.
w+ Open for reading and writing. The file is created if it does
not exist, otherwise it is truncated. The stream is
positioned at the beginning of the file.
a Open for appending (writing at end of file). The file is
created if it does not exist. The stream is positioned at the
end of the file.
a+ Open for reading and appending (writing at end of file). The
file is created if it does not exist. The initial file
position for reading is at the beginning of the file, but
output is always appended to the end of the file.
As such, it appears you are attempting to open the file for reading and writing.

Inserting a value into a file

In the code below, I have saved the values 1 - 9 in an Excel file and I want to insert an "a" between "4" and "5". I have set the pointer to position 7 but it is still inserting it at the end. Please help me understand this.
FILE *ExcelFile = fopen("testdata.csv","a");
if (ExcelFile == NULL)
return -1;
fprintf(ExcelFile,"1 2 3 4 5 6 7 8 9");
fseek (ExcelFile, 7, SEEK_SET );
//printf("pos is %ld bytes\n", pos);
fprintf(ExcelFile,"a");
fclose(ExcelFile);
The reason this does not work is because you are opening the file for appending (the "a" flag in the fopen call). Whenever you write to the file the data you write will always be appended. If your file does not exists before opening, use fopen("testdata.csv","w") instead.
You can't just "insert" the value into a file. You must open a new file, copy the first part of the first file, then your value, then the rest, and then replace the old file with the new one, or, if the file is small, read it into memory, clear the file, and then write the correct file.

fread Only first 5 bytes of .PNG file

I've made a simple resource packer for packing the resources for my game into one file. Everything was going fine until I began writing the unpacker.
I noticed the .txt file - 26 bytes - that I had packed, came out of the resource file fine, without anyway issues, all data preserved.
However when reading the .PNG file I had packed in the resource file, the first 5 bytes were intact while the rest was completely nullified.
I traced this down to the packing process, and I noticed that fread is only reading the first 5 bytes of the .PNG file and I can't for the life of me figure out why. It even triggers 'EOF' indicating that the file is only 5 bytes long, when in fact it is a 787 byte PNG of a small polygon, 100px by 100px.
I even tested this problem by making a separate application to simply read this PNG file into a buffer, I get the same results and only 5-bytes are read.
Here is the code of that small separate application:
#include <cstdio>
int main(int argc, char** argv)
{
char buffer[1024] = { 0 };
FILE* f = fopen("test.png", "r");
fread(buffer, 1, sizeof(buffer), f);
fclose(f); //<- I use a breakpoint here to verify the buffer contents
return 0;
}
Can somebody please point out my stupid mistake?
Can somebody please point out my stupid mistake?
Windows platform, I guess?
Use this:
FILE* f = fopen("test.png", "rb");
instead of this:
FILE* f = fopen("test.png", "r");
See msdn for explanation.
Extending the correct answer from SigTerm, here is some background of why you got the effect you did for opening a PNG file in text mode:
The PNG format explains its 8-byte file header as follows:
The first eight bytes of a PNG file always contain the following values:
(decimal) 137 80 78 71 13 10 26 10
(hexadecimal) 89 50 4e 47 0d 0a 1a 0a
(ASCII C notation) \211 P N G \r \n \032 \n
This signature both identifies the file as a PNG file and provides for immediate detection of common file-transfer problems. The first two bytes distinguish PNG files on systems that expect the first two bytes to identify the file type uniquely. The first byte is chosen as a non-ASCII value to reduce the probability that a text file may be misrecognized as a PNG file; also, it catches bad file transfers that clear bit 7. Bytes two through four name the format. The CR-LF sequence catches bad file transfers that alter newline sequences. The control-Z character stops file display under MS-DOS. The final line feed checks for the inverse of the CR-LF translation problem.
I believe that in text mode, the call to fread() was terminated when it read the sixth byte which contains a Ctrl+Z character. Ctrl+Z was historically used in MSDOS (and in CPM before it) to indicate the end of a file, which was necessary because the file system stored the size of a file as a count of blocks, not a count of bytes.
By reading the file in text mode instead of binary mode, you triggered the protection against accidentally using the TYPE command to display a PNG file.
One thing you could do that would have helped diagnose this error is to use fread() slightly differently. You didn't test the return value from fread(). You should. Further, you should call it like this:
...
size_t nread;
...
nread = fread(buffer, sizeof(buffer), 1, f);
so that nread is a count of the bytes actually written to the buffer. For the PNG file in text mode, it would have told you on the first read that it only read 5 bytes. Since the file cannot be that small, you would have had a clue that something else was going on. The remaining bytes of the buffer were never modified by fread(), which would have been seen if you initialized the buffer to some other fill value.

Resources