He estado tratando de pensar en una forma de hacer lo siguiente:

Se abre y lee un archivo. El archivo contiene lo siguiente

15;0
2;0

Las líneas se leen, el primer dígito de la línea reemplaza al segundo y el primer dígito de la línea se reemplaza por 0:

f = open("data.txt", "r+")

for line in f:
    if line != "\n":
        lineList = line.replace("\n", "").split(";")
        lineList[1] = lineList[0]
        lineList[0] = "0"
        dataLine = lineList[0] + ";" + lineList[1]
        f.write(dataLine)

f.close()

El problema ocurre al escribir la línea en el archivo. ¿Cómo puedo escribir ambas líneas al final del archivo y eliminar las dos primeras líneas? Gracias

-1
Johny 13 may. 2016 a las 19:09

3 respuestas

La mejor respuesta

La manera más rápida de implementar la solución (y probablemente una forma más lógica correcta) es leer primero el contenido del archivo dentro de un administrador de contexto y luego escribir los datos procesados en el mismo archivo dentro de otro administrador de contexto:

data = list()
with open("data.txt", "r") as f:
    for line in f.readlines():
        if line != '\n':
            listLine = line.split(";")
            data.append("0;{}\n".format(listLine[0]))

with open('data.txt', 'w') as f:
    for line in data:
        f.write(line)

Además, no necesita la sobrecarga de asignar diferentes valores a la lista listLine y luego crear una entrada de datos para escribir en su archivo. Solo usa directamente lo que ya tienes.

La desventaja de este método es el uso de la memoria: si su archivo será más grande que su memoria, necesitará otro enfoque.

3
iulian 13 may. 2016 a las 16:37

Revisa tu código.

listLine = line.split(";")
lineList[1] = lineList[0]
lineList[0] = "0"

Establece la variable listLine, y luego llama a lineList.

1
Stevo Mitric 13 may. 2016 a las 16:18

La solución de @iulian es buena, pero como había advertido, requiere suficiente memoria para contener los datos. Si espera archivos grandes y puede aceptar temporalmente usando espacio en disco adicional (en lugar de RAM), puede escribir en un archivo de salida separado, escribir datos procesados y luego reemplazar el original con él:

import shutil
import tempfile

with open("data.txt", "rU") as f_in:
    f_out = tempfile.NamedTemporaryFile(delete=False)
    for line in f_in:
        if ";" in line:
            line = "0;{}\n".format(line.split(";", 1)[0])
        f_out.write(line)
    f_out.close()
    shutil.move(f_out.name, "data.txt")

No puede reemplazar los datos en el lugar si no puede garantizar que las nuevas líneas no sean más largas que las antiguas. Si esto sucede, se encontrará en una situación en la que su posición de escritura está más allá de la lectura, y el archivo estará dañado.

Sin embargo, si puede estar seguro de que ninguna línea nueva será más larga que la anterior (por ejemplo, definitivamente no hay líneas "1234;" en la fuente que se convertirían en "0;1234" después de la transformación), también puede hacerlo. :

with open("data.txt", "rb+") as f:
    write_offset = 0
    for line in f.readlines():
        line_len = new_len = len(line)
        if ";" in line:
            line = "0;{}\n".format(line.split(";", 1)[0])
            new_len = len(line)
            if new_len > line_len:
                # Bad things had just happened.
                raise RuntimeError("New line is longer than old one!"
                                   " File is now corrupt.")

        read_offset = f.tell()            # Remember the current position
        f.seek(write_offset)              # Seek to where we should write to
        f.write(line)
        write_offset += new_len
        f.seek(read_offset)               # Return to where we were

    # It could happen that new file is shorter.
    f.seek(write_offset)
    f.truncate()

Esta versión realiza las actualizaciones en el lugar y no tiene requisitos adicionales de memoria o disco.

(Tenga en cuenta que f.readlines() tiene un búfer, por lo que los resultados de f.tell() no serán desplazamientos de línea individuales, en caso de que desee utilizarlos por cualquier motivo. Para nuestros propósitos, podemos ignorar esto de forma segura aquí. )

0
drdaeman 13 may. 2016 a las 17:28