FTP | CCD | Buscar | Trucos | Trabajo | Foros |
#1
|
|||
|
|||
Lentitud leer .csv
Mi problema es el siguiente:
Leo un archivo csv. en un RichEdit, lo leo con este componente porque con un Memo me paso del límite de caracteres. Después de leerlo lo cargo en un StringGrid y comparo los datos con una base de datos en busca de nuevos registros. El problema esta en la lentitud del proceso de lectura del .csv, no se me ocurre forma de acelerar este proceso ya que tengo que tener en cuenta: -Que cuando haya mas de un espacio seguido deje de leer la linea del RichEdit. -Que cuando encuentre un ";" debe meter la variable en la celda del StringGrid. -Que cuando encuentre algo que no sea ";" rellene la variable con la palabra encontrada. Mi código es el siguiente, si alguien tiene alguna idea de como podría acelerar el proceso seria de gran ayuda. Código:
void __fastcall TXPrincipal::ToolButton2Click(TObject *Sender) { if(OpenDialog1->Execute()) { //LECTURA DE CSV int col =0; int cont=0; String referencia =""; RichEdit1->Lines->LoadFromFile(OpenDialog1->FileName); XCarga->Show(); XCarga->Caption="Leiendo .CSV..."; XCarga->ProgressBar1->Min = 0; XCarga->ProgressBar1->Max = RichEdit1->Lines->Count; for (int i =0; i <= RichEdit1->Lines->Count; i++) { XCarga->ProgressBar1->Position = i; col=0; cont=0; for (int j=1; j<= RichEdit1->Lines->Strings[i].Length();j++) { XCarga->Caption="Leiendo .CSV...Linea: "+ IntToStr(i)+ "Columna: "+ IntToStr(j); if (RichEdit1->Lines->Strings[i][j] != ' ') { cont =0; if (RichEdit1->Lines->Strings[i][j] == ';') { StringGrid1->Cells[col][i] = referencia; referencia = ""; col++; } if (RichEdit1->Lines->Strings[i][j] != ';') { referencia = referencia +RichEdit1->Lines->Strings[i][j]; } } if (RichEdit1->Lines->Strings[i][j] == ' ') { cont++; if (cont >2) break; } } } //COMPARAR CON BD XCarga->Close(); } XDatos->TCategorias->Open(); XDatos->TSubCat1->Open(); XDatos->TSubCat2->Open(); XDatos->TSubCat3->Open(); XDatos->TMarcas->Open(); XCarga->Close(); XDatos->TCaracteristicas->Open(); int cont=0; XCarga->Show(); XCarga->ProgressBar1->Min = 1; XCarga->ProgressBar1->Max = RichEdit1->Lines->Count; String ref = ""; for (int f=1;f<=StringGrid1->RowCount;f++) { if (StringGrid1->Cells[0][f]!="") { ref = StringGrid1->Cells[0][f]; XCarga->Caption = IntToStr(f)+ " Productos Nuevos"; XCarga->ProgressBar1->Position = f; XDatos->QExisteProducto->Close(); XDatos->QExisteProducto->Parameters->ParamByName("PRef")->Value = ref; XDatos->QExisteProducto->Open(); if (XDatos->QExisteProducto->FieldByName("existe")->Value ==0) { String categoria =""; XDatos->QProductos->Append(); XDatos->QProductosREFERENCIA->Value = StringGrid1->Cells[0][f]; XDatos->QProductosESTADO->Value = StringGrid1->Cells[1][f]; categoria = StringGrid1->Cells[2][f]; XDatos->QExisteCategoria->Close(); XDatos->QExisteCategoria->Parameters->ParamByName("PCat")->Value = categoria ; XDatos->QExisteCategoria->Open(); if (XDatos->QExisteCategoria->FieldByName("Existe")->Value >0) { XDatos->QCodigoCategoria->Close(); XDatos->QCodigoCategoria->SQL->Text = "select * from categorias where categoria = :PCat"; XDatos->QCodigoCategoria->Parameters->ParamByName("PCat")->Value = categoria; XDatos->QCodigoCategoria->Open(); XDatos->QProductosCATEGORIA->Value = XDatos->QCodigoCategoriaCodCategoria->Value; XDatos->QCodigoCategoria->Close(); } else { XDatos->TCategorias->Append(); XDatos->TCategoriasCATEGORIA->Value = StringGrid1->Cells[2][f]; XDatos->TCategorias->Post(); XDatos->QProductosCATEGORIA->Value=XDatos->TCategoriasCodCategoria->Value; } String subcat1 =StringGrid1->Cells[3][f]; XDatos->QExisteSubcat1->Close(); XDatos->QExisteSubcat1->Parameters->ParamByName("PSubCat1")->Value = subcat1; XDatos->QExisteSubcat1->Open(); if (XDatos->QExisteSubcat1->FieldByName("Existe")->Value >0) { XDatos->QCodigoSubCat1->Close(); XDatos->QCodigoSubCat1->SQL->Text = "select * from SUBCATS1 where SUBCAT1 = :PSubcat1"; XDatos->QCodigoSubCat1->Parameters->ParamByName("PSubcat1")->Value = subcat1; XDatos->QCodigoSubCat1->Open(); XDatos->QProductosSUBCAT1->Value = XDatos->QCodigoSubCat1CodSUBCAT1->Value; XDatos->QCodigoSubCat1->Close(); } else { XDatos->TSubCat1->Append(); XDatos->TSubCat1SUBCAT1->Value = StringGrid1->Cells[3][f]; XDatos->TSubCat1CATEGORIA->Value = XDatos->QProductosCATEGORIA->Value; XDatos->TSubCat1->Post(); XDatos->QProductosSUBCAT1->Value= XDatos->TSubCat1CodSUBCAT1->Value; } String subcat2 =StringGrid1->Cells[4][f]; XDatos->QExisteSubcat2->Close(); XDatos->QExisteSubcat2->Parameters->ParamByName("PSubCat2")->Value = subcat2; XDatos->QExisteSubcat2->Open(); if (XDatos->QExisteSubcat2->FieldByName("Existe")->Value >0) { XDatos->QCodigoSubCat2->Close(); XDatos->QCodigoSubCat2->SQL->Text = "select * from SUBCATS2 where SUBCAT2 = :PSubcat2"; XDatos->QCodigoSubCat2->Parameters->ParamByName("PSubcat2")->Value = subcat2; XDatos->QCodigoSubCat2->Open(); XDatos->QProductosSUBCAT2->Value = XDatos->QCodigoSubCat2CodSUBCAT2->Value; XDatos->QCodigoSubCat2->Close(); } else { XDatos->TSubCat2->Append(); XDatos->TSubCat2SUBCAT2->Value = StringGrid1->Cells[4][f]; XDatos->TSubCat2SUBCAT1->Value = XDatos->QProductosSUBCAT1->Value; XDatos->TSubCat2->Post(); XDatos->QProductosSUBCAT2->Value = XDatos->TSubCat2CodSUBCAT2->Value; } String subcat3 =StringGrid1->Cells[5][f]; XDatos->QExisteSubcat3->Close(); XDatos->QExisteSubcat3->Parameters->ParamByName("PSubCat3")->Value = subcat3; XDatos->QExisteSubcat3->Open(); if (XDatos->QExisteSubcat3->FieldByName("Existe")->Value >0) { XDatos->QCodigoSubcat3->Close(); XDatos->QCodigoSubcat3->SQL->Text = "select * from SUBCATS3 where SUBCAT3 = :PSubcat3"; XDatos->QCodigoSubcat3->Parameters->ParamByName("PSubcat3")->Value = subcat3; XDatos->QCodigoSubcat3->Open(); XDatos->QProductosSUBCAT3->Value = XDatos->QCodigoSubcat3CodSUBCAT3->Value; XDatos->QCodigoSubcat3->Close(); } else { XDatos->TSubCat3->Append(); XDatos->TSubCat3SUBCAT3->Value = StringGrid1->Cells[5][f]; XDatos->TSubCat3SUBCAT2->Value = XDatos->QProductosSUBCAT2->Value; XDatos->TSubCat3->Post(); XDatos->QProductosSUBCAT3->Value = XDatos->TSubCat3CodSUBCAT3->Value; } XDatos->QProductosPRODUCTO->Value = StringGrid1->Cells[6][f]; XDatos->QProductosKEY->Value = StringGrid1->Cells[7][f]; String marca =StringGrid1->Cells[8][f]; XDatos->QExisteMarca->Close(); XDatos->QExisteMarca->Parameters->ParamByName("PMarca")->Value = marca; XDatos->QExisteMarca->Open(); if (XDatos->QExisteMarca->FieldByName("Existe")->Value >0) { XDatos->QCodigoMarca->Close(); XDatos->QCodigoMarca->SQL->Text = "select * from MARCAS where MARCA = :PMarca"; XDatos->QCodigoMarca->Parameters->ParamByName("PMarca")->Value = marca; XDatos->QCodigoMarca->Open(); XDatos->QProductosMARCA->Value = XDatos->QCodigoMarcaCodMARCA->Value; XDatos->QCodigoMarca->Close(); } else { XDatos->TMarcas->Append(); XDatos->TMarcasMARCA->Value = StringGrid1->Cells[8][f]; XDatos->TMarcas->Post(); XDatos->QProductosMARCA->Value = XDatos->TMarcasCodMARCA->Value; } XDatos->QProductosDESCRIPCION->Value = StringGrid1->Cells[9][f]; XDatos->QProductosFOTOS->Value = StringGrid1->Cells[10][f]; XDatos->QProductosCATEGORIAX->Value = StringGrid1->Cells[11][f]; XDatos->QProductosCATEGORIAS->Value = StringGrid1->Cells[12][f]; XDatos->QProductos->Post(); for(int c=13;c<=StringGrid1->ColCount;c++) { if (StringGrid1->Cells[c][f]!="") { if (c % 2 !=0) { XDatos->TCaracteristicas->Append(); XDatos->TCaracteristicasCATEGORIA->Value = XDatos->QProductosCATEGORIA->Value; XDatos->TCaracteristicasSUBCAT1->Value = XDatos->QProductosSUBCAT1->Value; XDatos->TCaracteristicasSUBCAT2->Value = XDatos->QProductosSUBCAT2->Value; XDatos->TCaracteristicasSUBCAT3->Value = XDatos->QProductosSUBCAT3->Value; XDatos->TCaracteristicasref->Value = XDatos->QProductosREFERENCIA->Value; XDatos->TCaracteristicasCARACTERISTICA->Value = StringGrid1->Cells[c][f]; XDatos->TCaracteristicasVALOR->Value = StringGrid1->Cells[c+1][f]; XDatos->TCaracteristicas->Post(); } } } if (StringGrid1->Cells[0][f]=="") cont ++; if (cont > 100) break; } } } XCarga->Close(); XDatos->QRecorreProductos->Close(); DBGrid1->Refresh(); } Un Saludo. |
#2
|
||||
|
||||
Una pregunta, si quieres leer un fichero y mostrarlo en un stringgrid, ¿por qué lo cargas en el richedit de intermediario?
|
#3
|
|||
|
|||
Pues en principio lo hice por comodidad, ya que con el LoadFromFile ya leo perfectamente el csv teniendo en cuenta los saltos de linea, y me coloca 1 registro por linea en el RichEdit, lo cual facilita luego la lectura para el StringGrid.
Piensas que la lentitud es a causa de leer el RichEdit? quizás leyendo directamente desde el archivo puede ser mas rápido? Si es asi como crees que podria leer desde el archivo caracter a caracter para tener en cuenta las mismas cosas? Gracias por tu interes |
#4
|
||||
|
||||
Hola ErYcK.
Si no entendí mal lo que deseas hacer, se me ocurre que podrías cambiar el separador ';' por ',' y aprovechar la propiedad CommaText del TStringGrid. Fijate si de este modo hace mas rápido lo que buscas: Código:
void __fastcall TForm1::Button1Click(TObject *Sender) { TStringList *TS = new TStringList; TStringGrid *SG = static_cast<TStringGrid*> (StringGrid1); if (OpenDialog1->Execute()) { TS->LoadFromFile(OpenDialog1->FileName); for(int i=0; i< TS->Count; i++) { StringReplace(TS->Strings[i], ';', ',', TReplaceFlags() << rfReplaceAll); SG->Rows[i]->CommaText = TS->Strings[i]; } } delete TS; }
__________________
Daniel Didriksen Guía de estilo - Uso de las etiquetas - La otra guía de estilo .... |
#5
|
|||
|
|||
Gracias por tu aporte ecfisa, el problema es que algunos campos llevan ',' entonces necesito el ';' como separador, sino me crearía conflictos.
Por ejemplo hay un campo fotos en el cual hay 6 nombres de fotos separados con ',' entonces me metería 6 campos distintos donde debe ser solo uno. Este mismo proceso lo hice en principio utilizando el componente Memo, y lo hacia más rápido pero me vi obligado a cambiarlo porque llegara el límite de caracteres del Memo, no termino de entender porque con el RichEdit se ralentiza tanto, en principio pensé que el problema estaba en que siempre recorría al completo los campos del RichEdit y de por ese motivo utilice el contador para que una vez encuentre 2 espacios seguidos me me salga del bucle, pero no consigo acelerarlo suficiente con eso. De nuevo gracias por vuestra atención. |
#6
|
||||
|
||||
Hola ErYcK.
A ver, proba si te sirve de este modo: Código:
void __fastcall TForm1::Button1Click(TObject *Sender) { if (OpenDialog1->Execute()) { TStringList *TS = new TStringList; TS->LoadFromFile(OpenDialog1->FileName); for(int i=0; i< TS->Count; i++) ExtractStrings(TSysCharSet()<< ';', TSysCharSet() << ' ', TS->Strings[i].c_str(), StringGrid1->Rows[i]); delete TS; } }
__________________
Daniel Didriksen Guía de estilo - Uso de las etiquetas - La otra guía de estilo .... |
#7
|
|||
|
|||
Buenísimo el aporte ecfisa, me acelera muchísimo el proceso y en principio va bien, el único fallo es que la base de datos de la empresa tiene ciertos fallos, como por ejemplo que algunos de los campos no están, por ejemplo algunos de los registros son algo así:
referencia;estado;producto;categoria;categoria1;categoria2;categoria3; descripción 11234;;producto1;hogar; electrodomésticos;Lavadoras;;lavadora ultimo modelo tal y tal; Es decir algunos campos vienen vacíos, con lo cual se genera en el csv dos ';' seguidos y lo que hace es meterme en el estado, la categoría. No se si me he explicado bien, el tema es que cuando se encuentran dos ';' seguidos ha dejar esa celda vacía, estoy dándole vueltas al código que me pusiste e intento dar con la tecla para tener eso en cuenta pero me da ami que no puede ser de esa forma, aunque no lo se. Si se te ocurre algo seria de gran ayuda. Gracias por el esfuerzo. |
#8
|
||||
|
||||
Hola de nuevo.
Cita:
Código:
ExtractStrings(TSysCharSet()<< ';', TSysCharSet() << '\0', TS->Strings[i].c_str(), StringGrid1->Rows[i])
__________________
Daniel Didriksen Guía de estilo - Uso de las etiquetas - La otra guía de estilo .... |
#9
|
|||
|
|||
Hola otra vez siento ser tan pesado.
Con ese cambio que me diste me sigue metiendo mal los datos, mete la categoría en el estado en la mayoría de los registros, he probado a mezclar tu idea con la mía, y lo hace bien, el problema es que los registros demasiado largos me los mete en el siguiente registro, entiendo que es porque el TStringList tendrá un límite de caracteres, te muestro el código. Código:
if(OpenDialog1->Execute()) { TStringList *TS = new TStringList; TS->LoadFromFile(OpenDialog1->FileName); XCarga->Show(); XCarga->ProgressBar1->Min = 0; XCarga->ProgressBar1->Max = TS->Count; int cont=0; int col=0; String referencia=""; for(int i=0; i< TS->Count; i++) { cont=0; col=0; XCarga->ProgressBar1->Position=i; XCarga->Caption="Leidno .CSV .. Linea: "+i; for (int j=1;j<=TS->Strings[i].Length();j++) { if (TS->Strings[i][j]!= ' ') { cont=0; if (TS->Strings[i][j] == ';') { StringGrid1->Cells[col][i] = referencia; referencia=""; col++; } else { referencia = referencia+TS->Strings[i][j]; } } if (TS->Strings[i][j] == ' ') { cont++; if (cont>2) break; } } } Si sabes alguna forma de solucionar el problema usando el código que antes me mostraste seria genial, si no me gustaría saber si el TStringList tiene límite de caracteres y si se puede ampliar este límite. Gracias por tu paciencia que ha de ser mucha. |
#10
|
||||
|
||||
Hola.
La capacidad de cada línea de TStringList es la que tiene la propiedad vectorial Strings cuyos elementos son de tipo AnsiString y según la ayuda de Builder C++ es: Código:
Type Maximum length Memory required Used for AnsiString ~2^31 characters 4 bytes to 2GB 8-bit (ANSI) characters Saludos.
__________________
Daniel Didriksen Guía de estilo - Uso de las etiquetas - La otra guía de estilo .... |
#11
|
|||
|
|||
Aquí os dejo un ejemplo de csv comprimido, contiene 1 registro demasiado largo, el cual me da conflictos como te he comentado anteriormente.
De nuevo gracias por tu ayuda. Un Saludo. |
#12
|
||||
|
||||
Hola ErYcK.
No me queda muy en claro la definición de la cabecera (columnas) ¿ Conocés cuantas y cuales son ? Saludos.
__________________
Daniel Didriksen Guía de estilo - Uso de las etiquetas - La otra guía de estilo .... |
#13
|
|||
|
|||
Es que es algo extraño, te comento:
La primera linea del csv guarda los nombres de los campos de una tabla denominada Productos, pero a partir de ahí se guardan los valores de estos campos que son 12 si no me equivoco, seguidos de una característica y el valor de la misma, el tecla esta en que cada producto tiene unas características, algunos más que otros entonces no se sabe cuantas columnas hay hasta que no se lee el csv. Yo en el StringGrid le tengo puesto un limite de columnas suficientemente alto como para que pudiese entrar el registro mas largo, y después cuando lo paso a la base de datos desde el StringGrid guardo los 12 primeros campos en una tabla y las características que le siguen las voy metiendo en otra tabla relacionada con Productos, pero ese proceso en principio si que esta listo, el problema es que tiene que cargarse correctamente el StringGrid para que funcione. No se si me he expresado con claridad, el tema es algo rebuscado. Gracias por el esfuerzo. Un Saludo. |
#14
|
||||
|
||||
Hola ErYcK.
Cita:
Código:
00)Referencia :19974; 01)Estado; :1; 02)Categoría (Español); :PUERICULTURA; 03)SubCategoría 1 (Español); :HORA DE JUGAR; 04)SubCategoría 2 (Español); :GANDULITAS Y COLUMPIOS; 05)SubCategoría 3 (Español); :; 06)Nombre; :HAMACA PLAY BABY; 07)Keywords; :; 08)Marca; :PLAY BABY; 09)Descripción; :; 10)Fotos (separadas por ,); :HAMACA-4.jpg,HAMACA-3.jpg,HAMACA-2.jpg,HAMACA-1.jpg,HAMACA-5.jpg,HAMACA-6.jpg; Cita:
Con ese formato, no creo posible aplicar los métodos que te sugerí ya que la aparición de los datos no pareciera obedecer a un patrón repetitivo. Saludos.
__________________
Daniel Didriksen Guía de estilo - Uso de las etiquetas - La otra guía de estilo .... Última edición por ecfisa fecha: 20-06-2012 a las 18:27:29. |
#15
|
|||
|
|||
Esos dos campos de los que me hablas son campos que relleno automáticamente, el de CATEGORÍAS, siempre se rellena con eso, y el otro se rellena con la categoría y las subcategorias que tenga el producto separadas con '/'.
Pero claro eso lo hago cuando doy altas aquí simplemente me interesa leerlas. Respecto a lo que te pregunté sobre los StringList es porque me mete parte de los datos de un registro en el siguiente cuando es demasiado largo y no entiendo el porque, por que dado el tamaño que me dijiste que tenia no tendría sentido que llegase al límite ¿no?. Un Saludo |
#16
|
||||
|
||||
Hola.
Cita:
Saludos.
__________________
Daniel Didriksen Guía de estilo - Uso de las etiquetas - La otra guía de estilo .... Última edición por ecfisa fecha: 20-06-2012 a las 20:34:22. |
#17
|
|||
|
|||
Perdona por la tardanza.
Con acceder al archivo secuencialmente entiendo que debo leer el archivo carácter a carácter, aunque no se exactamente como se haría desde Builder, si pudiese darme una idea seria de gran ayuda. Gracias |
#18
|
||||
|
||||
__________________
Daniel Didriksen Guía de estilo - Uso de las etiquetas - La otra guía de estilo .... |
#19
|
|||
|
|||
Gracias por el aporte, he intentando entender la forma de leer el archivo con el enlace que me pusiste pero no consigo entender exactamente como se haría para leer carácter por carácter, de esa forma, si pudieses darme une ejemplo sencillo de como se hace me ayudaría a entenderlo.
Gracias y disculpa por las molestias, pero no consigo entenderlo por mi mismo. |
#20
|
||||
|
||||
Cita:
Por ejemplo, este código cuenta los caracteres de un archivo de texto leyéndolos de a uno: Código:
#include<stdio.h> void __fastcall TForm1::Button1Click(TObject *Sender) { FILE *fp; char ch; int char_leidos = 0; if ((fp=fopen("C:\\ARCHIVO.TXT","rt"))) while ((ch = fgetc(fp))!= EOF) char_leidos++; fclose(fp); ShowMessage("Caracteres leidos: "+IntToStr(char_leidos)); } Saludos.
__________________
Daniel Didriksen Guía de estilo - Uso de las etiquetas - La otra guía de estilo .... |
Herramientas | Buscar en Tema |
Desplegado | |
|
|
Temas Similares | ||||
Tema | Autor | Foro | Respuestas | Último mensaje |
Lentitud en ADO | JF Sebastian | Conexión con bases de datos | 0 | 16-03-2008 11:06:26 |
Lentitud Firebird | mjjj | Conexión con bases de datos | 16 | 13-01-2008 17:35:06 |
Lentitud en la red. | Carlos Arevalo | Varios | 2 | 09-07-2007 19:04:08 |
Lentitud en la red | Ignacio | Conexión con bases de datos | 2 | 26-08-2003 14:09:39 |
|