Tengo este enorme archivo XML de tamaño 2.8GB. Este es el volcado de artículos de la Wikipedia polaca. El tamaño de este archivo es muy problemático para mí. La tarea es buscar este archivo para una gran cantidad de datos. Todo lo que tengo son títulos de los artículos. Pensé que podría ordenar esos títulos y utilizar un ciclo lineal en el archivo. La idea no es tan mala, pero los artículos son no ordenados alfabéticamente. Están ordenados por ID, que no sé a priori.Trabajando con un archivo XML muy grande en C#
Entonces, mi segunda idea fue hacer un índice de ese archivo. Para almacenar en otras líneas de archivos (o bases de datos) en el siguiente formato: title;id;index
(tal vez sin una identificación). Yo mi otra pregunta pedí ayuda con eso. La hipótesis era que, si tenía el índice de etiqueta necesaria, podía usar el método simple Seek
para mover el cursor dentro del archivo sin leer todo el contenido, etc. Para archivos más pequeños, creo que esto podría funcionar bien. Pero en mi computadora (computadora portátil, C2D proc, Win7, VS2008) me da error de que la aplicación no responde.
En mi programa, estoy leyendo cada línea del archivo y compruebo si contiene una etiqueta que necesito. También estoy contando todos los bytes que leo y guardo líneas en el formato mencionado anteriormente. Entonces, mientras el programa de indexación se cuelga. Pero hasta entonces, el archivo índice de resultados es 36.2MB y el último índice es como 2.872.765.202 (B) mientras que el archivo XML completo es 3.085.439.630 B de largo.
Mi tercer pensamiento fue dividir el archivo en trozos más pequeños. Para ser precisos en 26 piezas (hay 26 letras en idioma latino), cada una contiene solo entradas que comienzan por la misma letra, p. en a.xml, todas las entradas que comiencen con títulos en la letra "A". Los archivos finales serían como decenas de MB, máximo alrededor de 200 MB, creo. Pero existe el mismo problema con la lectura de todo el archivo.
Para leer el archivo, probablemente utilicé la forma más rápida: usando StreamReader
. Leí en alguna parte que las clases StreamReader
y XmlReader
de System.Xml
son los métodos más rápidos. StreamReader
incluso más rápido que XmlReader
. Es obvio que no puedo cargar todo este archivo en la memoria. He instalado solo 3GB de RAM y Win7 toma como 800MB-1GB cuando está completamente cargada.
Así que estoy pidiendo ayuda. ¿Qué es lo mejor que puedo hacer? El punto es que la búsqueda de este archivo XML tiene que ser rápida. Tiene que ser más rápido que descargar páginas únicas de Wikipedia en formato HTML. Ni siquiera estoy seguro de si eso es posible.
¿Tal vez cargar todo el contenido necesario en la base de datos? Tal vez eso sería más rápido? Pero aún tendré que leer todo el archivo al menos una vez.
No estoy seguro de si hay algunos límites sobre 1 longitud de pregunta, pero también incluiré una muestra de mi código fuente de indexación.
while (reading)
{
if (!reader.EndOfStream)
{
line = reader.ReadLine();
fileIndex += enc.GetByteCount(line) + 2; //+2 - to cover characters \r\n not included into line
position = 0;
}
else
{
reading = false;
continue;
}
if (currentArea == Area.nothing) //nothing interesting at the moment
{
//search for position of <title> tag
position = MoveAfter("<title>", line, position); //searches until it finds <title> tag
if (position >= 0) currentArea = Area.title;
else continue;
}
(...)
if (currentArea == Area.text)
{
position = MoveAfter("<text", line, position);
if (position >= 0)
{
long index = fileIndex;
index -= line.Length;
WriteIndex(currentTitle, currentId, index);
currentArea = Area.nothing;
}
else continue;
}
}
reader.Close();
reader.Dispose();
writer.Close();
}
private void WriteIndex(string title, string id, long index)
{
writer.WriteLine(title + ";" + id + ";" + index.ToString());
}
Saludos y gracias de antemano,
Ventus
Editar: Enlace al volcado de este wiki http://download.wikimedia.org/plwiki/20100629/
No olvide que tengo incluso un problema con la lectura de todo el archivo. Lleva tanto tiempo con el código anterior, que VS cree que algo está mal aquí y detiene la ejecución posterior después de un tiempo. ¿Cómo evitar eso? – Ventus
OK. Finalmente logré escanear todo el archivo y transferir su contenido a la base de datos SQLite. DB me gustan los 2,81GB así que esto trae a colación problemas de rendimiento. Pero esto es por otra pregunta. Usé el código anterior, en mi pregunta, ligeramente modificado. Tomó mucho tiempo para indexar este archivo, debido a mi falta de conocimiento sobre el uso de SQLite. Gracias por las respuestas. – Ventus
siempre que trabaje con esa cantidad de datos brutos no indexados, llevará algún tiempo procesarlos. Pero al menos solo tienes que hacerlo una vez. Ahora que es un DB puedes obtener resultados en segundos. Buena suerte. –