Opening a file in C in write mode - c

I am writing a C program that converts a text file into a binary file and vice versa. The first question I have is about opening a file in "w" mode. Is there any need to have a check that the output file is opened correctly?
FILE *output;
output = fopen("output.bin", "w");
if(output == NULL)
{ printf("Error opening output file\n");}
Basically my question is whether or not output would ever actually == NULL. Because if there was a problem opening the output wouldn't it just create a new file named "output.bin"?
Also my other question is how characters are actually saved in a binary file. I know I'm supposed to save each character as an unsigned char so it can have values between 0 and 255 and then I should write that char to the output file. The actual logical path of how that happens is not making sense if anyone can help me or point me in the right direction I would appreciate it!

Yes, opening a file in write mode might still fail. Here's a bunch of possible reasons, but certainly not the only ones:
You don't have permission to create or change the file.
The file is read-only, or the directory it would be in is read-only.
The file would be inside another file. (test/foo if test is a file and not a directory)
The filesystem is out of space or inodes (on filesystems that have a fixed number of inodes)
The user has hit their disk space quota.
The file would be on another computer, and the network is down.
The filename is invalid - such as C:/???*\\\\foo on windows.
The filename is too long.

Related

Can an already opened FILE handle reflect changes to the underlying file without re-opening it?

Assuming a plain text file, foo.txt, and two processes:
Process A, a shell script, overwrites the file in regular intervals
$ echo "example" > foo.txt
Process B, a C program, reads from the file in regular intervals
fopen("foo.txt", "r"); getline(buf, len, fp); fclose(fp);
In the C program, keeping the FILE* fp open after the initial fopen(), doing a rewind() and reading again does not seem to reflect the changes that have happened to the file in the meantime. Is the only way to see the updated contents by doing an fclose() and fopen() cycle, or is there a way to re-use the already opened FILE handle, yet reading the most recently written data?
For context, I'm simply trying to find the most efficient way of doing this.
On Unix/Linux, when you create a file with a name which already existed, the old file is not deleted or altered in any way. A new file is created and the directory is updated to point at the new file instead of the old one.
The old file will continue to exist as long as some directory entry points at it (Unix file systems allow the same file to be pointed to by multiple directories) or some program has an open file handle to the file, which is more relevant to your question.
As long as you don't close fp, it continues to refer to the original file, even if that file is no longer referenced by the filesystem. When you close fp, the file will get garbage collected automatically, and the next time you open foo.txt, you'll get a file descriptor for whatever file happens to have that name at that point in time.
In short, with the shell script you indicate, your C program must close and reopen the file in order to see the new contents.
Theoretically, it would be possible for the shell script to overwrite the same file without deleting it, but (a) that's tricky to get right; (b) it's prone to race conditions; and (c) closing and reopening the file is not that time-consuming. But if you did that, you would see the changes. [Note 1]
In particular, it's common (and easy) to append to an existing file, and if you have a shell script which does that, you can keep the file descriptor open and see the changes. However, in that case you would normally have already read to the end of the file before the new data was appended, and the standard C library treats the feof() indicator as sticky; once it gets set, you will continue to get an EOF indication from new reads. If you suspect that some process will be writing more data to the file, you should reset the EOF indication with fseek(fp, 0, SEEK_CUR); before retrying the read.
Notes
As #amadan points out in a comment, there are race conditions with echo text > foo.txt as well, although the window is a bit shorter. But you can definitely avoid race conditions by using the idiom echo text > temporary_file; mv -f temporary_file foo.txt, because the rename operation is atomic. Of course, that would definitely require you to close and reopen the file. But it's a good idea, particularly if the contents being written are long or critical, or if new files are created frequently.

Reading a string from a file with C. Fopen with w+ mode is not working

I made a C program that reads a string from a .txt file, then it encrypts the string, and finally it writes the string in the same file.
The thing is that if I use fopen("D:\\Prueba.txt","w+"), the program doesn't work, it prints garbage like this )PHI N.
I've debugged and I know the error is there in that line, because if I use fopen("D:\\Prueba.txt","r+"), the program works, and it writes what it should.
But I want to use w+ because it will rewrite what the .txt file had. Why is w+ not working?
If you're opening with w+ to first read the content, that's not going to work. From C11:
w+: truncate to zero length or create text file for update.
What's probably happening is that you read data from the now empty file but don't correctly check that it worked. That would explain the weird "content" you see of )PHI N.
One solution is to open the file as with r, open another file with w, and transfer the contents, encrypting them as part of that process. Then close both, delete the original, and rename the new one to the original name. This will allow you to process arbitrarily-sized files since you process them a bit at a time.
If you don't want to use a temporary file, and you're sure you can store the entire content in memory, you could open it r+, get the content, the reopen it with a new mode, such as with:
FILE *readFh = fopen( "myfile.txt", "r+");
// Read in content, massage as needed.
FILE *writeFh = frepoen( NULL, "w+", readFh);
// Provided that worked, you should now have an empty file to write to.
// Write back your massaged data.

Read/Write highscore from a file (Lua - Corona SDK)

Here's my issue: I have a file with the highscore written in it (just the first line, no nicknames, just the highscore), I need to read that line and compare it with the actual score obtained in the game session, if the score is higher, overwrite the file with the new value, but if I try to read it I get a null value... Seems like i'm not reading it the right way. What's wrong with my code?
Thanks for the help!
local path = system.pathForFile( "data.sav", system.DocumentsDirectory )
local file = io.open( path, "w+" )
highscore_letta = file:read("*n")
print(highscore_letta)
if (_G.player_score > tonumber(highscore_letta)) then
file:write(_G.player_score)
end
io.close( file )
I had this problem myself. I found out that if you open a file in "w+" mode, the current contents are deleted, so that you can write new contents. So to read and write you have to open the file twice. First, you open the file in "rb" mode and get the file contents, then close it. Then you reopen it in "wb" mode, write the new number, and close it.
In Windows, you need "b" in the file mode. Otherwise, the strings that you are reading and writing may be modified in unexpected ways: for instance, a newline ("\n") may be replaced with carriage return–newline ("\r\n").
The file modes that Lua supports are borrowed from the C language. (I found a description on page 305 of what I guess is a draft of the C specification.) I think the Lua manual sort of assumes that you will know what these modes mean, as an experienced C programmer would, but to me it wasn't at all obvious.
Thus to read a number and then write a new one:
local filepath = "path/to/file"
-- Create a file handle that will allow you to read the current contents.
local read_file = io.open(filepath, "rb")
number = read_file:read "*n" -- Read one number. In Lua 5.3, use "n"; the asterisk is not needed.
read_file:close() -- Close the file handle.
local new_number = 0 -- Replace this with the number you actually want to write.
-- Create a file handle that allows you to write new contents to the file,
-- while deleting the current contents.
write_file = io.open(filepath, "wb")
write_file:write(new_number) -- Overwrite the entire contents of the file.
write_file:flush() -- Make sure the new contents are actually saved.
write_file:close() -- Close the file handle.
I created a script to do these operations automatically, as they're somewhat annoying to type every time.
The mode "r+" or "r+b" is supposed to allow you to read and write, but I couldn't get it to work when the original contents are longer than the new contents. If the original contents are "abcd", four bytes, and the new contents are "efg", three bytes, and you write at offset 0 in the file, the file will now have "efgd": the last byte of the original contents is not deleted.

fopen() returning a NULL pointer, but the file definitely exists

The code I have is as follows:
FILE *txt_file = fopen("data.txt", "r");
if (txt_file == NULL) {
perror("Can't open file");
}
The error message returned is:
Can't open file: No such file or directory
The file 'data.txt' definitely exists in the working directory (it exists in the directory that contains my .c and .h files), so why is fopen() is returning a NULL pointer?
Standard problem. Try
FILE *txt_file = fopen("C:\\SomeFolder\\data.txt", "r");
I.e. try opening it with the full absolute path first ; if it works then you just have to figure out what the current directory is with _getcwd() and then fix your relative path.
Is it possible that the filename is not really "data.txt"?
On Unix, filenames are really byte strings not character strings, and it is possible to create files with controls such as backspace in their names. I have seen cases in the past in which copy-pasting into terminals resulted in files with ordinary-looking names, but trying to open the filename that appears in a directory listing results in an error.
One way to tell for sure that the filenames really are what you think they are:
$ python
>>> import os
>>> os.listdir('.')
My problem was that I had a file filename.txt and I didn't realize that in reality it was filename.txt.txt due to windows not showing the extension.
Make sure that your input file is in the same directory as the executable, which may be different than the one where your source files are kept. If you're running the program in an IDE debugger, make sure that your working directory is set to the location of the input file. Also, if you're running in *nix rather than Windows, you may need to prepend a "./" to the input filename.
Invisible SPACE character in file name?
Once a year I have a similar problem:
I try to open a file with the filename in a string, obtained from a sting operation. When I print the name it seems OK, but fopen() returns a null pointer. The only help is printing the name with delimiters showing the exact beginning and end of the filename string. Of course this does not not help with unprintable chars.
I just had a similar issue like this where I knew the path was correct and the file was in the right location. Check the file permissions. It is possible that the program cannot access the file because it is getting permission denied.
I encountered the same errno to fopen on Linux from a script file corrupted by Windows.
ENOENT 2 No such file or directory
Wordpad on Windows (or some other Microsoft culprit) inserted CRLF = (0x0D, 0x0A) into my linux script files in place of newline = LF = 0x0A. When I read the file name into a buffer and called fopen if failed due to the invisible appended CR character.
In the Codelite editor on Linux Mint I was able to show EOL characters (View > Display EOL) and remove them with find and replace, using copy and paste of the CRLF from the corrupted script files and the LF from an uncorrupted file into the text fields.

C Programming fopen() while opening a file

I've been wondering about this one. Most books I've read shows that when you open a file and you found that the file is not existing, you should put an error that there's no such file then exit the system...
FILE *stream = NULL;
stream = fopen("student.txt", "rt");
if (stream==NULL) {
printf(“Cannot open input file\n”);
exit(1);
else {printf("\nReading the student list directory. Wait a moment please...");
But I thought that instead of doing that.. why not automatically create a new one when you found that the file you are opening is not existing. Even if you will not be writing on the file upon using the program (but will use it next time). I'm not sure if this is efficient or not. I'm just new here and have no programming experience whatsoever so I'm asking your opinion what are the advantages and disadvantages of creating a file upon trying to open it instead of exiting the system as usually being exampled on the books.
FILE *stream = NULL;
stream = fopen("student.txt", "rt");
if (stream == NULL) stream = fopen("student.txt", "wt");
else {
printf("\nReading the student list directory. Wait a moment please...");
Your opinion will be highly appreciated. Thank you.
Because from your example, it seems like it's an input file, if it doesn't exist, no point creating it.
For example if the program is supposed to open a file, then count how many vowels in it, then I don't see much sense of creating the file if it doesn't exist.
my $0.02 worth.
Argument mode:
``r'' Open text file for reading.
``r+'' Open for reading and writing.
``w'' Truncate file to zero length or create text file for writing.
``w+'' Open for reading and writing. The file is created if it does not
exist, otherwise it is truncated.
``a'' Open for writing. The file is created if it does not exist.
``a+'' Open for reading and writing. The file is created if it does not
exist.
Your question is a simple case. Read above description, when you call fopen(), you should decide which mode shall be used. Please consider why a file is not created for "r" and "r+", and why a file is truncated for "w" and "w+", etc. All of these are reasonable designs.
If your program expects a file to exist and it doesn't, then creating one yourself doesn't make much sense, since it's going to be empty.
If OTOH, your program is OK with a file not existing and knows how to populate one from scratch, then it's perfectly fine to do so.
Either is fine as long as it makes sense for your program. Don't worry about efficiency here -- it's negligible. Worry about correctness first.
You may not have permission to create/write to a file in the directory that the user chooses. You will have to handle that error condition.

Resources