0

I am writing some text into a file:

import codecs
outfile=codecs.open("c:/temp/myfile.sps","w+","utf-8-sig")
#procedures for creating the text_to_write
outfile.write (text_to_write)
outfile.close()

Now, what I want to do is to insert into the file an additional text, always at a certain line (say line 10), but this additional text is final only after all the procedures for creating the text_to_write. So the code for inserting the additional text, at line 10, should be the last code:

Is this possible without closing the file, reopening, and then saving again ? (the reopen-insert-close approach is detailed here, but I would like to avoid it). I am looking for something like this:

import codecs
outfile=codecs.open("c:/temp/myfile.sps","w+","utf-8-sig")
#procedures for creating the text_to_write
outfile.write (text_to_write)
#code for inserting additional text at line 10
outfile.close()
horace_vr
  • 3,026
  • 6
  • 26
  • 48
  • You can probably use the `seek` method. https://docs.python.org/2/library/io.html#io.IOBase.seek However it's based on bytes rather than lines and you may not want to override what you already have. – Haochen Wu Mar 19 '18 at 16:00

1 Answers1

1

Since you don't know the exact position (in bytes) of the insertion point, you need to read the lines of the file content, insert the additional text after the line 10 and write the file a second time.

note: a Python 2+3 way to open a file is to use the io module instead of the codecs module.

For instance, you have the following text to write and additional text:

text_to_write = u"""\
|  1 | This
|  2 | 
|  3 | text
|  4 | 
|  5 | contains
|  6 | 
|  7 | at
|  8 | 
|  9 | least
| 10 | 
| 11 | ten
| 12 | 
| 13 | lines."""

additional_text = u"""\
| ++ | ADDITIONAL
| ++ | TEXT
"""

You can open the file for reading and writing. The file is created if it does not exist, otherwise it is truncated. The stream is positioned at the beginning of the file.

with io.open("file.txt", mode="w+", encoding="utf-8-sig") as f:
    f.write(text_to_write)
    f.seek(0)
    lines = f.readlines()
    lines[10:10] = additional_text.splitlines(keepends=True)
    f.seek(0)
    f.writelines(lines)

This solution is not very efficient because you read the content you just write. You can also process everything in memory and then write the file.

The result is:

|  1 | This
|  2 | 
|  3 | text
|  4 | 
|  5 | contains
|  6 | 
|  7 | at
|  8 | 
|  9 | least
| 10 | 
| ++ | ADDITIONAL
| ++ | TEXT
| 11 | ten
| 12 | 
| 13 | lines.

Another solution using a list in memory:

lines = text_to_write.splitlines(keepends=True)
lines[10:10] = additional_text.splitlines(keepends=True)
with io.open("file2.txt", mode="w+", encoding="utf-8-sig") as f:
    f.writelines(lines)
Laurent LAPORTE
  • 21,958
  • 6
  • 58
  • 103