FiveTech Support Forums

FiveWin / Harbour / xBase community
Board index FiveWin para Harbour/xHarbour Importar 3.900.000 registros
Posts: 1445
Joined: Mon Oct 10, 2005 02:38 PM
Importar 3.900.000 registros
Posted: Wed Jul 03, 2013 06:31 PM

Hola a todos,

Debo importar a DBF (por comodidad), 3.900.000 registros.
La información la tendré en un TXT de 3.900.000 líneas; cada lína tiene 4 campos separados por ";".

Son campos cuyo contenido son cifras y por tanto los puedo trabajar como números o cadenas.

Creen que debo tener algo especial en cuenta?
Ustedes como lo harían?

Gracias.

Un Saludo

Carlos G.



FiveWin 25.12 + Harbour 3.2.0dev (r2502110321), BCC 7.7 Windows 11 Home

Posts: 8515
Joined: Tue Dec 20, 2005 07:36 PM
Re: Importar 3.900.000 registros
Posted: Wed Jul 03, 2013 07:00 PM
João Santos - São Paulo - Brasil - Phone: +55(11)95150-7341
Posts: 1088
Joined: Fri Oct 07, 2005 03:33 PM
Re: Importar 3.900.000 registros
Posted: Wed Jul 03, 2013 11:38 PM
Hola,

se me ocurre algo así

Code (fw): Select all Collapse
      cImport := MEMOREAD("inputFile.txt")
      
      aRows := HB_ATokens( cImport, CHR(13) )

      FOR i := 1 TO Len( aRows )
            aFields :=  HB_ATokens( aRows[i], ";" )
            ............
            AADD( aData, aFields )
      NEXT


Te queda en aData toda la importación para que hagas el tratamiento que necesites antes de subirlo al DBF, o si ves mejor lo pasas directamente al DBF

saludos

Marcelo
Posts: 652
Joined: Wed Oct 19, 2005 12:03 PM
Re: Importar 3.900.000 registros
Posted: Thu Jul 04, 2013 09:55 AM
Hola hace cuatro de años tuve un problema similar, ya que rentas (tanto provincial como de capital), generaba un archivo txt para que nosotros tuvieramos las alícuotas para aplicar a los contribuyentes. El problema era que tenía una amplitud de entre 89 megas y 30 respectivamente.

Al intentar hacerlo era practicamente imposible y se me quedaba como colgado (hice varias pruebas y todas con el mismo resultado). La solución me la dió Carlos Vargas utilizando Visual Fox, que lo lee sin problemas. Uso el programa externamente e importo el resultado a Dbf
Te envío una de las formas que lo hacía en cliper hasta mas o menos 4 megas funcionaba bien

Code (fw): Select all Collapse
#include "Fivewin.ch"



FUNCTION PADCAPITAL()

LOCAL MfILE := cGetfile32("Archivo (*.txt) | *.txt |","Seleccione padron a importar")
local cCuit
local nPer
local nRet
local cRazon
local cStrline
local nTotal
local oMtr
local cAlias


//ShellExecute( ,"open",mfile,,,1 )

if !pasaje1("padroncf");return nil;endif
set order to 1
dbzap()



oTxtFil := TTxtFile():New( mfile ) 
nTotal := oTxtFil:RecCount() 
DEFINE DIALOG odlg resource "dia_indexo"
odlg:cCaption := "Generando padron capital"

REDEFINE PROGRESS oMtr  id 160 of odlg

REDEFINE SAY oSay var "texto bajado de internet" id 125


ACTIVATE DIALOG odlg CENTERED NOWAIT ON INIT ( oMtr:SetRange( 1, ntotal ),oMtr:setpos(0))




FOR z := 1 TO oTxtFil:RecCount() 
    cStrline := oTxtFil:ReadLine() 
  
    cCuit := substr(cStrline,28,11)
    nPer :=  val(substr(cStrline,46,4))
    nRet := val(substr(cStrline,51,4))
    cRazon := substr(cStrline,62,60)

    if yabase()
       replace cuit with cCuit, percepcion with nPer, retencion with nret, razon with cRazon
       dbcommit()
       dbunlock()
    endif
    oTxtfil:skip()
    oMtr:nPosition +=1
next

oTxtFil:close()

delete tag capcuit
index on cuit tag capcuit

odlg:end()
dbcloseall()


El código que uso actualmente para estos casos es

Code (fw): Select all Collapse
#include "FIVEWIN.CH"

FUNCTION buscotxto(lcapital)


local cinit := GetWinDir()+"\mega.ini"
local dgr := GetpvProfString("camino","renpath",,cinit) 
local dgrc :=  GetpvProfString("camino","rencpath",,cinit)
local programa := GetpvProfString("camino","curproga",,cinit) 
local memo:=GetpvProfString("camino","curpath",,cinit) +"\" +  iif(!lcapital, "padron.dbf","padroncf.dbf")
local memo1:=  GetpvProfString("camino","curpath",,cinit) +"\" + iif(!lcapital, "padron.cdx","padroncf.cdx")


if !lcapital
  waitrun(dgr + "import")                 // (1)
else
  waitrun(dgrc + "importo")              // (2)
endif


sysrefresh()

waiton()



if file(memo)  

 erase &memo
 erase &memo1
endif

if !lcapital
     use padron
     copy to &memo
     dbclosearea()
     erase padron.dbf
     if !pasaje1("padron");return nil ;endif
     delete tag cuit
     index on field4 tag cuit
     cierroalias(alias())
else
     use padroncf
     copy to &memo
     dbclosearea()
     erase padroncf.dbf
     if !pasaje1("padroncf");return nil ;endif
     delete tag cuit
     index on field4 tag cuit
     cierroalias(alias())
endif

waitoff()



if msgyesno("Desea Actualizar las bases de datos" + CRLF + "Clientes y proveedores","Mensaje del sistema")
    if !lcapital
      actualcli(.t.)
      actualcli(.f.)
        else
      actucap(.t.)
      actucap(.f.)
        endif
endif

return nil


/******************************************************************************/
function actualcli(lcliente)
local  oRen
local oMae
local oProve
local aObj := array(0)
local cTexto:= "Actualizando alícuotas rentas de clientes"
local ntotal := 0



if !pasaje("padron");return nil ;endif
database oRen
aadd(aObj,oRen)
oRen:setorder(1)

if lcliente
    if !pasaje("maeclie");cldata(aObj) ;return nil ;endif
    database oMae
    aadd(aObj,oMae)
    oMae:setorder(3)
    ntotal := oMae:RecCount() 
    oMae:beof := {|| nil}
    oMae:gotop()


    MUESTRO(oMae, oRen,ntotal,ctexto,.t.)
else

    if !pasaje("maepro");cldata(aObj) ;return nil ;endif
    database oProve
    aadd(aObj,oProve)
    oProve:setorder(3)
    oProve:beof := {|| nil}
    oProve:gotop()


    cTexto:= "Actualizando alícuotas rentas de proveedores"

    MUESTRO(oProve, oRen,ntotal,ctexto,.f.)
endif
cldata(aObj)

return nil
/******************************************************************************/

STATIC FUNCTION MUESTRO(oDbf,oRen,nTotal,ctexto, lcliente)

local odlg
local oMtr
local oSay
local nRetiene := ""
local nPercibe := ""
local cCuit := ""

DEFINE DIALOG odlg resource "dia_indexo"
odlg:cCaption := cTexto

REDEFINE PROGRESS oMtr  id 160 of odlg


REDEFINE SAY oSay var ctexto id 125


ACTIVATE DIALOG odlg CENTERED NOWAIT ON INIT ( oMtr:SetRange( 1, ntotal ),oMtr:setpos(0))

odbf:gotop()
do
     oMtr:nPosition +=1   
      cCuit :=  STRTRAN(oDbf:cuit, "-", "")
      oRen:seek(cCuit)
        if oRen:found()  
         if reviso(oDbf)
            nPercibe :=  strtran(oRen:field8,",",".")
            nRetiene := strtran(oRen:field9,",",".")
            oDbf:percibe := val( nPercibe )
            oDbf:retiene :=  val( nRetiene)
            oDbf:save()           
            oDbf:commit()
            oDbf:unlock()
                endif 
       elseif lcliente .and. oDbf:nropcia = 1
        oDbf:percibe :=  3
        oDbf:retiene :=  1.75   
        oDbf:save()           
        oDbf:commit()
        oDbf:unlock()
      endif
      oDbf:skip()
      sysrefresh()
until oDbf:eof()

odlg:end()
return nil
/******************************************************************************/
function actucap(lcliente)                           //actualizacion alicuotas de capital
local  oRen
local oMae
local oProve
local aObj := array(0)
local cTexto:= "Alícuotas rentas capital de clientes"
local ntotal := 0



if !pasaje("padroncf");return nil ;endif
database oRen
aadd(aObj,oRen)
oRen:setorder(1)

if lcliente
    if !pasaje("maeclie");cldata(aObj) ;return nil ;endif
    database oMae
    aadd(aObj,oMae)
    oMae:setorder(3)
    ntotal := oMae:RecCount() 
    oMae:beof := {|| nil}
    waiton()
    do  
      if reviso(oMae)
         oMae:percap := 0
         oMae:retcap := 0
         oMae:save()
         oMae:commit()
         oMae:unlock()
          endif  
      oMae:skip()
      sysrefresh()
    until oMae:eof()
    waitoff()

    MUESTRO1(oMae, oRen,ntotal,ctexto,.t.)
else

    if !pasaje("maepro");cldata(aObj) ;return nil ;endif
    database oProve
    aadd(aObj,oProve)
    oProve:setorder(3)
    oProve:beof := {|| nil}
    oProve:gotop()
    waiton()
    do  
      if reviso(oProve)
         oProve:percap := 0
         oProve:retcap := 0
         oProve:save()
         oProve:commit()
         oProve:unlock()
          endif  
      oProve:skip()
      sysrefresh()
    until oProve:eof()
    waitoff()
    ntotal := oProve:RecCount() 
    oProve:beof := {|| nil}
    cTexto:= "Alícuotas rentas capital de proveedores"

    MUESTRO1(oProve, oRen,ntotal,ctexto,.f.)
endif
cldata(aObj)

return nil

/******************************************************************************/
STATIC FUNCTION MUESTRO1(oDbf,oRen,nTotal,ctexto, lcliente)

local odlg
local oMtr
local oSay
local nRetiene := ""
local nPercibe := ""
local cCuit := ""

DEFINE DIALOG odlg resource "dia_indexo"
odlg:cCaption := cTexto

REDEFINE PROGRESS oMtr  id 160 of odlg


REDEFINE SAY oSay var ctexto id 125


ACTIVATE DIALOG odlg CENTERED NOWAIT ON INIT ( oMtr:SetRange( 1, ntotal ),oMtr:setpos(0))

odbf:gotop()
do
     oMtr:nPosition +=1   
      cCuit :=  STRTRAN(oDbf:cuit, "-", "")
      oRen:seek(cCuit)
        if oRen:found()  
         if reviso(oDbf)
            nPercibe := strtran(oRen:field8,",",".")
            nRetiene := strtran(oRen:field9,",",".")
            oDbf:percap := val( nPercibe )
            oDbf:retcap :=  val( nRetiene)
            oDbf:save()           
            oDbf:commit()
            oDbf:unlock()
                endif 
      endif
      oDbf:skip()
      sysrefresh()
until oDbf:eof()

odlg:end()
return nil
/******************************************************************************/


dónde import.exe e importo.exe (1) y (2) respectivamente me generan una dbf (creada desde VIsual fox) que luego importo a mis bases de datos... Y lo hace de forma muy rápida.

Luis
Posts: 44158
Joined: Thu Oct 06, 2005 05:47 PM
Re: Importar 3.900.000 registros
Posted: Thu Jul 04, 2013 10:13 AM

Carlos,

Pienso que la clave para que el proceso vaya rápido es usar una forma eficiente de leer el fichero.

Si cada línea tiene la misma longitud entonces puedes hacer un código a medida que recorra el fichero muy rapido, evitando usar arrays, pues solo duplicarian la información en memoria.

Si la longitud de cada registro se mantiene, no hay que usar At(), sino leer una cantidad x de bytes cada vez

regards, saludos

Antonio Linares
www.fivetechsoft.com
Posts: 1710
Joined: Tue Oct 28, 2008 06:26 PM
Re: Importar 3.900.000 registros
Posted: Thu Jul 04, 2013 12:28 PM
Si el contenido no tiene comas "," reemplazar todos los ";" por ","
Usar APPEND
Code (fw): Select all Collapse
USE BASE NEW EXCLUSIVE //CON LOS 4 CAMPOS
DBZAP()
APPEND FROM ARCHIVO.TXT DELIMITED


Seria bueno mostrar un poco del contenido del archivo de texto

Saludos,

Adhemar
Saludos,



Adhemar C.
Posts: 1445
Joined: Mon Oct 10, 2005 02:38 PM
Re: Importar 3.900.000 registros
Posted: Sat Jul 06, 2013 06:36 PM

Muchas gracias a todos por las ideas.
De momento no las puedo aplicar; el equipo que me tiene que proporcionar el fichero esta teniendo problemas para generarlo (sin comentarios).

Un Saludo

Carlos G.



FiveWin 25.12 + Harbour 3.2.0dev (r2502110321), BCC 7.7 Windows 11 Home

Posts: 44158
Joined: Thu Oct 06, 2005 05:47 PM
Re: Importar 3.900.000 registros
Posted: Sun Jul 07, 2013 01:01 PM

Carlos,

muy bueno :-D

regards, saludos

Antonio Linares
www.fivetechsoft.com

Continue the discussion