tags:

views:

317

answers:

4

Hello,

I want to read a line in a file and insert the new line ("\n") character in the n position on a line, so that a 9-character line, for instance, gets converted into three 3-character lines, like this:

"123456789" (before)
"123\n456\n789" (after)

I've tried with this:

f = open(file, "r+")
f.write("123456789")
f.seek(3, 0)
f.write("\n")
f.seek(0)
f.read()

-> '123\n56789'

I want it not to substitute the character in position n, but only to insert another ("\n") char in that position.

Any idea about how to do this? Thanks

+7  A: 

I don't think there is any way to do that in the way you are trying to: you would have to read in to the end of the file from the position you want to insert, then write your new character at the position you wish it to be, then write the original data back after it. This is the same way things would work in C or any language with a seek() type API.

Alternatively, read the file into a string, then use list methods to insert your data.

source_file = open("myfile", "r")
file_data = list(source_file.read())
source_file.close()
file_data.insert(position, data)
open("myfile", "wb").write(file_data)
jkp
+1: You **must** read and rewrite the file.
S.Lott
-1 for the fact that you're opening the file without doing anything to close it afterwards. Last I checked, that isn't such a good idea, especially if he needs to do something else with the file afterwards.
JAB
It's still a helpful post.
Skurmedel
Only slightly. 1) Strings have no "insert" method. 2) Even if they did, it would only insert the requested character at one spot; you'd have to make a loop that would increment `position` by 4 each time (starting with `position` being 2), with the reason for incrementing by 4 being that you'd have to account for the inserted character in addition to the next three characters.
JAB
@Cat, yes, sorry: left out the conversion to a list. Also, have updated the example to close the file, but this is not strictly necessary. If you are being pedantic you could say it was better, but in this case I wanted brevity for the example.
jkp
...Or you could convert the string `file_data` to a list using `list(file_data)`. Either way, though, the code given would not work as expected.
JAB
@jkb: It's fine. I undid my downvote, as well, as the comments here work as additional info for your answer.
JAB
Anyway, the only thing now is that your version only inserts something once, while willehr apparently wants something that will insert a `\n` every three characters in the original data.
JAB
In any case this answer with its comments have solved my question. Thanks to all :)
willehr
A: 
with open(file, 'r+') as f:
    data = f.read()
    f.seek(0)

    for i in range(len(data)): # could also use 'for i, chara in enumerate(data):' and then 'f.write(chara)' instead of 'f.write(data[i])'
        if (i + 1) % 3 == 0:  # could also do 'if i % 3 == 2:', but that may be slightly confusing
            f.write('\n')
        else:
            f.write(data[i])

I don't think it's all that Pythonic (due to the range(len(data))), but it should work, unless your data file is really really large (in which case you'll have to process the data in the file part by part and store the results in another file to prevent overwriting data you haven't processed yet).

(More on the with statement.)

JAB
A: 

You want to achieve "insert" rather than "overwrite" functionality. There might be a library to do this, but you could also do it pretty simply manually. The basic idea here is to copy your 9-character line into a string, and split that string, inserting newlines where desired. For example:

f = open(file,"r+")
s = f.readline()
l = s[0:3] + "\n" + s[3:6] + "\n" + s[6:9]
f.seek(-9,1)
f.write(l)

The seek() and write() might not be exactly what you need but they should be close.

Matt Ball
A: 

You can think a file is just an array of characters, and if you want to insert a new element in the middle of an array, then you have to shift all the elements that are after it.

You could do what you say if the file contained a "linked list" of chars or "extends", but then you would need a special editor to see it sequentially.

fortran