2009-02-04 8 views
8

Necesito crear un programa java que creará un hilo para buscar un archivo en una carpeta particular (carpeta fuente) y recoger el archivo inmediatamente para el proceso (convertirlo a formato de archivo csv) una vez que encuentre el archivo en el Carpeta de origen. Problema al que me enfrento ahora es que el archivo que llega a la carpeta de origen es de gran tamaño (la herramienta FTP se usa para copiar archivos del servidor a la carpeta de origen), thread está escogiendo ese archivo inmediatamente antes de copiarlo completamente a la carpeta fuente y lanzar una excepción. ¿Cómo detengo el hilo hasta que el archivo se copia completamente en la carpeta de origen? Tiene que elegir el archivo para procesarlo solo después de que el archivo se haya copiado por completo en la carpeta de origen.¿Cómo se manejan los archivos incompletos? Obteniendo la excepción

+0

Es bueno saber, ¿qué excepción? –

Respuesta

1

Suponiendo que haya ningún control sobre el proceso de FTP ...

Que sea así. Cuando obtenga la excepción, intente procesarla nuevamente la próxima vez. Repítalo hasta que el archivo sea procesado. Es bueno tener pocos atributos en caso de excepción para comprobarlo más tarde, como; nombre, última modificación, tamaño.

Compruebe la excepción exacta antes de decidir procesarla más adelante, la excepción puede ocurrir por algún otro motivo.

2

Si tiene algún control sobre el proceso que realiza el FTP, es posible que tenga que crear un "archivo de marca" en el directorio de origen inmediatamente DESPUÉS de que termine el ftp para el archivo grande.

Luego, su subproceso Java tiene que verificar la presencia de este archivo de indicador, si está presente, entonces hay un archivo listo para ser procesado en el directorio de origen. Antes de procesar el archivo grande, el hilo debe eliminar el archivo de indicador.

El archivo de marca puede ser cualquier cosa (incluso un archivo vacío).

3

Usted podría intentar cosas diferentes:

  • comprobar varias veces la fecha de la última modificación y el tamaño del archivo hasta que no cambia más de una determinada cantidad de tiempo, y luego procesarla. (Como lo señala qbeuek, esto no es seguro ni determinista.)
  • Solo procesa archivos con nombres que coinciden con ciertos criterios (por ejemplo, * .dat). Cambie el proceso de carga/descarga de FTP para cargar/descargar archivos con un nombre diferente (por ejemplo, * .dat.temp) y cambie el nombre de los archivos una vez que se hayan completado.
  • Descargue los archivos en una ubicación diferente y muévalos a su directorio de procesamiento una vez que estén completos.
  • Como dijo Vinegar, si no funciona la primera vez, inténtelo más tarde. :)
+0

No sé por qué tenemos votos a favor, a veces. La gente comienza a dispararlo a todas partes. 100 reputación es demasiado baja para vengar a alguien. Debe ser mayor, puede ser 1000 o 2000. –

+0

Bueno, a veces voto cosas solo para equilibrar los votos a la baja, dando al voto +8 puntos que de otra manera no recibirían, eso es algo. En este caso, hubiera votado tu respuesta de todos modos, difícil. – itsadok

+0

te he votado negativamente, porque el primer elemento de tu lista de sugerencias no es seguro ni determinista. – qbeuek

4

La forma más segura es descargar el archivo a una ubicación diferente y luego moverlo a la carpeta de destino.

Otra variación mencionada por Bombe es cambiar el nombre del archivo a alguna otra extensión después de la descarga y buscar solo archivos con esa extensión.

+0

+1 Esta no es la manera más segura, pero la única forma de hacerlo. Todas las demás opciones desperdician recursos o son inseguras :) –

4

Solo leo el archivo que no está en modo de escritura. Esto es más seguro ya que significa que no hay otro proceso escribiendo en este archivo. Puede verificar si el archivo no está en modo de escritura utilizando el método canWrite de la clase File.

Esta solución funciona bien para mí, ya que también tengo exactamente el mismo escenario al que se enfrenta.

0

Si su sistema operativo es Linux, y su kernel> 2.6.13, puede usar la API de notificación de eventos del sistema de archivos llamada inotify. Hay una implementación de Java aquí: https://bitbucket.org/nbargnesi/inotify-java.

Aquí hay un código de muestra (fuertemente inspirado en el sitio web).

 try { 
     Inotify i = new Inotify(); 
     InotifyEventListener e = new InotifyEventListener() { 

      @Override 
      public void filesystemEventOccurred(InotifyEvent e) { 
       System.out.println("inotify event occurred!"); 
      } 

      @Override 
      public void queueFull(EventQueueFull e) { 
       System.out.println("inotify event queue: " + e.getSource() + 
         " is full!"); 
      } 

     }; 
     i.addInotifyEventListener(e); 
     i.addWatch(System.getProperty("user.home"), Constants.IN_CLOSE_WRITE); 
    } catch (UnsatisfiedLinkError e) { 
     System.err.println("unsatisfied link error"); 
    } catch (UserLimitException e) { 
     System.err.println("user limit exception"); 
    } catch (SystemLimitException e) { 
     System.err.println("system limit exception"); 
    } catch (InsufficientKernelMemoryException e) { 
     System.err.println("insufficient kernel memory exception"); 
    } 
0

Esto está en Grails y estoy usando FileUtils Biblioteca de la fama Commons Apache. La función sizeof devuelve el tamaño en bytes.

def fileModified = sourceFile.lastModified() 
    def fileSize = FileUtils.sizeOf(sourceFile) 

    Thread.sleep(3000) //sleep to calculate size difference if the file is currently getting copied 

    if((fileSize != FileUtils.sizeOf(sourceFile)) && (fileModified != sourceFile.lastModified())) //the file is still getting copied to return 
    { 
     if(log.infoEnabled) 
      log.info("File is getting copied!") 
     return 
    } 

    Thread.sleep(1000) //breather for picking up file just copied. 

Tenga en cuenta que esto también depende de lo que la utilidad o el sistema operativo que está utilizando para transferir los archivos. La apuesta más segura es copiar el archivo que se ha copiado o se ha copiado a un archivo o directorio diferente. El proceso de copia es robusto y le asegura que el archivo está presente después del proceso de copiado. El que estoy usando proviene de la API de commons.

FileUtils.copyFileToDirectory (f Archivo, Directorio D)

Si va a copiar un archivo enorme que está en proceso de ser copiado ten en cuenta que esto llevará tiempo y que le gustaría empezar este hilo en paralelo o mejor tener una aplicación separada dedicada para el proceso de transferencia.

Cuestiones relacionadas