37 mensajes Página 1 de 2
Hola buenas, después de una especie de batalla de programadores que tuve con webultra :pc: he terminado de hacer mi plugin, el plugin parte y une archivos binarios al tamaño que le digas por lo que no es muy complicado :hypno:

En el plugin he puesto un ejemplo simple del funcionamiento con el que puedes separar archivos y volverlos a unir con el tamaño que quieras, además de poder controlar el tamaño del bloque de lectura/escritura que quieres utilizar.

Versión 1.0:
Contenido Oculto: ON
	<br />Usted necesita responder en este tema para ver el contenido oculto.


A la hora de poner el Blocksize es aconsejable poner un tamaño con el que se pueda dividir el tamaño del archivo destino, porque si no da error el plugin.
Por ejemplo, si pones para partir el archivo en cachos de 1000KB puedes poner un blocksize de 5, 10, 20, 50, 100, 200, 250, 500 y 1000 por ejemplo, aunque puede que me deje alguno...

También es aconsejable usar un blocksize de 100Kb en el caso de que el tamaño destino sea múltiplo de 100, ya que es más rápido partiendo el archivo, aquí os dejo unas pruebas que hice con el File.BinarySplit.

Spoiler: Mostrar
1KB: 7' 36"
10KB: 1' 9"
100KB: 25"
1.000KB: 29"
10.000KB: 32"
100.000KB: 1' 30"


Las pruebas las hice con un archivo de 1.000.000 de KB, partiéndolo en partes de 100.000KB y con los tamaños de bloque que pongo. En el caso de no especificar tamaño de bloque el plugin toma 10KB por defecto.

También os dejo el código para que le echéis un vistazo si queréis:

File.BinarySplit:
function File.BinarySplit(filePath, folderPath, sizeKB, blocksizeKB, CallbackFunction, CallbackInSize)
        if blocksizeKB == nil then blocksizeKB = 10; end
        if sizeKB%blocksizeKB ~= 0 then --Comprueba si el tamaño del archivo es múltiplo del tamaño de bloque
                Application.SetLastError(9999); return "The File.SplitBinary function only accepts file sizes multiples of blocksize"; --Si no es múltiplo devuelve este error
        else --en caso contrario continua
                local inputfile = io.open(filePath, "rb"); --Abre el archivo de origen en modo lectura(r)  y binario(b)
                if inputfile then --Si se ha abierto correctamente continua
                        local filesize = inputfile:seek("end"); --Calcula el tamaño del archivo iendo al final y devolviendo la posición
                        local totalsize = 0
                        inputfile:seek("set", 0); --Vuelve al principio del archivo para comenzar a partirlo.
                        local partes = Math.Round(filesize / (sizeKB*1024), 0); if filesize%(sizeKB*1024) ~= 0 then partes = partes+1; end; --Calcula el número de partes en las que se partirá el archvo
                        for j = 1, partes do --Repite el código de abajo tantas veces como partes haya
                                local destfile = io.open(folderPath.."\\"..String.SplitPath(filePath).Filename..String.SplitPath(filePath).Extension.."."..String.Repeat("0", String.Length(tostring(partes))-String.Length(j))..j, "wb"); --Abre el archivo destino en modo escritura(w) y binario(b)
                                if destfile then --Si el archivo destino se ha abierto corréctamente continua
                                        while destfile:seek() < (sizeKB*1024) do --Repite el bucle hasta que el archivo destino tiene el tamaño deseado
                                                local bloque = inputfile:read(blocksizeKB*1024); --Lee el tamaño de bloque seleccionado del archivo origen
                                                if(not bloque)then break; end --Si no hay datos de origen (final de archivo) entonces rompe el bucle
                                                if CallbackFunction ~= nil then --Comprueba si hay funcion callback
                                                        local continuar = ""
                                                        if CallbackInSize == true then --Comprueba si queremos el callback en tamaño o %
                                                                continuar = CallbackFunction(inputfile:seek(), filesize); --Si lo queremos en tamaño ejecuta el callback con los dos valores
                                                        else
                                                                continuar = CallbackFunction(Math.Round((inputfile:seek() / filesize) * 100, 0)); --Si lo que queremos es % entonces calcula cual sería y ejecuta el callback con ese valor
                                                        end
                                                        if continuar == false then --Si el callback devuelve false...
                                                                destfile:close(); inputfile:close(); -- Se cierran los archivos origen y destino, y...
                                                                Application.SetLastError(1027); return _tblErrorMessages[1027]; --Se devuelve un código de error
                                                        end
                                                end
                                                destfile:write(bloque); --En el caso de que no se haya llegado al final del archivo ni se haya devuelto false en el callback escribe los 10KB al archivo.
                                        end
                                        totalsize = totalsize + destfile:seek("end"); --calcula el tamaño del archivo destino y lo suma al tamaño total de los archivos.
                                        destfile:close(); --Cierra el archivo destino
                                else
                                        Application.SetLastError(1004); return _tblErrorMessages[1004]; --Si el archivo destino no se abrió corréctamente devuelve un código de error
                                end
                                if(inputfile:seek() == filesize)then break;end --Esta línea más bien podría borrarse pero la mantengo por si acaso, hace que si se llega al final del archivo de origen entonces termina el bucle "for"
                        end
                        inputfile:close(); --Cierra el archivo de origen.
                        if totalsize == filesize then --Comprueba si el total de los archivos destino coincide con el tamaño del archivo de origen
                                Application.SetLastError(0); return 0; --Si el tamaño es igual devuelve el código de error 0 que significa que todo ha ido bien
                        else
                                Application.SetLastError(9999); return _tblErrorMessages[9999]; --En caso contrario devuelve un código de error desconocido (9999)
                        end
                else
                        Application.SetLastError(1021); return _tblErrorMessages[1021]; --Si no se abrió el archivo origen corréctamente devuelve un código de error
                end
        end
end
Parsed in 0.009 seconds, using GeSHi 1.0.8.9


File.BinaryJoin:
function File.BinaryJoin(FilePath, FileDest, blocksizeKB, CallbackFunction, CallbackInSize)
        if blocksizeKB == nil then blocksizeKB = 100; end
        if io.open(FilePath) then --Comprueba que existe el archivo de origen
                local tamext = String.Length(String.SplitPath(FilePath).Extension)-1 --Saca el número de caracteres de la extensión
                if tamext > 0 then --Si tiene extensión continua, eso ayuda a distinguir las carpetas también.
                        local total = 0;
                        local totalsize = 0
                                               
                        for j = 1, String.ToNumber(String.Repeat("9", tamext)) do --Comienza un bucle que se ejecuta x veces 9, si la extensión es .1 serían 9, si es .01 serían 99, y así sucesivamente
                                local inputfile = io.open(String.SplitPath(FilePath).Drive..String.SplitPath(FilePath).Folder..String.SplitPath(FilePath).Filename.."."..String.Repeat("0", tamext-(String.Length(j)))..j, "rb"); --Abre el archivo de origen
                                if inputfile then       --Si el archivo origen se ha abierto corréctamente entonces continua
                                        totalsize = totalsize + inputfile:seek("end"); --Suma al total el tamaño del fichero origen
                                        inputfile:close(); --Cierra el archivo origen
                                        total = total + 1 --Suma 1 al total de archivos origen, cosa útil más adelante
                                else
                                        --En caso de no existir el archivo origen cancela el bucle para que no se ejecute más veces de las devidas
                                        --Por ejemplo, tenemos un fichero .01 y el último es .11, es inutil seguir buscando del .12 hasta el .99
                                        break
                                end
                        end
                       
                        local outputfile = io.open(FileDest, "wb") --Abre el archivo destino en modo escritura(w) y binario(b)
                        if outputfile then --Si se abre el archivo destino corréctamente continua
                                for j = 1, total do --Repite el bucle tantas veces como archivos haya.
                                        local inputfile = io.open(String.SplitPath(FilePath).Drive..String.SplitPath(FilePath).Folder..String.SplitPath(FilePath).Filename.."."..String.Repeat("0", tamext-(String.Length(j)))..j, "rb"); --Abre el archivo de origen en modo lectura(r) y binario(b)
                                        while true do --Hace un bucle infinito
                                                local bloque = inputfile:read(10240); --Lee 10KB del arhcivo origen
                                                if(not bloque)then break; end --Si se llega al final del archivo origen entonces sale del bucle infinito
                                                if CallbackFunction ~= nil then --Comprueba si hay funcion callback
                                                        local continuar = ""
                                                        if CallbackInSize == true then --Comprueba si los datos de la función callback los queremos en tamaño o %
                                                                continuar = CallbackFunction(outputfile:seek(), totalsize); --En caso de quererlo en tamaño envía los dos valores al callback
                                                        else
                                                                continuar = CallbackFunction(Math.Round((outputfile:seek() / totalsize) * 100, 0)); --En caso contrario calcula el % y lo envia al callback
                                                        end
                                                        if continuar == false then --Si la función callback devuelve false entonces cierra los archivos y cancela el progreso
                                                                inputfile:close(); outputfile:close();
                                                                Application.SetLastError(1027); return _tblErrorMessages[1027];
                                                        end
                                                end
                                                outputfile:write(bloque); --Escribe el bloque de 10KB que leímos antes
                                        end
                                        inputfile:close(); --Cierra el archivo de origen
                                end
                                if outputfile:seek("end") == totalsize then --Comprueba que el tamaño del destino coincide con el calculado arriba
                                        outputfile:close(); --Cierra el archivo destino
                                        Application.SetLastError(0); return 0; --Si el tamaño es igual devuelve el código de error 0 que significa que todo ha ido bien
                                else
                                        outputfile:close(); --Cierra el archivo destino
                                        Application.SetLastError(9999); return _tblErrorMessages[9999]; --En caso contrario devuelve un código de error desconocido (9999)
                                end
                        else
                                Application.SetLastError(1004); return _tblErrorMessages[1004]; --Si el archivo destino no se abrió corréctamente devuelve un código de error
                        end
                else
                        Application.SetLastError(1019); return _tblErrorMessages[1019]; --Si la extensión es nula devuelve un código de error
                end
        else
                Application.SetLastError(1021); return _tblErrorMessages[1021]; --Si no se abrió el archivo origen corréctamente devuelve un código de error
        end
end
Parsed in 0.007 seconds, using GeSHi 1.0.8.9


File.BinaryAutoJoin:
function File.BinaryAutoJoin(FilePath, blocksizeKB, CallbackFunction, CallbackInSize)
        --La única diferencia entre JoinBinary y AutoJoinBinary es la selección o no del archivo destino
        --por lo que lo único que hace este código es sacarlo automáticamente del archivo origen y ejecutar
        --el File.JoinBinary
        local FileDest = String.SplitPath(FilePath).Drive..String.SplitPath(FilePath).Folder..String.SplitPath(FilePath).Filename
        return File.BinaryJoin(FilePath, FileDest, blocksizeKB, CallbackFunction, CallbackInSize)
end
Parsed in 0.002 seconds, using GeSHi 1.0.8.9
Interensate..., Gracias
Imagen
Gracias daniel , tiene buena pinta ;)
pisharrrrako! XDD
Heyy carsonzillo!!! xD

Se me olvidó decir que lo he probado varias veces y funciona pero si encontráis algún error decírmelo ;).

PDTA: Creo que más menos he aprendido lo suficiente del io.open y el :seek para poder añadirle cabecera al archivo, que la puedo usar para varias cosas como por ejemplo reconocer si el archivo ha sido partido con el plugin, guardar la extensión o incluso ponerle el CRC para que a la hora de volverlo a unir compruebe si lo ha hecho corréctamente.
good

thank you
....................
Imagen
gracias :D
gracias, voy a descargar.
very thanx for you :SOS:
Daniel no sirve, no podes partir archivos mayores a 2GB.
Me parece que habria que hacerlo en otro lenguaje al plugin, fijate si se puede cambiar el sistema de manejo de archivos por otro.

Saludos!
Podría intentar portarlo a C++ y crear una DLL lo único es que de C++ no se mucho y a lo mejor tardo...
Hola
Te comento que encontre una solución al problema de los archivos mayores a 2GB.

Lo que tienes que hacer es reemplazar:
local filesize = inputfile:seek("end"); --Calcula el tamaño del archivo iendo al final y devolviendo la posición
 
Parsed in 0.002 seconds, using GeSHi 1.0.8.9


por esta declaración:
local filesize = File.GetSize(filePath); --Calcula el tamaño del archivo a partir
 
Parsed in 0.002 seconds, using GeSHi 1.0.8.9


La funcion seek es la que no puede procesar archivos mayores a 2gb, pero con la funcion GetSize que viene con AMS no hay ningun problema.

Otra cosa que te recomiendo es que cada vez que haces una declaracion del io de lua lo almacenes en dos variables en lugar de una, de esta forma si tiene un error en lugar de obtener solo nil obtienes un string con un mensaje de error. Es así como logre identificar el problema en tu codigo.

Entonces por ejemplo en vez de realizar la declaracion de esta forma:
local inputfile = io.open(filePath, "rb");
 
Parsed in 0.002 seconds, using GeSHi 1.0.8.9


Lo haces asi:
local inputfile, cError = io.open(filePath, "rb");
 
Parsed in 0.002 seconds, using GeSHi 1.0.8.9


Cuando la funcion open falla, devuelve dos parametros: nil y el string con la descripcion del error ocurrido.
Entonces puedes obtener informacion sobre el error leyendo la variable cError.

Si te interesa puedo revisar tu codigo, implementar estos detalles y por que no agregar un poquito mas de funcionalidad.

Saludos!
thanks for topic very good.
thank you
???
WOOOW .. GOOD JOB
frankpo escribió: Hola
Te comento que encontre una solución al problema de los archivos mayores a 2GB.

Lo que tienes que hacer es reemplazar:
local filesize = inputfile:seek("end"); --Calcula el tamaño del archivo iendo al final y devolviendo la posición
 
Parsed in 0.002 seconds, using GeSHi 1.0.8.9


por esta declaración:
local filesize = File.GetSize(filePath); --Calcula el tamaño del archivo a partir
 
Parsed in 0.002 seconds, using GeSHi 1.0.8.9


La funcion seek es la que no puede procesar archivos mayores a 2gb, pero con la funcion GetSize que viene con AMS no hay ningun problema.

Otra cosa que te recomiendo es que cada vez que haces una declaracion del io de lua lo almacenes en dos variables en lugar de una, de esta forma si tiene un error en lugar de obtener solo nil obtienes un string con un mensaje de error. Es así como logre identificar el problema en tu codigo.

Entonces por ejemplo en vez de realizar la declaracion de esta forma:
local inputfile = io.open(filePath, "rb");
 
Parsed in 0.002 seconds, using GeSHi 1.0.8.9


Lo haces asi:
local inputfile, cError = io.open(filePath, "rb");
 
Parsed in 0.002 seconds, using GeSHi 1.0.8.9


Cuando la funcion open falla, devuelve dos parametros: nil y el string con la descripcion del error ocurrido.
Entonces puedes obtener informacion sobre el error leyendo la variable cError.

Si te interesa puedo revisar tu codigo, implementar estos detalles y por que no agregar un poquito mas de funcionalidad.

Saludos!


Gracias por esto, no lo vi y ya dejé un poco de lado la función ya que no la uso jejeje.
<p>
</p>
gracias
Muchas gracias Ceone.
The link is not found
Imagen
37 mensajes Página 1 de 2

¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 2 invitados