SoloCodigo

CLR: .Net / Mono / Boo / Otros CLR => C# => Mensaje iniciado por: Dieguinho. en Martes 4 de Diciembre de 2007, 13:47

Título: Procesar Archivo De Texto Rapido
Publicado por: Dieguinho. en Martes 4 de Diciembre de 2007, 13:47
Buenas, tengo una consulta.

Tengo que procesar un archivo de texto de la manera mas rapida posible.
Actualmente los estaba procesando linea por linea (el texto tiene una estructura ya armada) con streamreader.readline.
Pero bueno al ser 1.300.000 lineas el proceso tarda bastante. Hay algun metodo para hacerlo mas rapido??
En otras oportunidades lo que hacia era poner todo el contenido en un string por ejemplo y procesar el string, pero con esta cantidad de registros me salen errores de memoria. (el txt ocupa 80mb)

Alguien tiene algun metodo mas rapido o algo para aconsejarme??

Saludos.
Título: Re: Procesar Archivo De Texto Rapido
Publicado por: JuanK en Martes 4 de Diciembre de 2007, 14:25
Cita de: "Dieguinho."
Tengo que procesar un archivo de texto de la manera mas rápida posible.
a que te refieres con procesar...
puntualmente que es lo que necesitas hacer?


muestranos el código que usas para lectura y a lo que tu llamas procesamiento.
Título: Re: Procesar Archivo De Texto Rapido
Publicado por: Dieguinho. en Martes 4 de Diciembre de 2007, 14:57
Si, lo que tengo que hacer es lo siguiente.
El archivo txt que menciono tiene un formato como el siguiente:

Código: Text
  1. 21112007;18102006;01012021;20165718144;D;S;N;6,00;1,72;15;10
  2. 21112007;07122007;01012010;20255566491;D;S;N;6,00;1,73;15;10
  3. 21112007;02012010;31122020;30691156377;D;S;N;6,00;1,74;15;10
  4.  
(y asi hasta pasar el millon de lineas)

Uno de los valores de cada linea (que estan separados por ";") representa un nro de cliente.
Por otro lado en una tabla en una base de datos tengo guardados los clientes que trabajan con la empresa en donde trabajo.
Entonces lo que yo tendria que hacer es leer en cada linea ese nro de cliente, fijarme (por medio de una consulta SQL) si ese cliente existe en la base de datos y si existe hago un INSERT a otra tabla con casi todos los valores que aparecen en esa linea. Eso y algunas cosas mas.

El problema que leer linea por linea directamente del archivo y hace muy lento el proceso. (en realidad porque son muchas lineas).
Aunque todavia no se bien como se haria, ¿podria ser una forma mas rapida cargando bloques del archivo a memoria (por ejemplo a un string) y procesar el string directamente?
Asi estoy leyendo el archivo

Código: Text
  1.             StreamReader sr = new StreamReader(txtRuta.Text);      
  2.             while ((sLineaTexto = sr.ReadLine()) != null)
  3.  

Otra cosa que puedo mejorar es que por cada linea hago un Select a la base de datos para ver si existe. Quiza podría dejar esos clientes de la base de datos en una lista o no se si se podra en un dataset y despues consuntarlos directamente de ahi, no se si sera eso mas rapido.

El codigo que uso para procesar cada lineas del archivo de texto debe tener unas 80 lineas. Si te interesa te lo puedo resumir y ponerlo, no lo hago realmente para no molestar tanto.

Espero que me este explicando bien...
Saludos y gracias!
Título: Re: Procesar Archivo De Texto Rapido
Publicado por: JuanK en Martes 4 de Diciembre de 2007, 15:14
1- No cargues de a una linea, carga bloques de a varias lineas en un array de strings de un tamaño fijo
2- Ese tamaño fijo debe ser una constante
3- De acuerdo a ese tamaño fijo has packs de consultas a la base de datos, es decir no haces una consulta por cada linea cargada sino que haces una consulta que te devuelva todos los valores asociados a todas las lineas de una sola vez .
4- Por cada linea leida que exista previamente en la bd creas los insert y luego envías los insert en un solo bloque sin hacer commit.
5-Por defecto cada operacion hecha hace auto commit, asi que debes manipular los objetos de conexion a la bad para previamente desactivar el commit.
6- Hay maneras en los objetos de conexion de crear varios estatements  (INSERTS) y luego solo enviarlos a la base de datos en un solo envio.
7- Haces commit de manera manual solo al final de cada bloque.

El problema no es propiamente la lectura del archivo, aunque se puede optimizar leyendo de pedazos mas grandes, el problema mas fuerte son las idas y venidas a la base de datos.

Incluso de manera opcional, puedes probar cargando de una sola vez todo el archivo a memoria en un array de strings y luego operar sobre dicho arreglo por bloques tal como te lo he indicado arriba.

También coloca el código, entre mas información mejor.
Título: Re: Procesar Archivo De Texto Rapido
Publicado por: Dieguinho. en Martes 4 de Diciembre de 2007, 16:10
buenisimo, con esto ya tengo cosas para ver.
Despues te comento como me va quedando.
Gracias!!
Título: Re: Procesar Archivo De Texto Rapido
Publicado por: JuanK en Martes 4 de Diciembre de 2007, 18:52
ok,   :suerte:

no olvides retroalimentar en este hilo para saber como te fue o que más se puede mejorar.
Título: Re: Procesar Archivo De Texto Rapido
Publicado por: Dieguinho. en Miércoles 5 de Diciembre de 2007, 18:27
Bueno, considerando que el tema mas importante, como me mencionaste, eran las consultas a la base de datos resolvi hacer el proceso al reves.

En lugar de recorrer el archivo linea por linea y por cada una hacer el Select para ver si es un cliente valido decidi hacer lo contrario. Hice un select con todos los clientes de la empresa y tomaba cada uno y lo buscaba en el archivo txt (tanto la consulta como el archivo txt tienen los clientes en orden asi que el txt lo recorro una sola vez).
De esta manera cambio el millon y pico de select por 1 solo y asi bajó considerablemente el tiempo de 2 horas y media a, por ahora, 18 minutos.

Igualmente me quedan muchas cosas para optimizar como ser el tema de los insert, agruparlos y enviarlos todos juntos, o leer el archivo por bloques, etc.

Pero bueno esto ya fue de mucha ayuda, asi que gracias nuevamente!!

Saludos!
Título: Re: Procesar Archivo De Texto Rapido
Publicado por: JuanK en Miércoles 5 de Diciembre de 2007, 20:21
Cita de: "Dieguinho."
2 horas y media a, por ahora, 18 minutos.
12:1   :lol:  :smartass:

Y estoy seguro que se puede aún mucho más.  :comp: