Dudas sobre manejo de archivos

Facon p0stm4n en gmail.com
Sab Jul 5 23:12:56 CEST 2008


¡Hola Comunidad!, soy nuevo aquí desde hace poco, y desde entonces he
leído algunos digest, que se crean para los usuarios como resumen,
algunos de los cuales me han resultado verdaderamente útiles para lo
que estoy intentando desarrollar.

De momento se poco de Python, pero poco a poco voy aprendiendo
cositas, y si necesito algo suelo mirar la documentación o googlear,
para encontrar una respuesta, sin embargo en esta ocasión estoy
estantacado porque no se por donde tirar, estoy desarrollando un
Cortador de Archivos que permita dividir un Archivo en varios trozos
de tantos MBs, de forma que si por ejemplo tengo un archivo llamado
"prueba.zip" de 3MB, el programa me crea: "prueba.zip.0",
"prueba.zip.1" y "prueba.zip.2" de 1MB cada uno, hasta hay bien porque
lo he conseguido, puedo trocear archivos de más de 6.69 GB (Es con el
último archivo que probe).

Mi problema consiste en que ha pesar de que puede con casi cualquier
archivo en cuanto a tamaño se refiere, el problema es el tamaño de los
trozos, que ha partir de 500 MB me da el error "Memory Error", debido
a que es demasiado extenso los datos que añado al string, asi que
decidi hacerlo por arrays (y me funciona), pero el problema es que
para el último archivo con el seek(), tengo el problema de que cuando
escribe en el último archivo, que me pone repetido.

Funciona:

$ python cortador.py archivo_origen tamaño destino

El tamaño es en bytes.

El código:

cortador.py:

# -*- coding: cp1252 -*-
# Cortador by Facon
# Gracias a Google y Documentación de Python
# Agradecimientos a http://www.elhacker.net, en especial a Novlucker

import string
import os
import sys

ruta = sys.argv[1] # Archivo a dividir
nombre_archivo = os.path.basename(ruta) # Obtener nombre real del archivo
tamano_trozo = sys.argv[2] # Tamaño de los trozos (Bytes xDDDD)
destino = sys.argv[3] # Destino de los Trozos
destino2 = destino
tamano_trozo = int(tamano_trozo) # Pasamos argumento de String a Integer
tamano = os.path.getsize(ruta) # Tamaño del Archivo (Bytes)
print "\nTamaño: " + repr(tamano) + " Bytes\n\nParticionando Archivo,
por favor espere..." # Imprimir Tamaño del Archivo (Bytes)
datos = ['', '', ''] # Datos del buffer
posicion = 0 # Para posicionarse en los datos a leer
i = 0 # Para Hacer .0, .1, .2, .3, .4, etc...
f = open (ruta, 'rb') # Abrimos archivo
while posicion <= tamano: # Creamos bucle que diga que si posicion
menor o igual que tamaño hago lo que esta a continuación
    destino = destino + nombre_archivo + "." + repr(i) # Crear nombre
del archivo prueba.jpg.0, prueba.jpg.1, prueba.jpg.*
    print "Creado: " + destino
    j = open (destino, 'ab') # Creamos el archivo prueba.jpg.*
    datos = ['', '', '']
    if tamano_trozo >= 419430400:
        if i == 0:
            datos[0] = f.read(tamano_trozo/3) # Datos toma lo leido del buffer
            f.seek(tamano_trozo/3)
            datos[1] = f.read (tamano_trozo/3) # Datos toma lo leido del buffer
            f.seek(tamano_trozo/3)
            datos[2] = f.read (tamano_trozo/3) # Datos toma lo leido del buffer
            f.seek(tamano_trozo/3)
            j.write(datos[0]) # Escribimos en el archivo.
            j.write(datos[1])
            j.write(datos[2])
            j.close() # Cerramos archivo
            posicion = tamano_trozo # Metemos la posición siguiente en
la integer
            i = i + 1 # Sumamos 1 a la variable integer
        else:
            f.seek (posicion) # Función que va al byte con el valor de posición
            datos[0] = f.read(tamano_trozo/3) # Poner datos (X bytes
de info.) en la variable desde esa posición
            f.seek(tamano_trozo/3)
            az = f.seek(tamano_trozo/3)
            datos[1] = f.read(tamano_trozo/3)
            f.seek(tamano_trozo/3)
            ad = f.seek(tamano_trozo/3)
            datos[2] = f.read(tamano_trozo/3)
            f.seek(tamano_trozo/3)
            if az == tamano or ad == tamano:
                datos[1] = ''
                datos[2] = ''
            j.write(datos[0]) # Escribimos en archivo
            j.write(datos[1])
            j.write(datos[2])
            posicion = posicion + tamano_trozo # Vamos una posicion más avanzada
            j.close() # Cerramos archivo
            i = i + 1 # Sumamos 1 a la variable integer
    else:
        if i == 0:
            datos[0] = f.read(tamano_trozo) # Datos toma lo leido del buffer
            j.write(datos[0]) # Escribimos en el archivo.
            j.close() # Cerramos archivo
            posicion = tamano_trozo # Metemos la posición siguiente en
la integer
            i = i + 1 # Sumamos 1 a la variable integer
        else:
            f.seek (posicion) # Función que va al byte con el valor de posición
            datos[0] = f.read(tamano_trozo) # Poner datos (X bytes de
info.) en la variable desde esa posición
            j.write(datos[0]) # Escribimos en archivo
            posicion = posicion + tamano_trozo # Vamos una posicion más avanzada
            j.close() # Cerramos archivo
            i = i + 1 # Sumamos 1 a la variable integer
    destino = destino2
f.close() # Cerramos archivo principal

x = open (destino2 + nombre_archivo + ".bat", 'w') # A partir de aquí
creamos el .bat para pegar archivos
x.write('copy /b "'+ nombre_archivo + '.0" "' + nombre_archivo + '"\n')
z = 1
while z<i:
    x.write('copy /b "'+ nombre_archivo +'"+"'+ nombre_archivo +'.'+
repr(z)+ '"\n')
    z = z + 1
x.close()

# x = open ('pegador_linux', 'w') # Creamos el equivalente .bat para
Linux es decir para Bash
# x.write('#!/bin/bash\n')

-- FIN CÓDIGO --

Pueden copiar como quiera, lo puse en
_http://code.google.com/p/pythonprogramas/ bajo GPL v3, para que hagan
lo que quieran con el código.

Por favor ayudenme!.
_______________________________________________
Lista de correo Python-es 
http://listas.aditel.org/listinfo/python-es
FAQ: http://listas.aditel.org/faqpyes





Más información sobre la lista de distribución Python-es