Ir al contenido


Foto

Error con archivos de 2Gb o mas


  • Por favor identifícate para responder
6 respuestas en este tema

#1 undying

undying

    Newbie

  • Miembros
  • Pip
  • 6 mensajes

Escrito 29 septiembre 2013 - 11:32

Buenas,

Es mi primer mensaje en el foro y espero podais ayudarme.

Estoy intentando hacer una app al estilo de hacha, el problema que tengo es que cuando intento cortar un archivo en 2 Gb o mas, no lo hace, me crea dos archivos uno del mismo tamaño que el original y otro con 0 bytes. Si por ejemplo quiero cortar un archivo de 15Gb me crea un archivo *.001 con un tamaño de 15Gb y otro *.002 con 0 bytes. En cambio si lo corto entre 1Gb o menos, no hay problema siendo basicamente el mismo codigo.

Os pongo el codigo para que veais por si os resulta de ayuda.



delphi
  1. ...
  2. if principal.opc8.Checked then
  3.     begin
  4.       LongF:= 2147483648;       
  5.       FileQ := TFileStream.Create(Archivo, fmOpenRead or fmShareDenyWrite);
  6.     try
  7.       for i := 1 to Trunc((FileQ.Size) / LongF) + 1 do
  8.       begin
  9.         ArchivoP := ChangeFileExt( Archivo, '.' + FormatFloat('000', i ) );
  10.         Stream := TFileStream.Create( ArchivoP, fmCreate or fmShareExclusive);
  11.       try
  12.         if (FileQ.Size - fileQ.Position) < LongF then
  13.           LongF := (FileQ.Size - FileQ.Position);
  14.           Stream.CopyFrom(FileQ, LongF);
  15.       finally
  16.         Stream.Free;
  17.       end;
  18.   end;
  19.   finally
  20.   FileQ.Free;
  21.   end;
  22.   end;
  23. ...



¿Sabeis por que no me deja crear archivos de 2Gb? Perdonad que os pregunte, igual es una tonteria pero como digo en mi prensentacion en el foro, soy novatillo y hay ciertas cosas que no veo.

Saludos y gracias.
  • 0

#2 Sergio

Sergio

    Advanced Member

  • Moderadores
  • PipPipPip
  • 1.092 mensajes
  • LocationMurcia, España

Escrito 30 septiembre 2013 - 03:25

Me juego una cerveza a que LongF es de algún tipo que no admite enteros superiores a 2 mil millones!

Si usas un longint resulta que justo su límite está en... 2GB expresado en bytes (2147483647)!

Así que, como tu longitud de fichero es el límite del longint +1, eso equivale a 0, y un copyfrom de 0 de largo copiaría todo el fichero (por eso tu .001 tiene 15GB), peeero, si multiplicas por dos, obtienes limite*2+2, es decir, 1, así que el segundo fichero tendría 1 byte, y el tercero creo que 2 bytes!

Prueba a cambiar LongF a tipo Ing64 a ver si así evitas el problema.
  • 0

#3 undying

undying

    Newbie

  • Miembros
  • Pip
  • 6 mensajes

Escrito 30 septiembre 2013 - 08:21

Exacto sergio, me he llevado 5 dias cambiando cosas menos lo que tenia que cambiar. Muchas gracias por la ayuda, ahora mismo estoy preparando un achivo de mas de 25 Gb para probar la aplicacion a tope y buscarle fallos en ese sentido.

Por otra parte, aprovecho para preguntarte un par de cosas:

1º ¿seria correcto o acertado que la aplicacion nada mas ejecutarse (por ejemplo en el evento onCreate del formulario) reconociera el SO y si este cumple los requisitos? y en caso de no ser asi, que mande un mensaje de error y se cierre.
2º Me gustaria implementar la comprobacion de archivos corruptos usando el hash md5, tiene delphi alguna función para esto?
imagino que seria pasando el primer archivo en este caso el .001 y con eso realizaria algun tipo de calculo ¿es asi? nunca hice nada de esto del md5. He encontrado algunas funciones MD5 en google, pero no tienen mas de 15 o 20 lineas y no sé si será lo que busco.

Saludos y una vez mas gracias.

  • 0

#4 Sergio

Sergio

    Advanced Member

  • Moderadores
  • PipPipPip
  • 1.092 mensajes
  • LocationMurcia, España

Escrito 01 octubre 2013 - 04:13

Exacto sergio, me he llevado 5 dias cambiando cosas menos lo que tenia que cambiar. Muchas gracias por la ayuda, ahora mismo estoy preparando un achivo de mas de 25 Gb para probar la aplicacion a tope y buscarle fallos en ese sentido.


Es un fallo clásico, siempre que un número te falle para ciertos valores altos y no para otros más bajos, es eso casi seguro.

1º ¿seria correcto o acertado que la aplicacion nada mas ejecutarse (por ejemplo en el evento onCreate del formulario) reconociera el SO y si este cumple los requisitos? y en caso de no ser asi, que mande un mensaje de error y se cierre.


Bueno, un programa tipo hacha no se qué requerimientos de SO tiene, parece que pocos... pero bueno, si quieres asegurarte de algo que se ha de cumplir, puedes hacerlo de varias formas, una opción es el onCreate, pero ojo, no puedes hacer un free en onCreate, así que quizas sea mejor tener un flag de que se ha comprobado ya, y en el onShow si ese flag es false lanzar la comprobación.

Otra opción es usar el .pas del propio proyecto y comprobarlo ANTES de cargar el formulario principal, si no cumple, avisas con un ShowMessage y matas la aplicación sin llegar a crear el form (igual si no cumple un requerimiento eso hace que el form no se pueda crear).

Recuerda que un proyecto es un .pas que se ejecuta como cualquier otro, y antes del application.start podrías comprobar cualquier cosa y si no sale bien, no ejecutas el start y en su lugar sacas un mensajito.


2º Me gustaria implementar la comprobacion de archivos corruptos usando el hash md5, tiene delphi alguna función para esto?
imagino que seria pasando el primer archivo en este caso el .001 y con eso realizaria algun tipo de calculo ¿es asi? nunca hice nada de esto del md5. He encontrado algunas funciones MD5 en google, pero no tienen mas de 15 o 20 lineas y no sé si será lo que busco.


Tienes funciones para calcular el MD5 de un fichero o stream en las Indy, por ejemplo. Son funciones sencillas, les pasas un stream, el algoritmo lo recorre entero, y te devuelve un array de bytes, con la grácia de que en el fichero cambias un solo bit, la salida cambia totalmente y se detecta sin problemas el cambio.

El MD5 lo tendrías que calcular del fichero original completo, eso te da una "huella dactilar" (una lista de bytes de una longitud fija, si quieres que sea "texto" deberías pasarle despues un algoritmo "Base64" que lo converte en texto, pero la longitud en modo texto aumenta, claro) que tendrias que añadir en tu primer fichero, de forma que el .001 lleve primero unos bytes con el MD5 y luego empieze el fichero en sí (o guardar un .MD5 y luego el .001 y siguientes, eso es más inseguro claro).

Luego, al recomponer el fichero, lees el MD5 del incio del .001, el resto del .001 es ya fichero, le añades el .002 etc., y al final terminas con un fichero de 25Gb ¿es el mismo que el original o ha pasado algo por el camino? Pues le calculas el MD5 y comparas con el que sacaste del .001, si son diferentes el fichero está corruto.
  • 0

#5 undying

undying

    Newbie

  • Miembros
  • Pip
  • 6 mensajes

Escrito 01 octubre 2013 - 01:15

Hola sergio, gracias por tus aportes e ideas, gracias a dios ya tengo solucionado estos dos puntos, el primero es lo que decias del tipo de variable longint o long64 y en cuanto al hash MD5, encontré una función en la web de seonae, para usar el hashing MD5 y sha1, me daba un error pero después de mirarme la función un buen rato pude encontrarlo. Por el momento todo va mas o menos bien, salvo un pequeño error que me da a la hora de abrir el explorardor de archivos y cerrarlo sin seleccionar ninguno (me manda el error de no poder abrir un archivo con nombre ""), y en eso estoy ahora.

Más adelante, me gustaría "encapsular" el proceso mas gordo que sería el del corte de archivos en si mismo dentro de un thread, es que tal cual está ahora mismo, se congela todo y no puedo ni minimizar la aplicacion cuando está funcionando.

Bueno, saludos y una vez mas gracias.
  • 0

#6 Rolphy Reyes

Rolphy Reyes

    Advanced Member

  • Moderadores
  • PipPipPip
  • 2.092 mensajes
  • LocationRepública Dominicana

Escrito 02 octubre 2013 - 05:49

Hola sergio, gracias por tus aportes e ideas, gracias a dios ya tengo solucionado estos dos puntos, el primero es lo que decias del tipo de variable longint o long64 y en cuanto al hash MD5, encontré una función en la web de seonae, para usar el hashing MD5 y sha1, me daba un error pero después de mirarme la función un buen rato pude encontrarlo. Por el momento todo va mas o menos bien, salvo un pequeño error que me da a la hora de abrir el explorardor de archivos y cerrarlo sin seleccionar ninguno (me manda el error de no poder abrir un archivo con nombre ""), y en eso estoy ahora.

Más adelante, me gustaría "encapsular" el proceso mas gordo que sería el del corte de archivos en si mismo dentro de un thread, es que tal cual está ahora mismo, se congela todo y no puedo ni minimizar la aplicacion cuando está funcionando.

Bueno, saludos y una vez mas gracias.


Saludos.

Existen varias posibles maneras de resolver  el congelamiento:
- La clase TThread.
- El uso del metodo ProcessMessages.
- Y por ultimo, pero no menos importante, una hecha en casa por nuestro compañero cHackAll.
  • 0

#7 undying

undying

    Newbie

  • Miembros
  • Pip
  • 6 mensajes

Escrito 02 octubre 2013 - 06:42

Buenas Rolphy Reyes

En cuanto acabe con unas lineas que tengo entre mano me miro mas detenidamente lo que comentas, prefiero ir acabando cosas antes de ponerme con otra sino va a ser un caos.

Gracias por la sugerencia! saludos.
  • 0




IP.Board spam blocked by CleanTalk.