Using the C language, I am trying to manipulate some files generated by openssl and containing a lot of (very) special characters. But the end of file seems to be prematurely detected.
For example see an extract of my program, that is supposed to copy a file to another :
(for simplicity reasons I do not show the test of the opening of the file but I do that in my program)
char msgcrypt[FFILE];
FILE* fMsg = fopen(f4Path,"r");
while(fgets(tmp,FFILE,fMsg) != NULL) strcat(msgcrypt,tmp);
fclose(fMsg);
FILE* fMsg2 = fopen(f5Path,"w");
fprintf(fMsg2,"%s",msgcrypt);
fclose(fMsg2);
here is the content of the file located at f4Path :
Salted__X¢~xÁïÈú™xe^„fl¯�˜<åD
now the content of the file located at f5Path :
Salted__X¢~xÁïÈú™xe^„fl¯
Notice that 4 characters are missing.
Do someone have an idea?
But the end of file seems to be prematurely detected
Sounds familiar.
Use fopen(f4Path, "rb") when opening the file. This has real significance on Windows.
Don't use string functions (fprintf, strcat, fgets etc) they will choke on NUL characters. Use fread and fwrite instead.
strcat tries and copy a nul-terminated char *. Which means, if it encounters a 0, which it probably has done here, it will stop copying.
You'd better use open read, memcpy and write.
That character it stops on I copied into a hex editor, and it ends up being EF BF BD, a BOM if I'm not mistaken. As a result, reading the file as a text file fails. I don't see any NULL characters (unless copying and pasting got rid of them).
The answer (as has already been discussed) is to not treat it as a text file, and avoiding the str functions won't do any harm either.
The first thing I'd do though is add a check for how may characters are read, that way you'll know where the data is being truncated. Right now it could be in any of: read, strcat, write.
Related
Is it possible to write at the middle of a file for example I want to insert some string at the 5th position in the 2nd line of a file in c ?
I'm not very familiar with some of C functions that are related to handling files , if someone could help me I would appreciate it
I tried using fputs but I couldn't insert characters at the desired location
open a new output file
read the input file line by line (fgets) writing each line out to a new file as you read.
When you hit the place you want to insert write the new line(s)
The carry on copy the old lines to the new file
close input and output
rename output file to input
Continuing from my comments above. Here's what I'd do:
Create two large, static char[] buffers of the same size--each large enough to store the largest file you could possibly ever need to read in (ex: 10 MiB). Ex:
#define MAX_FILE_SIZE_10_MIB (10*1024*1024)
static char buffer_file_in[MAX_FILE_SIZE_10_MIB];
static char buffer_file_out[MAX_FILE_SIZE_10_MIB];
Use fopen(filename, "r+") to open the file as read/update. See: https://cplusplus.com/reference/cstdio/fopen/. Read the chars one-by-one using fgetc() (see my file_load() function for how to use fgetc()) into the first large char buffer you created, buffer_file_in. Continue until you've read the whole file into that buffer.
Find the location of the place you'd like to do the insertion. Note: you could do this live as you read the file into buffer_file_in the first time by counting newline chars ('\n') to see what line you are on. Copy chars from buffer_file_in to buffer_file_out up to that point. Now, write your new contents into buffer_file_out at that point. Then, finish copying the rest of buffer_file_in into buffer_file_out after your inserted chars.
Seek to the beginning of the file with fseek(file_pointer, 0, SEEK_SET);
Write the buffer_file_out buffer contents into the file with fwrite().
Close the file with fclose().
There are some optimizations you could do here, such as storing the index where you want to begin your insertion, and not copying the chars up to that point into buffer_file_in, but rather, simply copying the remaining of the file after that into buffer_file_in, and then seeking to that point later and writing only your new contents plus the rest of the file. This avoids unnecessarily rewriting the very beginning of the fie prior to the insertion point is all.
(Probably preferred) you could also just copy the file and the changes you insert straight into buffer_file_out in one shot, then write that back to the file starting at the beginning of the file. This would be very similar to #pm100's approach, except using 1 file + 1 buffer rather than 2 files.
Look for other optimizations and reductions of redundancy as applicable.
My approach above uses 1 file and 1 or 2 buffers in RAM, depending on implementation. #pm100's approach uses 2 files and 0 buffers in RAM (very similar to what my 1 file and 1 buffer approach would look like), depending on implementation. Both approaches are valid.
I want to do the following:
open and read and ASCII file
locate a substring (geographical coordinates)
create its replacement (apply corrections to the original coordinates)
overwrite the original substring (write in the original file the corrected coordinates).
The format of the ASCII file is:
$GPGGA,091306.00,4548.17420,N,00905.47990,E,1,09,0.87,233.5,M,47.2,M,,*53
I will paste here only the part of the code that is responsible for this operation:
opnmea = fopen (argv[1], "r+");
if (fgets(row_nmea, ROW, opnmea)==NULL){
if (strstr(row_nmea,"$GPGGA")!=NULL) {
sscanf(row_nmea+17, "%10c", old_phi);
sscanf(row_nmea+30, "%11c", old_lam);
sscanf(row_nmea+54, "%5c", old_h);
fputs();
}
}
What I do till now is to extract in a variable the old coordinates and I was thinking to use fputs() for overwriting the old with new values. But I could not do it. The other part of the code that is not here is computing the correct coordinates. My idea is to correct the rows one by one, as the fgets() function reads each line.
I would appreciate very much any suggestion that can show me how to use fputs() or another function to complete my work. I am looking for something simple as I am beginner with C.
Thank you in advance.
Patching a text file in place is not a good solution for this problem, for multiple reasons:
the modified version might have a different length, hence patching cannot be done in place.
the read-write operation of standard streams is not so easy to handle correctly and defeats the buffering mechanism.
if you encounter an error during the patching phase, a partially modified file can be considered corrupted as one cannot tell which coordinates have been modified and which have not.
other programs might be reading from the same file as you are writing it. They will read invalid or inconsistent data.
I strongly recommend to write a program that reads the original file and writes a modified version to a different output file.
For this you need to:
open the original file for reading opnmea = fopen(argv[1], "r");
open the output file for writing: outfile = fopen(temporary_file_name, "w");
copy the lines that do not require modification: just call fputs(row_nmea, outfile).
parse relevant data in lines that require modification with whatever method you are comfortable with: sscanf, strtok, ...
compute the modified fields and write the modified line to outfile with fprintf.
Once the file has been completely and correctly handled, you can replace the original file with rename. The rename operation is usually atomic at the file-system level, so other programs will either finish reading from the previous version or open the new version.
Of course, if the file has only one line, you could simply rewind the stream and write back the line with fprintf, but this is a special case and it will fail if the new version is shorter than the original. Truncating the extra data is not easy. An alternative is to reopen the file in write mode ("w") before writing the modified line.
I would recommend strtok(), followed by your revision, followed by strcat().
strtok() will let you separate the line using the comma as a delimiter, so you will get the field you want reliably. You can break up the line into separate strings, revise the coordinates you wish, and reassemble the line, including the commas, with strcat().
These pages include nice usage examples, too:
http://www.cplusplus.com/reference/cstring/strtok/
http://www.cplusplus.com/reference/cstring/strcat/?kw=strcat
I have written some data to a file manually i.e. not by my application.
My code is reading the data char by char and storing them in different arrays but my program gets stuck when I insert the condition EOF.
After some investigation I found out that in my file before EOF there are three to four \n characters. I have not inserted them. I don't understand why they are in my file.
Want to remove those pesky extra characters? First, see how many of them there are at the end of your file:
od -c <filename> | tail
Then, remove however many characters you don't like. If it's 3:
truncate -s -3 <filename>
But overall, if it were me, I'd change my program to discard undesired newline characters, unless they're truly invalid according to the input file format specification.
It is very easy to add additional newlines to the end of a file in every text editor. You have to push the cursor around to see them. Open your file in your editor and see what happens when you navigate to the end, you'll see the extra newlines.
There is no such thing as an EOF character in general. Windows treats control-Z as EOF in some cases. Perhaps you are talking about the return value from some API that indicates that it has reached the end of file?
hello i got a problem with reading from a file, i am trying to read from a file using fscanf() and i cant seem to sort it out.
i try to read the file line by line and putting the string in a variable (buffer) each time but i cant understand how the while loop is suppose to be looking like
thanks in advance
the file that i want to read from is a txt file with this format: first line :"1234,abc,etc" second line : "2432,fjh,etc" and more lines like those i want to be able to use the fscanf method inorder to put in each loop the all line lets say "1234,abc,etc" in my string variable and so on till i dont have any more lines to read from
this is what i managed to gather so far (ofc its not the currect way to write it):
char* buffer[100];
while (fscanf(FILE *finput,"%s",buffer)!=something)
{
printf("%s",buffer);
}
i want this code to be able to print all of the lines in my code if you would be able to correct my errors i will greatly appriciate it
I feel like you should read some of these great topics first:
Trouble reading a line using fscanf()
Reading file using fscanf() in C
fscanf multiple lines [c++]
There are plenty of reasons why you should use fgets or something else instead.
Quoting from this place:
fscanf() is a field oriented function and is inappropriate for use in a robust, general-purpose text file reader. It has two major drawbacks:
You must know the exact data layout of the input file in advance and rewrite the function call for every different layout.
It's difficult to read text strings that contain spaces because fscanf() sees space characters as field delimiters.
If you know the size of file you're trying to read, you could use fread(), which is block oriented.
i m reading from file line by line but when i read some garbage character like space /r is being added i m nt getting why it is being added although there is no such character in file from where i m reading ..i have used fread and fgets both from both i m getting the same problem please reply if u have solution for this problem
The file was probably edited/created on Windows. Windows uses \r\n as a line delimiter. When you read the file, you must strip the \r manually. Since most editors treat \r\n as a single character (line end), you can't "see" it but it's still in the file. Use a hex editor if you want to see it or a tool like od.
Open the file in text mode.
/* ... */
fopen(filename, "r"); /* notice no 'b' in mode */
/* ... */
Supposing you're on Windows ... on reading operations, the library is responsible for translating the literal "\r\n" present on disk to "\n"; and on writing operation, the library translates "\n" to "\r\n".