Open file mode string w+ - io

I know what io.open(file, "w") does, it indicates writting. However I have encountered io.open(file, "w+") and can't find what "w+" does?

io.open just uses fopen of C. you could check the manual of fopen in C.
w: Truncate file to zero length or create text file for writing.
The stream is positioned at the beginning of the file.
w+: the same as w, besides the handle returned could be used for
reading.

From the reference manual io.open
The mode string can be any of the following:
"r": read mode (the default);
"w": write mode;
"a": append mode;
"r+": update mode, all previous data is preserved;
"w+": update mode, all previous data is erased;
"a+": append update mode, previous data is preserved, writing is only allowed at the end of file.
update mode here means, both input and output may be performed on the
associated file.

I tested this in Lua 5.1 running on OpenWRT and found
file=io.open("/usr/share/result","w")
was the same as
file=io.open("/usr/share/result","w+")
Both actions erased the current content of the file and re-wrote it.
When I tried
file=io.open("/usr/share/result","a")
The file was appended to - it got longer and longer each time my code ran.
So I don't think there is a difference.

Related

Unsure how to resolve this overwriting error

I have a function that prompts the user to enter their firstname, Surname, Password and id.
What I realised is that every time I run this function it just overwrites my previous values for these 4 variables. What I want to achieve is to be able to run this function and then write the details to a text file and permanently save it and then be able to add another user's details and upload it. Currently when I restart the program and run my student registeration function it's just overwriting my previous variables. Perhaps I shouldn't store my data in variables? Any tips on how to resolve this?
f = open("studentlogindetails.txt", "a+")
f.write("\n" + firstname + " " + surname + " " + universitypassword + " " + universityid)
f.close()
The a+ mode is used to open a file to be read and appended to. Because it is intended to be read, the cursor is placed at the very beginning of the file under the assumption that you are going to immediately try to read from the file. When you try to write, the data written starts wherever the cursor is. You want to place the cursor at the end of the file before you write.
If you don't need to read information and only write, you can use the a mode instead, which opens the file for appending information and places the cursor at the end of the file.
Alternatively, you can manually move the cursor to the end of the file with the f.seek method.
The documentation states:
fileObject.seek(offset[, whence])
offset − This is the position of the read/write pointer within the file.
whence − This is optional and defaults to 0 which means absolute file positioning, other values are 1 which means seek relative to the current position and 2 means seek relative to the file's end.
So, if you want to keep using the a+ mode, you have to remember to use f.seek(0, 2) to place the cursor 0 bytes from the end of the file before writing.
The available file-open modes and their use can be seen below:
r: Opens the file in read-only mode. Starts reading from the beginning of the file and is the default mode for the open() function.
rb: Opens the file as read-only in binary format. Places the cursor at the start of the file.
r+: Opens a file for reading and writing. Places the cursor at the beginning of the file.
w: Opens in write-only mode. Places the cursor at the beginning of the file. This will overwrite any existing file with the same name. It will create a new file if one with the same name doesn't exist.
wb: Same behavior as w, except the file is opened in binary mode.
w+: Opens a file for writing and reading. Replaces all content and creates the file if it doesn't exist. This mode is used when you need to write to an empty-file and potentially read from it later in your code (before closing).
wb+: Same behavior as w+ except the file is in binary mode.
a: Opens a file for appending new information to it. The cursor is placed at the end of the file. A new file is created if one with the same name doesn't exist.
ab: Same behavior as a except the file is in binary mode.
a+: Opens a file for both appending and reading. The cursor is placed at the beginning of the file.
ab+: Same as a+ except the file is in binary mode.
Information for the modes was pulled and edited from here.
You should use the with keyword and write your data, you can pass the append argument as well.
with open("studentlogindetails.txt", "a") as f:
# Using f-strings
f.write(f"{firstname} {surname} {universitypassword} {universityid}")
Using with ensures all resources are cleaned up even if an error occurs.
Note: If this is just a project you're playing around with to learn how to write text files, then you're probably fine, however, if this is going to be used in production, it's best you use a proper database.
It looks like your writing some user data at a University, you can use the ID that is given to every student and employee as the primary key.
Also, don't store passwords in plain text, and don't implements your own hashing algorithm. Many robust solutions exist.

Opening the file in r+ mode but not able to truncate it?

I am failing to truncate a previously created file by opening it in r+ mode given that r+ Open for reading and writing. The stream is positioned at the beginning of the file.
Reference -> here
from sys import argv
script, filename = argv
print(f"We're going to erase {filename}")
print("If you don't want that, hit Ctrl+C (^C).")
print("If you do want that, hit return")
input("?")
print("Opening the file...")
target = open(filename, 'r+')
print(target.read())
print("Truncating the file, Goodbye!")
target.truncate()
The truncate method will resize the file so that it ends at the current file position (if you don't pass it a value for the size argument). When you read the file, you move the current position in the file from the start to the end. That means the truncation does nothing, since you're making the new end of the file the same as the old end position.
If you want to call truncate with no arguments, you need to seek back to the beginning of the file first, or alternatively, call truncate(0) to tell it to make the new file size zero bytes.
The "truncate" method takes an optional size parameter. If you do not specify that parameter, it uses the default location into the file. I assume since you just read the file, the default location is at the end of the file -- so nothing follows the current location and nothing gets truncated. Try passing a zero (0) to the truncate method and see what happens. You might also try opening the file with 'rw+'.

How could I judge whether the file has been changed since last saving in vim

I am trying to quantify my vim action by logging timestamp when saving(:w) a file.
Is it possible to know whether the file had really been edited since the last saving?
for example, I saved the file by :w, then, did nothing and just type :w to save it again, is it possible to judge that the file wasn't actually modified?
You can check the value of the 'modified' option:
if &modified
" do something if the buffer is modified
else
" do something else if it is not
endif
Vim displays a '[+]' next to the file name when the file has been modified. However it displays it even if there is no diff between the file on disk and your buffer (for example if you add the letter 'a' then remove it it will consider that the file has been edited).
press :file and if changes have been made [Modified] will be displayed after your file name.
If you have set laststatus to 2 in Vim, it shows you a status line at the bottom of the window which has a [+] indicator next to the filename when the file has been modified since it was last written.
Relevant help pages: laststatus, statusline
Before reading your answer, I thought it was about knowing if the file had been updated from another vim instance / editor before saving it!
If so, vim usally tell me when I want to save it :
WARNING : the file has been updated since vim read it !
Do you want to write it anyway (y/n)?
If it's only about knowing if you change anything since last time, as explained before, Vim display a [+] after your filename.

Saving a flat-file through Vim add an invisible byte to the file that creates a new line

The title is not really specific, but I have trouble identifying the correct key words as I'm not sure what is going on here. For the same reason, it is possible that my question has a duplicate, as . If that's the case: sorry!
I have a Linux application that receive data via flat files. I don't know exactly how those files are generated, but I can read them without any problem. Those are short files, only a line each.
For test purpose, I tried to modify one of those files and reinjected it again in the application. But when I do that I can see in the log that it added a mysterious page break at the end of the message (resulting in the application not recognising the message)...
For the sake of example, let's say I receive a flat file, named original, that contains the following:
ABCDEF
I make a copy of this file and named it copy.
If I compare those two files using the "diff" command, it says they are identical (as I expect them to be)
If I open copy via Vi and then quit without changing nor saving anything and then use the "diff" command, it says they are identical (as I also expect them to be)
If I open copy via Vi and then save it without changing anything and then use the "diff" command, I have the following (I added the dot for layout purpose):
diff original copy
1c1
< ABCDEF
\ No newline at end of file
---
.> ABCDEF
And if I compare the size of my two files, I can see that original is 71 bytes when copy is 72.
It seems that the format of the file change when I save the file. I first thought of an encoding problem, so I used the ":set list" command on Vim to see the invisible characters. But for both files, I can see the following:
ABCDEF$
I have found other ways to do my test, But this problem still bugged me and I would really like to understand it. So, my two questions are:
What is happening here?
How can I modify a file like that without creating this mysterious page break?
Thank you for your help!
What happens is that Vim is set by default to assume that the files you edit end with a "newline" character. That's normal behavior in UNIX-land. But the "files" your program is reading look more like "streams" to me because they don't end with a newline character.
To ensure that those "files" are written without a newline character, set the following options before writing:
:set binary noeol
See :help 'eol'.

Why would Vim add a new line at the end of a file?

I work with Wordpress a lot, and sometimes I changed Wordpress core files temporarily in order to understand what is going on, especially when debugging. Today I got a little surprise. When I was ready to commit my changes to my git repository, I noticed that git status was marking one of Wordpress files as not staged for commit. I remember I had reverted all the changes I did to that file before closing it, so I decided to use diff to see what had changed. I compared the file on my project with the file on the Wordpress copy that I keep in my downloads directory. It turns out the files differ at the very end. diff indicates that the there is a newline missing at the end of the original file:
1724c1724
< }
\ No newline at end of file
---
> }
I never even touched that line. The changes I made where somewhere in the middle of a large file. This leads me to think that vim added a newline character at the end of the file. Why would that happen?
All the answers I've seen here address the question "how could I prevent Vim from adding a newline character at the end of the file?", while the question was "Why would Vim add a new line at the end of a file?". My browser's search engine brought me here, and I didn't find the answer to that question.
It is related with how the POSIX standard defines a line (see Why should files end with a newline?). So, basically, a line is:
3.206 Line
A sequence of zero or more non- <newline> characters plus a terminating <newline> character.
And, therefore, they all need to end with a newline character. That's why Vim always adds a newline by default (because, according to POSIX, it should always be there).
It is not the only editor doing that. Gedit, the default text editor in GNOME, does the same exact thing.
Edit
Many other tools also expect that newline character. See for example:
How wc expects it.
GCC warns about it.
Also, you may be interested in: Vim show newline at the end of file.
Because vim is a text editor, it can sometimes "clean up" files for you. See http://vimhelp.appspot.com/vim_faq.txt.html#faq-5.4 for details on how to write without the ending newline, paraphrased below:
How do I write a file without the line feed (EOL) at the end of the file?
You can turn off the eol option and turn on the binary option to write a file without the EOL at the end of the file:
   :set binary
   :set noeol
   :w
Alternatively, you can use:
   :set noeol
   :w ++bin
Adding a newline is the default behavior for Vim. If you don't need it, then use this solution: VIM Disable Automatic Newline At End Of File
To disable, add this to your .vimrc
set fileformats+=dos
You can put the following line into your .vimrc
autocmd FileType php setlocal noeol binary
Which should do the trick, but actually your approach is somewhat wrong. First of all php won't mind that ending at all and secondly if you don't want to save your changes don't press u or worse manually try to recreate the state of the file, but just quit without saving q!. If you left the editor and saved for some reason, try git checkout <file>
3.206 Line
A sequence of zero or more non- characters plus a terminating character.
Interestingly, vim will allow you to open a new file, write the file, and the file will be zero bytes. If you open a new file and append a line using o then write the file it will be two characters long. If you open said file back up and delete the second line dd and write the file it will be one byte long. Open the file back up and delete the only line remaining and write the file it will be zero bytes. So vim will let you write a zero byte file only as long as it is completely empty. Seems to defy the posix definition above. I guess...

Resources