Opening the file in r+ mode but not able to truncate it? - python-3.x

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+'.

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.

Is sed line deletion atomic?

Lets say I have a file 'queue'. From what I understand, appending to it using '>>' is atomic as defined by POSIX. But if I have multiple processes appending, is it safe to do the following without data loss?
sed -e '1d' -i queue
I have several different script services on Linux that may want to pass information between them. Each has a 'queue' where new data is pushed on the bottom with the next item to be popped from the top.
Is my use of sed guaranteed to not miss an append operation from another process between the time it reads the file to a buffer and writes it to back to disk?
Thanks.
I'll defer to anyone else who makes a stronger claim, but I think it is not safe to use that way. -i works by making a temporary copy of the file and then moving that back in place, which would replace any additional changes in the middle.
Source: http://www.gnu.org/software/sed/manual/sed.html
-i[SUFFIX]
--in-place[=SUFFIX]
This option specifies that files are to be edited in-place. GNU sed does this by creating a temporary file and sending output to this file rather than to the standard output.1.
This option implies -s.
When the end of the file is reached, the temporary file is renamed to the output file's original name. The extension, if supplied, is used to modify the name of the old file before renaming the temporary file, thereby making a backup copy2).
This rule is followed: if the extension doesn't contain a *, then it is appended to the end of the current filename as a suffix; if the extension does contain one or more * characters, then each asterisk is replaced with the current filename. This allows you to add a prefix to the backup file, instead of (or in addition to) a suffix, or even to place backup copies of the original files into another directory (provided the directory already exists).
If no extension is supplied, the original file is overwritten without making a backup.

Open file mode string w+

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.

less viewer: Copy all the lines to clipboard

There has already been a post in stackoverflow for VI editor for copying all the text into the clipboard. (Copy all the lines to clipboard) I want to do the same thing with the less viewer. I tried to search online for the process called "yank" and I did not find anything for it.
How do I copy all lines in the less editor into the clip board.
And I cannot close less and reopen it in vi. It is because of the fact that I have managed to load this file into the editor and while I have loaded it, the file has already been moved in the back end. It is a long story. The easiest solution for me now is to copy the contents of the file into memory.
less doesn't have a clipboard, but you may be able to get it to output what's stored in its buffers to a new file. This will only work if the entire contents of the file are buffered:
Type g to go to the top of the file
Type | (that's a pipe character, not an L or I) to indicate that you want to output to a pipe
Type $ to indicate that you want the output content to go to the end of the file
Type dd of=/path/to/new/file and press Enter
The dd command will take the piped data and save it to the file passed to the of= argument.
as an workaround you can set terminal's font size to 1, then select with mouse and copy (works for big , but not huge files).
If the file is not too big and if it fits in your terminal number of lines configured, then do the following:
Terminal > Edit > Clear to start
cat <file_name>
Terminal > Edit > Select all
Terminal > Edit > Copy

Shell script to nullify a file everytime it reaches a specific size

I am in the middle of writing a shell script to nullify/truncate a file if it reaches certain size. Also the file is being opened/written by a process all the time. Now every time when I nullify the file, will the file pointer be repositioned to the start of the file or will it remain in its previous position? Let me know if we could reset the file pointer once the file has been truncated?
The position of the file pointer depends on how the file was opened by the process that has it open. If it was opened in append mode, then truncating the file will mean that new data will be written at the end of the file, which is actually the beginning too the first time it writes after the file is truncated. If it was not opened in append mode, then truncating the file will simply mean that there is a series of virtual zero bytes at the start of the file, but the real data will continue to be written at the same point as the last write finished. If the file is being reopened by the other process, rather than being held open, then roughly the same rules apply, but there is a better chance that the file will be written at the beginning. It all depends on how the first process to write to the file after the truncation is managing its file pointer.
You can't reset the file pointer of another process, AFAIK.
A cron job or something like this will do the task; it will find every files bigger than 4096bytes then nullified the files
$ find -type f -size 4096c -print0 | while IFS= read -r -d $'\0' line; do cat /dev/null > $line; done
enter link description here

Resources