Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Open file for reading and writing with truncate

How do I open a file for reading and writing that is also truncated to 0?

I've tried:

f = open(PATH, 'w+')

I'm unable to read from the file (f.read() returns an empty string), however.

Also:

f = os.fdopen(os.open(PATH, os.O_RDWR | os.O_TRUNC), 'r+')

Same behavious as the previous code.

like image 839
someguy Avatar asked Nov 01 '15 20:11

someguy


People also ask

How do you open a file for both reading and writing?

'r+' opens the file for both reading and writing. On Windows, 'b' appended to the mode opens the file in binary mode, so there are also modes like 'rb', 'wb', and 'r+b'. Also reading then writing works equally well using 'r+b' mode, but you have to use f.

Which mode is open an existing file and truncate?

If you open an already existing file for writing, you usually want to overwrite the content of the output file. The open mode std::ios_base::trunc (meaning truncate) has the effect of discarding the file content, in which case the initial file length is set to 0 .

What is truncate file?

To truncate is to shorten by cutting off. In computer terms, when information is truncated, it is ended abruptly at a certain spot. For example, if a program truncates a field containing the value of pi (3.14159265...) at four decimal places, the field would show 3.1415 as an answer.

How can you open a file for reading and writing in Python give an example?

Opening Files in PythonPython has a built-in open() function to open a file. This function returns a file object, also called a handle, as it is used to read or modify the file accordingly. We can specify the mode while opening a file. In mode, we specify whether we want to read r , write w or append a to the file.


2 Answers

Here's a table of modes:

mode-string  | truncate? | create? | what's allowed
-------------+-----------+---------+----------------
     r       |    no     |  no     |  reading (only)
     w       |    yes    |  yes    |  writing (only)
     a       |    no     |  yes    |  writing (only), auto-appends
     r+      |    no     |  no     |  read and write
     w+      |    yes    |  yes    |  read and write
     a+      |    no     |  yes    |  read and (auto-appending) write

Note that there's a missing mode ("read and non-auto-append write, that will not truncate but will create"). If you want that one you must use the os functions.

(With all of these, add b to the end of the mode sequence to operate on bytes. The behavior without b depends on Python2 vs Python3 and also the universal_newlines option.)

In addition to all of this, switching from "read mode" to "write mode", or vice versa, on any file opened with the + update-mode, requires a seek operation in most cases. See this answer for more.


Edit: here are the various os operations for opening files as defined for Unix-like systems:

os.open(path, flags, mode)

The path argument is pretty obvious, and the mode argument is used only if the file is going to be created (hence may be omitted if you leave out the os.O_CREAT flag). If you do supply mode, the most common value is 0666 which corresponds to rw-rw-rw-. The user's "umask" (see os.umask) will take away the unwanted permissions, e.g., a umask of 002 takes away the final write bit, resuling in rw-rw-r--, while 077 takes away all but the initial rw-. The two other common modes are 0777 (rwxrwxrwx for executable files) and 0600 (rw------- for user-private files, such as temporary files when working with the user's email).

The flags value should include exactly one of os.O_RDONLY, os.O_WRONLY, or os.O_RDWR: open for reading (only), writing (only), or both.

To these, you can add1os.O_CREAT, meaning "create file if it does not exist"; os.O_TRUNC, meaning "truncate file to zero bytes in length immediately"; and/or os.O_APPEND, meaning "all os-level write operations implicitly seek to the current end-of-file just before writing". There may (depending on OS flavor) be more flags such as O_EXCL, O_NDELAY, O_NOFOLLOW and more. (The one that is perhaps most commonly useful and dependable is O_EXCL, which means "fail if this would open an existing file" and hence is only really useful when combined with O_CREAT. Using the two together, you can make a new file that you can guarantee no other cooperating process in the system is also using. The O_NOFOLLOW flag, if it exists, is also useful in some security contexts, to avoid symlink traps.)

In all cases, given whatever read/write settings you supply at the os level—i.e., O_RDONLY, O_WRONLY, or O_RDWR—if you then wrap the file descriptor into a Python stream with os.fdopen, you cannot gain additional powers that you did not grant yourself at open time. You can only subtract some away, i.e., you can open with O_RDWR but then fdopen the stream as either read- or write-only. In addition, when using fdopen with update mode, the annoying restriction of requiring seek or flush operations between different I/O directions remains in place.

Note that the a (append) mode at the fdopen level, if it's obeyed at all, is "less powerful" than the O_APPEND mode (or using a mode with open or io.open, all of which result in setting the underlying O_APPEND mode). This mostly has to do with cooperating processes that share a file: if two or more such processes have files opened with O_APPEND, as long as their writes are "small enough" (the details vary again with OSes), their writes will not intermingle. If the files are merely opened as O_WRONLY or O_RDWR, two cooperating processes can call the underlying seek function and then the underlying write function, but if the two are racing each other, one may overwrite the other's data.

(Some flags, including O_APPEND, can be switched off and on using fcntl (from import fcntl) with the F_SETFL argument. This was a relatively late addition to Python2.)


1"Add" here can mean literal addition, but using bitwise or | operations is more conventional. That is, os.open(os.O_RDWR | os.O_CREAT | os.O_TRUNC, 0666), not os.open(os.O_RDWR + os.O_CREAT + os.O_TRUNC, 0666).

like image 173
torek Avatar answered Nov 22 '22 14:11

torek


If you want to store the data then truncate use r+:

with open(PATH,"r+") as f:
    line = f.read()
    f.seek(0)
    f.truncate()
like image 43
Padraic Cunningham Avatar answered Nov 22 '22 13:11

Padraic Cunningham