Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Editing a single line in a large text file

So I need to record a set of 4 integers whose values are different for every second of the day. i.e.:

#Here the values are initialized to the same value, however they will change as samples are taken
data = [[.25 for numData in range(4)] for numSecs in range(86400)]

Now obviously a two dimensional array(gah its python, LIST) whose first index length is 86400 is quite impractical. Instead I want to create a text file with 86400 lines formatted as such:

numSec data0 data1 data2 data3

0 .25 .25 .25 .25
1 .25 .25 .25 .25
2 .25 .25 .25 .25
...

And as samples are taken, I want to be able to edit this file, nay, I want to be able to edit the line of the file whose numSec = the second the sample was taken. For example, a sample taken at numSec = 2 (2 seconds after midnight) would cause my program to edit the file so that:

0 .25 .25 .25 .25
1 .25 .25 .25 .25
2 .70 .10 .10 .10
...

Seems easy enough, I have even read a bunch of posts which demonstrated how to rewrite a single in a text file. The problem is, they all require that you read in the whole file. I don't want my program to be reading 86,400 lines every second.

Thus we arrive at my question: Can I read a single line in a text file, edit it, and write it back to the file, without reading the entire file every single time a change needs to be made?

P.S. I should note I am running Ubuntu 12.04 (Precise) and this is for use in a ROS node

P.P.S This program will be running for an arbitrary amount of days so each "second" of data could be read and rewritten many times. Also another reason I would like to use a file is if the system needs to be shut off, I would like to save the distributions for the next time it is run.

like image 250
RoboCop87 Avatar asked Jun 11 '13 00:06

RoboCop87


1 Answers

You may need to modify this a bit and it assume that all lines are of the same length. For this, I had to pad the first column to a fixed width. But if you don't want padding you should be able to calculate the number of 1,2,3,4,.. digit numbers before a particular row.

data = [[.25 for numData in range(4)] for numSecs in range(86400)]
length_line=0

def write_line(f, sec, data):
    line="{:6d}".format(sec) + " " +" ".join(
            ["{:.2f}".format(dd) for dd in data])+"\n"
    f.write(line)
    return len(line)

with open('output', 'w') as of:
    for i,d in enumerate(data):
        length_line=write_line(of, i, d)

with open('output', 'rb+') as of:
    # modify the 2nd line:
    n = 2
    of.seek(n*length_line)
    write_line(of, n, [0.10,0.10,0.10,0.10])
    # modify the 10th line:
    n = 10
    of.seek(n*length_line)
    write_line(of, n, [0.10,0.10,0.10,0.10])
like image 131
perreal Avatar answered Oct 23 '22 10:10

perreal