Hola buenas, después de una especie de batalla de programadores que tuve con webultra
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
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:
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.
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:
File.BinaryJoin:
File.BinaryAutoJoin:


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:
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
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
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
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