Page 1 of 2

copiar muchisimos archivos de texto

Posted: Thu May 17, 2018 11:53 am
by wilsongamboa
compañeros buenos dias
Estoy tratando de crear un utilitario para respaldar archivos xml de un disco duro a otro en un servidor, el problema es que son muchos miles de ellos en el orden de 500000 archivos, lo estoy haciendo con
cFilein = 'z:\sistemas\xml\123456789.xml'
cFileOut = 'r:\respaldos\sistemas\xml\123456789.xml'

copy file ( cFilein ) to ( cFIleOut )

el programa se queda congelado ya he tratado de porner sysrefresh, estoy utilizando una window para esto ademas no me funcionan los meter que he puesto, la lectura la hago son directory() y me demora un minuto en la lectura pero al procesarlos se congela

aca algo del codigo donde se queda congelada la ventana

Code: Select all

method respaldo() class tWg_AlmacenXml

    local i
    local j
    local k
    local nLen
    local cFile
    local cFileOut
    for i = 1 to len( ::aCaminosfe ) //para cada almacen
        sysrefresh()
        ::oInterfaz:oWnd:SetMsg( ::aCaminosFe[ i ] )
        ::oInterfaz:oMeter:nTotal = len( ::aDirsfe )
        ::oInterfaz:oMeter:set( 0 )
        ::oInterfaz:oMeter:refresh()
        ::cPathFe    = ::aCaminosFe[ i ] //apunte al almacen
        if ::lStop
            exit
        end
        for j = 1 to len( ::aDirsfe ) //dentro del almacen cada directorio de data
            ::oInterfaz:oMeter:set( j )
            ::oInterfaz:oMeter:refresh()
            ::cSectionFe = ::aDirsfe[ j ]   //'compgen\autorizados\'  //apunte a directorio de data dentro del almacen
            ::cMascara   = ::aMascaras[ j ] // *.xml la terminacion de los archivos dentro de ese directorio
            ::oInterfaz:oWnd:SetMsg( 'leyendo .. ' + ::cPathfe + ::cSectionFe )
            //msginfo('voy a leer')
            ::leeData()  //leo los datos
            nLen = len( ::aData )
            ::oInterfaz:oWnd:SetMsg( 'proc .. ' + alltrim( str( nLen ) ) + ' archs ' + ::cPathRespaldo + ::cSectionFe )
            sysrefresh()
            //msginfo('ya lei')
            makedir( ::cPathRespaldo + ::cSectionFe ) //crea si no existe el directorio destino


            ::oInterfaz:oMeter1:nTotal = nLen
            ::oInterfaz:oMeter1:set( 0 )
            ::oInterfaz:oMeter1:refresh()
            ::oInterfaz:oWnd:refresh()
            for k = 1 to nLen

               if k % 10 == 0
                   sysrefresh()
                   //msginfo('acabo de refrescar')
                   ::oInterfaz:oWnd:SetMsg( ::cPathRespaldo + ::cSectionFe + str( k, 8 ) + ' / ' + str( nLen, 8 ) )
               end
               if ::lStop
                   exit
               end
               ::oInterfaz:oMeter1:set( k )
               ::oInterfaz:oMeter1:refresh()
               cFile    = ::cPathFe       + ::cSectionFe + ::aData[ k, 1 ]
               cFileOut = ::cPathRespaldo + ::cSectionFe + ::aData[ k, 1 ]
               //msginfo( cFile + CRLF + cFileOut )
               if !file( cFileOut )
                   copy file ( cFile ) to ( cFileOut )
               end
            next
            ::aData = {}
        next
    next


return nil
 
el codigo de la ventana es

Code: Select all

method ventana() class tWg_InterfazAlmacenXml

    local oSelf := Self

    DEFINE WINDOW ::oWnd FROM 0, 0 TO 450, 600 ;
        TITLE "Manejador de almacenes xml de facturación electrónica" PIXEL

    @ 050, 10 METER ::oMeter  VAR ::nActual  TOTAL ::nTotal  OF ::oWnd SIZE 235, 50 PIXEL
    @ 150, 10 METER ::oMeter1 VAR ::nActual1 TOTAL ::nTotal1 OF ::oWnd SIZE 235, 50 PIXEL
    @ 250, 10 BUTTON "&Parar Respaldo" OF ::oWnd SIZE 100, 50 ;
       ACTION ( oSelf:oAlmacen:lStop := .t. ) PIXEL

    //@ 350, 10 SAY ::oSay PROMPT "leyenda aca ...." OF ::oWnd SIZE 300, 50

    SET MESSAGE OF oSelf:oWnd TO 'mensajes del sistema de repaldos' NOINSET CLOCK DATE KEYBOARD

    ::oWnd:Say( 350, 10, 'leyendas van aca......', , , , .t. )


    ACTIVATE WINDOW ::oWnd on INIT ( oSelf:oAlmacen:oInterfaz := oSelf  ,;
                                     oSelf:oAlmacen:leeconfig()         ,;
                                     oSelf:oAlmacen:respaldo()          ,;
                                     oSelf:oWnd:end() )

return nil
 
alguien ha hecho algo parecido ?
me podrian dar unos consejos al respecto, muchas gracias de antemano

he probado con comando xcopy y se sale sin dar errores y no termina la copia, la idea es hacerlo de una manera automatizada

ademas de la forma que lo estoy haciendo tengo el inconveniente que las fechas son cambiadas de los ficheros si alguien sabe como copiarlos respetando la fecha de creacion

att

Wilson Gamboa A
Quito Ecuador

Re: copiar muchisimos archivos de texto

Posted: Thu May 17, 2018 12:09 pm
by hmpaquito
Hola,

Lo que yo haría sería primero determinar donde se produce el cuelgue del sistema. Para ello pondría unas trazas.
También quitaría momentaneamente los meters, para saber si originan el problema.

Para copiar con misma fecha: http://forums.fivetechsupport.com/viewt ... 05&start=0

Salu2

Re: copiar muchisimos archivos de texto

Posted: Thu May 17, 2018 2:16 pm
by wilsongamboa
muchsa gracias por rsponder
he quitado los meters y he puesto esa funcion que usa Rafa Carmona, ya copia con la misma fecha pero sigue congelandose la ventana
el problema esta cuando escribe en disco parece que se queda alli ya que ni siquiera aparece la leyenda que pongo cada 10 archivos copiados aca

Code: Select all

            for k = 1 to nLen

               if k % 10 == 0
                   sysrefresh()
                   //msginfo('acabo de refrescar')
                   ::oInterfaz:oWnd:SetMsg( ::cPathRespaldo + ::cSectionFe + str( k, 8 ) + ' / ' + str( nLen, 8 ) )
               end
               if ::lStop
                   exit
               end
               //::oInterfaz:oMeter1:set( k )
               //::oInterfaz:oMeter1:refresh()
               cFile    = ::cPathFe       + ::cSectionFe + ::aData[ k, 1 ]
               cFileOut = ::cPathRespaldo + ::cSectionFe + ::aData[ k, 1 ]
               //msginfo( cFile + CRLF + cFileOut )
               if !file( cFileOut )
                   //copy file ( cFile ) to ( cFileOut )
                   MYCOPYFILE( cFile , cFileOut, 0 )
               end
            next
 
esa leyenda no llega a aparecer en la ventana a pesar que si esta copiandose los archivos
estoy probando con 20000 archivos por directorio son como 3 y si funciona pero se queda congelado hasta terminar
podrias darme una idea de como poner una traza ?
perdon por la ignoracia

saludos
Wilson

Re: copiar muchisimos archivos de texto

Posted: Thu May 17, 2018 3:24 pm
by hmpaquito
Hola Wilson,

Mi idea de trazas se basa en grabar en un fichero log pistas de por donde va el proceso.

He comentado algunas cosas y puesto trazas

Code: Select all

nH:= FCreate("Trazas.Log")
           for k = 1 to nLen

// <<--               if k % 10 == 0
// <<--                   sysrefresh()
// <<--                   //msginfo('acabo de refrescar')
// <<--                   ::oInterfaz:oWnd:SetMsg( ::cPathRespaldo + ::cSectionFe + str( k, 8 ) + ' / ' + str( nLen, 8 ) )
// <<--               end
// <<--               if ::lStop
// <<--                   exit
// <<--               end
               //::oInterfaz:oMeter1:set( k )
               //::oInterfaz:oMeter1:refresh()
               cFile    = ::cPathFe       + ::cSectionFe + ::aData[ k, 1 ]
               cFileOut = ::cPathRespaldo + ::cSectionFe + ::aData[ k, 1 ]
               //msginfo( cFile + CRLF + cFileOut )

               FWrite("Antes del IF "+ cFile+ Space(3)+ cFileOut+ Space(3)+ Transform(File(cFile), "")+ Space(3)+ Transform(File(cFileOut), ""))
               if !file( cFileOut )
                   //copy file ( cFile ) to ( cFileOut )
                   FWrite("Antes de copiar "+ Time()) 
                      MYCOPYFILE( cFile , cFileOut, 0 )
                   FWrite("Despues de copiar "+ Transform(File(cFileOut), "")+ Space(3)+ Time())
               end
            next

FClose(nH)

 
En todo caso, para la prueba, apaga antivirus momentaneamente.
Salu2

Re: copiar muchisimos archivos de texto

Posted: Thu May 17, 2018 3:51 pm
by karinha

Code: Select all

// Just for FW 32 bits - C:\FWH..\SAMPLES\DLGFILE.PRG

#include "FiveWin.ch"

#define FO_MOVE           0x0001
#define FO_COPY           0x0002
#define FO_DELETE         0x0003
#define FO_RENAME         0x0004

#define FOF_MULTIDESTFILES         0x0001
#define FOF_CONFIRMMOUSE           0x0002
#define FOF_SILENT                 0x0004  // don't create progress/report
#define FOF_RENAMEONCOLLISION      0x0008
#define FOF_NOCONFIRMATION         0x0010  // Don't prompt the user.
#define FOF_WANTMAPPINGHANDLE      0x0020  // Fill in SHFILEOPSTRUCT.hNameMappings
                                      // Must be freed using SHFreeNameMappings
#define FOF_ALLOWUNDO              0x0040
#define FOF_FILESONLY              0x0080  // on *.*, do only files
#define FOF_SIMPLEPROGRESS         0x0100  // means don't show names of files
#define FOF_NOCONFIRMMKDIR         0x0200  // don't confirm making any needed dirs
#define FOF_NOERRORUI              0x0400  // don't put up error UI
#define FOF_NOCOPYSECURITYATTRIBS  0x0800  // dont copy NT file Security Attributes
#define FOF_NORECURSION            0x1000  // don't recurse into directories.

static oDlg

//----------------------------------------------------------------------------//

function Main()

   DEFINE DIALOG oDlg TITLE "System Files management Dialogs"
   
   @ 0.5, 1 BUTTON "&Copy" ACTION CopyFile( "*.XML", "C:\TESTE" ) ;
      SIZE 30, 12

   /*
   @ 1.5, 1 BUTTON "&Delete" ACTION DeleteFile( "c:\dlgfile.exe" ) ;
      SIZE 30, 12

   @ 2.5, 1 BUTTON "&Move" ACTION MoveFile( "dlgfile.exe", "c:\dlgfile.exe" ) ;
      SIZE 30, 12
   */

   ACTIVATE DIALOG oDlg CENTERED

return nil

//----------------------------------------------------------------------------//

function CopyFile( cSource, cDestination )

return SHFile( oDlg:hWnd, FO_COPY, cSource + Chr( 0 ), cDestination )

//----------------------------------------------------------------------------//

function DeleteFile( cFileName )

return SHFile( oDlg:hWnd, FO_DELETE, cFileName + Chr( 0 ) )

//----------------------------------------------------------------------------//

function MoveFile( cSource, cDestination )

return SHFile( oDlg:hWnd, FO_MOVE, cSource + Chr( 0 ), cDestination )

//----------------------------------------------------------------------------//

#pragma BEGINDUMP 

#include <hbapi.h>
#include <Windows.h>
#include <ShellApi.h>
#include <ShlObj.h>

HB_FUNC( SHFILE )
{
   SHFILEOPSTRUCT sh;

   memset( ( char * ) &sh, 0, sizeof( sh ) );

   sh.hwnd   = ( HWND ) hb_parnl( 1 );
   sh.wFunc  = ( UINT ) hb_parnl( 2 );
   sh.pFrom  = ( LPSTR ) hb_parc( 3 );
   sh.pTo    = ( LPSTR ) hb_parc( 4 );
   sh.fFlags = ( FILEOP_FLAGS ) hb_parnl( 5 );

   hb_retnl( SHFileOperation( &sh ) );
}

#pragma ENDDUMP

//----------------------------------------------------------------------------//
 

Re: copiar muchisimos archivos de texto

Posted: Thu May 17, 2018 4:48 pm
by wilsongamboa
Muchisimas gracias Karinha
voy a hacer lo que me dices y tu codigo con 20000 archivos funciona excelente supongo es del API de windows muchas gracias
voy a seguir a ver si lo sacon con mi docigo sino usare lo que me has enviado

Gracias nuevamente

att

Wilson
desde Quito Ecuador

Re: copiar muchisimos archivos de texto

Posted: Thu May 17, 2018 4:59 pm
by nageswaragunupudi

Code: Select all

   oFs   := CreateObject( "Scripting.FileSystemObject" )
   oFs:CopyFile( "z:\systems\xml\*.xml" , "r:\backups\systems\xml\", .t. ) // .t. for overwrite

Re: copiar muchisimos archivos de texto

Posted: Thu May 17, 2018 6:06 pm
by karinha
Perfect mister Rao. Many thanks.

Code: Select all

#Include "FiveWin.ch"

static oWnd

//----------------------------------------------------------------//

FUNCTION Main()

   LOCAL oBar, cOrigen, cDestino

   cOrigen  := Curdrive()+":\fwh1701\samples\*.prg"

   cDestino := Curdrive()+":\backup\"


   DEFINE WINDOW oWnd TITLE "Copiar Archivos"

   DEFINE BUTTONBAR oBar _3D OF oWnd

   DEFINE BUTTON OF oBar ACTION( Copiar( cOrigen, cDestino ), oWnd:End() )

   SET MESSAGE OF oWnd TO "Copiar Archivos" NOINSET CLOCK DATE KEYBOARD

   ACTIVATE WINDOW oWnd CENTER

RETURN NIL

//----------------------------------------------------------------//

FUNCTION Copiar( cOrigen, cDestino )

   LOCAL oFs

   If .not. Lisdir( cDestino )
      LMkdir( cDestino )
   Endif

   CURSORWAIT()

   oFs   := CreateObject( "Scripting.FileSystemObject" )

   // oFs:CopyFile( "z:\systems\xml\*.xml" , "r:\backups\systems\xml\", .t. ) // .t. for overwrite

   oFs:CopyFile( cOrigen, cDestino, .T. ) // .t. for overwrite

   CURSORARROW()

   ? "Pronto..."

RETURN NIL
Regards, saludos.

Re: copiar muchisimos archivos de texto

Posted: Thu May 17, 2018 6:47 pm
by cnavarro
Otra posibilidad utilizando herramientas del sistema

http://forums.fivetechsupport.com/viewt ... 92#p204832

Re: copiar muchisimos archivos de texto

Posted: Thu May 17, 2018 7:11 pm
by karinha

Code: Select all

// Otro ejemplo:

#include "FiveWin.ch"

//----------------------------------------------------------------------------//

MEMVAR cOrigen
MEMVAR cDestino

function Main()

   cOrigen  := Curdrive()+":\fwh1701\samples\*.dbf"
   cDestino := Curdrive()+":\backup\"

   MsgRun( "Copia archivos en 5 segundos",;
           "Copia archivos ahora",;
            { | oDlg | CopiaArch( oDlg ) } )

return nil

//----------------------------------------------------------------------------//

function CopiaArch( oDlg )

   local  oFs
   local nFor, nStart

   If .not. Lisdir( cDestino )
      LMkdir( cDestino )
   Endif

   for nFor := 4 to 0 step -1

      nStart = GetTickCount()

      while ( GetTickCount() - nStart ) < 1000
      end

      oDlg:cMsg := "Copia archivos en "+;
                    LTrim( Str( nFor ) ) + " segundos" + ;
                    If( nFor > 1, "s", "" )

      oDlg:Refresh()

      SysRefresh()

   next

   oFs   := CreateObject( "Scripting.FileSystemObject" )

   // oFs:CopyFile( "z:\systems\xml\*.xml" , "r:\backups\systems\xml\", .t. ) // .t. for overwrite

   oFs:CopyFile( cOrigen, cDestino, .T. ) // .t. for overwrite

   nMsgBox( "Copia Normal", "Ok, Bye, Bye!" )

return nil

Re: copiar muchisimos archivos de texto

Posted: Thu May 17, 2018 7:51 pm
by karinha

Code: Select all

// Usando ROBOCOPY.EXE del windows,

#include "FiveWin.ch"

//----------------------------------------------------------------------------//

MEMVAR cOrigen
MEMVAR cDestino
MEMVAR cFiles

function Main()

   cOrigen  := Curdrive()+":\fwh1701\samples"
   cDestino := Curdrive()+":\backup"
   cFiles   := "*.dbf"

   MsgRun( "Copia archivos en 5 segundos",;
           "Copia archivos ahora",;
            { | oDlg | CopiaArch( oDlg ) } )

return nil

//----------------------------------------------------------------------------//

function CopiaArch( oDlg )

   local nFor, nStart, cComando

   If .not. Lisdir( cDestino )
      LMkdir( cDestino )
   Endif

   for nFor := 4 to 0 step -1

      nStart = GetTickCount()

      while ( GetTickCount() - nStart ) < 1000
      end

      oDlg:cMsg := "Copia archivos en "+;
                    LTrim( Str( nFor ) ) + " segundos" + ;
                    If( nFor > 1, "s", "" )

      oDlg:Refresh()

      SysRefresh()

   next

   // ROBOCOPY C:\FWH\SAMPLES C:\BACKUP *.PRG
   cComando = "ROBOCOPY "+cOrigen+" "+cDestino+" "+cFiles // /MIR - Subcarpetas

   MYRUN( cComando )

   nMsgBox( "Copia Normal", "Ok, Bye, Bye!" )

return nil

***************************
Function MYRUN( cComando )

   ***************************
   Local oShell, RET, lOk:=.T.

   TRY
      #IFDEF __XHARBOUR__
         oShell := CreateObject( "WScript.Shell" )
      #ELSE
         oShell := Win_OleCreateObject( "WScript.Shell" )
      #ENDIF

   CATCH

      TRY
         #IFDEF __XHARBOUR__
            oShell := CreateObject( "WScript.Shell" )
         #ELSE
            oShell := Win_OleCreateObject( "WScript.Shell" )
         #ENDIF

      CATCH

         lOk:=.F.

        END
   END

   IF lOk

      TRY

          //.F. = Nao espera a aplicacao fechar, .T. espera.
          oShell:Run( "%comspec% /c " + cComando, 0, .T. ) 

      CATCH

          lOk:=.F.

      END

      oShell := NIL

   ENDIF

   //--   RET := oShell:Run( "%comspec% /c " + cComando, 0)  //, .T. )

RETURN lOk
 

Re: copiar muchisimos archivos de texto

Posted: Thu May 17, 2018 7:52 pm
by cnavarro
Joao, muy bien, muchas gracias

Re: copiar muchisimos archivos de texto

Posted: Fri May 18, 2018 4:45 pm
by wilsongamboa
Muchisimas gracias a todos los que me han ayudado al momento voy a comparar tiempos y ver con cual solucion me quedo, les mantendre informados de nuevo muchisimas gracias

saludos

Wilson

Re: copiar muchisimos archivos de texto

Posted: Fri May 18, 2018 8:40 pm
by tiaofw
Is this command fast too? Is it slower or is it the same thing?

Code: Select all


DLL32 FUNCTION COPYFILE( cExistingFileName AS LPSTR, cNewFileName AS LPSTR, lFailIfExists AS LONG ) AS BOOL;
    PASCAL FROM "CopyFileA" LIB "kernel32.dll"

 

Re: copiar muchisimos archivos de texto

Posted: Fri May 18, 2018 9:18 pm
by nageswaragunupudi
tiaofw wrote:Is this command fast too? Is it slower or is it the same thing?

Code: Select all


DLL32 FUNCTION COPYFILE( cExistingFileName AS LPSTR, cNewFileName AS LPSTR, lFailIfExists AS LONG ) AS BOOL;
    PASCAL FROM "CopyFileA" LIB "kernel32.dll"

 
This copies a single file only.