2013-06-11 13 views
6

Quindi ho bisogno di registrare un set di 4 numeri interi i cui valori sono diversi per ogni secondo del giorno. cioè .:Modifica di una singola riga in un file di testo di grandi dimensioni

#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)] 

Ora, ovviamente una matrice bidimensionale (gah sua pitone, LIST) il cui primo indice di lunghezza è 86400 è assolutamente impossibile. Invece voglio creare un file di testo con 86.400 righe formattate come ad esempio:

numSec data0 data1 data2 data3 

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

E come vengono prelevati campioni, voglio essere in grado di modificare questo file, anzi, voglio essere in grado di modificare la linea di il file il cui numSec = il secondo il campione è stato preso. Ad esempio, un campione prelevato a numSec = 2 (2 secondi dopo la mezzanotte) potrebbero causare il mio programma per modificare il file in modo che:

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

sembra abbastanza facile, ho anche letto un sacco di posti che hanno dimostrato come riscrivi un singolo in un file di testo. Il problema è che richiedono tutti di leggere l'intero file. Non voglio che il mio programma stia leggendo 86.400 linee al secondo.

Così arriviamo alla mia domanda: Posso leggere una singola riga in un file di testo, modificarla e scriverla di nuovo nel file, senza leggere l'intero file ogni volta che è necessario apportare una modifica?

P.S. Devo notare che sto usando Ubuntu 12.04 (Precise) e questo è per l'uso in un nodo ROS

PPS Questo programma verrà eseguito per un numero arbitrario di giorni in modo che ogni "secondo" di dati possa essere letto e riscritto molte volte . Un'altra ragione per cui vorrei usare un file è se il sistema deve essere spento, vorrei salvare le distribuzioni per la prossima volta che viene eseguito.

+7

Se ogni voce nel file ha una lunghezza fissa, forse 'mmap'. Altrimenti, considera il database. – Jokester

+0

Se ciascuna voce ha una lunghezza fissa, si può semplicemente aprire il file in modalità binaria, calcolare l'offset, 'seek' e' write' in posizione.(Funzionerà anche in modalità testo, purché si tenga conto delle nuove righe e delle larghezze del char, ma è tecnicamente illegale.) Tuttavia, 'mmap' sarà probabilmente più semplice, quindi da +1 a jokester. – abarnert

+1

Cosa ti fa pensare che la memorizzazione di 86400 serie di 5 numeri è un problema? In ogni caso, è necessario scrivere, in media, metà del file ogni secondo. Inoltre, ogni secondo avrà a che fare con la linea immediatamente successiva alla riga precedente - perché non tenere tutto in memoria? – Neil

risposta

3

Potrebbe essere necessario modificarlo un po 'e si assume che tutte le linee siano della stessa lunghezza. Per questo, ho dovuto riempire la prima colonna di una larghezza fissa. Ma se non vuoi il padding, dovresti essere in grado di calcolare il numero di numeri 1,2,3,4, .. cifre prima di una particolare riga.

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]) 
+0

Grazie per la tua risposta, mentre sto avendo qualche problema a decifrare write_line (non ti preoccupare lo scoprirò) Vedo che stai ancora dichiarando la matrice bidimensionale. Il problema della lettura/scrittura è quello di evitare quella struttura, includendo quindi l'uso della lettura/scrittura non necessario. Credo di avere una nuova domanda, 86400 serie di 5 numeri non sono così grandiose come un maiale spaziale? – RoboCop87

+0

@ RoboCop87, l'ho dichiarato solo per popolare il file di output per il test. Non hai bisogno di un array 2d. Ma è necessario scrivere un file iniziale. Però quella struttura dovrebbe usare meno di 10 MB. – perreal

+0

Non sono sicuro che tu abbia familiarità con ROS (non lo sono assolutamente, e dovrei usarlo) ma da quello che ho capito gestisce un sacco di programmi allo stesso tempo ed è molto oneroso per il tuo sistema . Non sono sicuro di quanto 10 MB incidano su un sistema del genere, motivo per cui stavo cercando di essere cauto utilizzando il file. Sarebbe a malapena un dirigibile nel campo dell'informatica? O farebbe la differenza? – RoboCop87

2

Se le linee sono di lunghezze diverse, tutto quello che segue la riga modificata si troverà nella posizione sbagliata e sarà necessario riscrivere tutte quelle righe. Se tutte le linee hanno la stessa lunghezza, è possibile effettuare il seek() e write() i nuovi dati calcolando l'offset della riga nel file. Vedi Python File Objects per maggiori informazioni.

0

Non sono sicuro che sia utile memorizzare 345600 (86400 * 4) volte a 0,25. Basta memorizzare il valore predefinito nella prima riga. Aggiunge una riga alla volta. Se i timestamp non vengono ordinati, inseriscili come sono e al termine della giornata, ordina il contenuto del file una volta e riempi i timbri mancanti con il valore predefinito. Esempio:

default: 0.25 
2 .70 .10 .10 .10 
3 .80 .20 .20 .20 
1 .50 .30 .30 .30 
5 .40 .30 .30 .30 

processo Successivamente questo file per ottenere questo:

1 .50 .30 .30 .30 
2 .70 .10 .10 .10 
3 .80 .20 .20 .20 
4 .25 .25 .25 .25 
5 .40 .30 .30 .30 
+0

Vedo quello che stai dicendo, tuttavia questo programma verrà eseguito per un numero arbitrario di giorni, quindi l'aggiunta di uno alla volta non sarebbe una soluzione efficace. – RoboCop87

0

Se fossi in te, vorrei utilizzare un database SQLite per memorizzare i record. La chiave sarebbe la seconda dell'osservazione e ogni riga sarebbe composta da 4 valori. L'aggiornamento e la modifica sarebbero molto più efficienti.

Problemi correlati