6
votes

Modification d'une seule ligne dans un grand fichier texte

Donc, j'ai besoin d'enregistrer un ensemble de 4 entiers dont les valeurs sont différentes pour chaque seconde de la journée. i.e.:

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

est évidemment un tableau de deux dimensions (GAH Son Python, liste) dont la première longueur d'index est de 86400 est assez pratique. Au lieu de cela, je souhaite créer un fichier texte avec 86400 lignes formatés comme tels: p> xxx pré>

et comme des échantillons sont pris, je veux pouvoir éditer ce fichier, Nay, je veux Pour pouvoir éditer la ligne du fichier dont NUMSEC = le second, l'échantillon a été pris. Par exemple, un échantillon pris à NumSec = 2 (2 secondes après minuit) entraînerait mon programme de modifier le fichier afin que: p> xxx pré>

semble assez facile, j'ai même lu Un tas de messages qui a démontré comment réécrire un seul dans un fichier texte. Le problème est que tous ont tous besoin de lire dans l'ensemble du dossier. Je ne veux pas que mon programme soit en train de lire 86 400 lignes chaque seconde. P>

Nous arrivons donc à ma question: puis-je lire une seule ligne dans un fichier texte, le modifier et l'écrire dans le fichier , sans lire l'ensemble du fichier chaque fois qu'un changement doit être effectué? P>

ps Je dois noter que je suis en cours d'exécution Ubuntu 12.04 (précis) et ceci est destiné à être utilisé dans un nœud ROS P>

PPS Ce programme sera exécuté pour une quantité arbitraire de jours afin que chaque "seconde" des données puisse être lue et réécrit plusieurs fois. En outre, une autre raison pour laquelle je voudrais utiliser un fichier est si le système doit être éteint, je voudrais enregistrer les distributions pendant la prochaine exécution. P> P>


15 commentaires

Si chaque entrée du fichier a une longueur fixe, peut-être mmap . Sinon, considérez la base de données.


Si chaque entrée a une longueur fixe, vous peut Ouvrez simplement le fichier en mode binaire, calculez le décalage, rechercher et écrire en place. (Cela fonctionnera également en mode texte aussi, tant que vous prenez en compte les nouvelles lignes et les largeurs de caractères, mais il est techniquement illégal.) Toutefois, MMAP va probablement être plus simple, donc +1 à Jokester .


Qu'est-ce qui vous fait penser que stocker 86400 séries de 5 chiffres est un problème? En tout état de cause, vous devez écrire, en moyenne, la moitié du fichier chaque seconde. De plus, chaque seconde traitera de la ligne immédiatement après la ligne précédente - pourquoi ne pas garder tout en mémoire?


Quelle est la fréquence des données accessibles après écrit? Et l'instance reste-t-elle en vie? Si tel est le cas, mettez-le en cache à une liste et enregistrez toutes les mises à jour X au fichier. Si vous ne voulez pas aller avec mmap ou une base de données.


Je ne comprends pas le problème. Si chaque seconde que vous mettez à jour le fichier avec la nouvelle valeur de quatre paires, pourquoi ne faites-vous pas simplement ajouter au fichier les données reçues dans chaque seconde? Après minuit, réinitialisez le fichier à zéro. Lors de la lecture, vous supposez que toutes les secondes au-dessus de la dernière deuxième lecture sont la valeur initialisée. Vous évitez l'initialisation et votre taille de fichier est plus faible jusqu'à la fin de la journée.


Avoir besoin d'écrire dans le "passé"? Je veux dire, avez-vous déjà besoin d'écrire à la ligne 2 après avoir écrit à la ligne 3?


@ Jokester, je peux les faire résoudre en utilisant des zéros de placement, si nécessaire.


@Neil, il semble juste que ce soit beaucoup, si ce n'est pas vraiment alors je suppose qu'aucun problème.


@sebastian, je suis désolé, je n'étais pas clair, cela sera réellement mis à jour chaque jour, ses probabilités de suivi d'un événement à certains moments d'une journée.


Êtes-vous coincé dans ce format de fichier? Je veux dire, pourquoi ne pas enregistrer que des données pertinentes et que vous traitez ultérieurement en supposant que les lignes «secondes» manquantes? Sauver les appels d'E / S semble être votre objectif.


Pendant ce temps, si vous voulez vraiment un tableau 2D, avez-vous envisagé d'utiliser numpy ou pandas au lieu de la liste native S de Liste s? En général, les choses seront un peu plus pratiques pour opérer, beaucoup plus rapides et plus compactes. En particulier, la rédaction d'un réseau de 86400 lignes ne nécessitera aucune boucle dans Python - bien sûr, il nécessitera toujours un I / O de 2 Mo, mais cela sera probablement presque instantané grâce à la mise en cache de disque et ne nécessitera presque pas de processeur.


@Sebastian je ne suis pas coincé dans un format particulier, je n'ai jamais traité de grandes quantités de données et pour une raison quelconque, je pensais que les fichiers texte pourraient être un bon moyen de traiter cela.


@Abarnert Je n'ai jamais entendu parler de Numpy ou de Panda, je ne sais pas à quel point la mise en cache de disque est, mais je ferai de la lecture et de voir si cela m'aidera.


Si votre intention est de sauvegarder des appels d'E / S dans le traitement en temps réel, je suggère de stocker uniquement des données pertinentes, c'est-à-dire les deuxième et les quatre paires valeurs. Ensuite, traitez le fichier afin d'élaborer, éventuellement un autre fichier, par exemple, de le nourrir à un programme de parcelle. Le traitement va lire chaque ligne définissant une valeur par défaut pour chaque seconde manquante du fichier. Mais tout dépend de vos besoins.


Les deux secondes et les quatre valeurs de paire sont les seules données pertinentes, comme vous l'avez dit. L'objectif est d'avoir une valeur de quatre paires pour chaque seconde de la journée, alors même si ce que vous suggérez de sauvegarderait beaucoup de temps et d'espace au début, car le fichier se riche, je rencontrerai toujours le même problème. J'apprécie très bien votre suggestion, je n'avais pas pensé à cette approche.


4 Réponses :


2
votes

Si les lignes sont de longueurs différentes, tout après que la ligne modifiée sera dans la mauvaise position et que vous devez réécrire toutes ces lignes. Si les lignes ont toutes une même longueur, vous pouvez recherche () et écrire () les nouvelles données en calculant le décalage de la ligne dans le fichier. Voir Objets de fichier Python pour plus d'informations.


0 commentaires

3
votes

Vous devrez peut-être modifier cela un peu et supposer que toutes les lignes sont de même longueur. Pour cela, je devais poser la première colonne à une largeur fixe. Mais si vous ne voulez pas de rembourrage, vous devriez pouvoir calculer le nombre de 1,2,3,4, .. chiffres de chiffres avant une rangée particulière.

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


8 commentaires

Merci de votre réponse, alors que j'ai eu des difficultés à décypphercer write_line (ne vous inquiétez pas, je vais le comprendre) Je vois que vous déclarez toujours la matrice bidimensionnelle. Le problème de la lecture / de l'écriture est d'éviter cette structure, y compris donc l'utilisation de lecture / écriture inutile. Je suppose que j'ai une nouvelle question, il y a 86400 séries de 5 chiffres, ce qui n'est vraiment pas si grand d'espace de porc d'espace?


@ ROBOCOP87, je lui ai dit simplement de remplir le fichier de sortie pour tester. Vous n'avez pas besoin d'un tableau 2D du tout. Mais vous devez écrire un fichier initial. Cette structure devrait cependant utiliser moins de 10 Mo.


Je ne sais pas si votre familier avec ROS (je ne suis certainement pas, et je suis censé l'utiliser) mais d'après ce que je comprends, il gère beaucoup de programmes en même temps et qui est très imposable sur votre système. Je ne sais pas combien de 10 Mo d'impact sur un système comme celui-là, c'est pourquoi j'essayais d'être prudent en utilisant le fichier. Serait-ce à peine un vignette dans la portée de l'informatique? Ou cela ferait-il une différence?


Je pense que vous irez bien avec des points de contrôle dans un fichier à des intervalles de 5 minutes avec une structure de données de mémoire si vous n'exécutez pas sur un système intégré. Il peut même être préférable de continuer à ajouter à un fichier et à démarrer un nouveau fichier chaque jour.


Aussi l'idée de la base de données est assez solide


mon ignorance Je pensais que l'utilisation du fichier texte de cette manière utilisait une base de données, une base de données étant une collection de données et un fichier texte peuplé étant une collection de données


Non, une base de données est tellement plus que cela. Vous n'aurez pas besoin d'écrire du code pour traiter des fichiers et vous pouvez faire toutes sortes de mises à jour de manière fiable.


Je vais examiner cela plus que. Merci!



0
votes

Je ne suis pas sûr s'il est utile de stocker 345600 (86400 * 4) fois un 0,25. Stockez simplement la valeur par défaut dans la première ligne. Que d'ajouter une ligne à la fois. Si les horodatages ne viennent pas dans l'ordre, mettez-les simplement comme ils le sont et après la journée terminée, triez une fois le contenu du fichier et remplissez les timbres d'heure manquantes avec la valeur par défaut. Exemple: xxx

Processez ensuite ce fichier pour obtenir ceci: xxx


1 commentaires

Je vois ce que vous dites, cependant, ce programme sera exécuté pour un nombre de jours arbitraires, il suffit de simplement ajouter un à la fois une solution efficace.



0
votes

Si j'étais vous, j'utiliserais une base de données SQLite pour stocker des enregistrements. La clé serait la deuxième de l'observation et chaque ligne serait composée de 4 valeurs. La mise à jour et la mise à jour serait beaucoup plus efficace.


0 commentaires