Estoy haciendo un programa en C# para crear un índice de ficheros para despues usar este índice en otras aplicaciones.
¿Pero es la mejor manera, guardar un índice en un XML?
Suponiendo que hablemos de una base de datos de uso local (cuyo contenido llámese índice de archivos), entonces un archivo Xml es una manera ideal si lo que quieres es generar un archivo de texto plano que sea accesible/legible por el humano y sencillamente parseable por la máquina (vease también una estructura CSV, aunque a mi siempre me ha parecido algo muy, muy feo), de lo contrario, y si realmente nos debemos obsesionar por el rendimiento, entonces podrías serializar los datos en un archivo binario, a falta de mencionar un método más óptimo que tal vez puedo desconocer.
También habría que tener en cuenta la forma en que contruyas el Xml y también como lo cargas, me refiero a la lógica que emplees (por ejemplo instanciar un
XmlWriter para escribir en el archivo poco a poco, o usar directamente el
XmlSerializer) y los tiempos de respuesta de estas lógicas de tu algoritmo, pero si hablamos de una simple serialización de datos en Xml o Binario, entonces la velocidad de carga/lectura varia apenas unos milisegundos con cantidades de datos normales (1-100 mb).
Dicen que el serializador
protobuf da mejores resultados que utilizando los serializadores de la librería de clases de .Net Framework, pero nunca lo he probado ya que no manejo una cantidad de datos que podamos denominar "
Big Data" y por ende no me interesa romperme el cerebro para optimizar hasta tal punto ...y creo que tu tampoco necesitarás llegar hasta ese extremo, de todas formas por si te interesa lo puedes descargar aquí:
https://github.com/google/protobufEn fin, por un lado tenemos la serialización XML y por otro la binaria, ¿para que más opciones?.
¿Cual es "la mejor manera" entre estas dos?, pues depende de las necesidades de cada uno, pero en lo que respecta a rendimiento para salir de dudas he realizado un pequeño test, donde he obtenido todas las rutas absolutas de mi sistema de archivos, y estos han sido los resultados:
Total file amount......: 165,465 files.
FileSystem.Xml filesize: 18.88 MB.
FileSystem.Dat filesize: 16.51 MB.
Method Name: SerializeXml
Elapsed Time: 00:00:00:254 ms
Method Name: SerializeBin
Elapsed Time: 00:00:00:161 ms
Method Name: DeserializeXml
Elapsed Time: 00:00:00:327 ms
Method Name: DeserializeBin
Elapsed Time: 00:00:00:281 ms
Como se puede comprobar, el archivo resultante Xml ocupa unos MB más que el binario, y también tarda más en cargar. Los nombres de los métodos tienen nombres
self-explanatory, creo que no es necesario explicar su funcionalidad.
El código fuente parcial, en VB.Net:
( Para resumir lo que ocurre, simplemente obtengo la ruta absoluta de todos los archivos del disco duro "C:\", y seguidamente uso la class
BinaryFormatter y
XmlSerializer para serializar los datos, mientras que con un
StopWatch mido el tiempo de ejecución de ambos tipos de serialización y deserialización. )
Imports System.IO
Public NotInheritable Class Form1 : Inherits Form
Dim fileSystemPaths As String()
Const xmlFilePath As String = ".\FileSystem.xml"
Const binFilePath As String = ".\FileSystem.dat"
Private Sub Form1_Shown() Handles MyBase.Shown
Me.fileSystemPaths = Utils.FileDirSearcher.GetFilePaths("C:\", SearchOption.AllDirectories).ToArray
Utils.Misc.MeasureAction(AddressOf SerializeXml, writeResultInConsole:=True)
Utils.Misc.MeasureAction(AddressOf SerializeBin, writeResultInConsole:=True)
Utils.Misc.MeasureAction(AddressOf DeserializeXml, writeResultInConsole:=True)
Utils.Misc.MeasureAction(AddressOf DeserializeBin, writeResultInConsole:=True)
Dim sb As New StringBuilder
With sb
.AppendLine(String.Format("Total file amount......: {0} files.", Me.fileSystemPaths.Count.ToString("n0")))
.AppendLine(String.Format("FileSystem.Xml filesize: {0} MB.", (New FileInfo(xmlFilePath).Length / (1024 * 1024)).ToString("n2")))
.AppendLine(String.Format("FileSystem.Dat filesize: {0} MB.", (New FileInfo(binFilePath).Length / (1024 * 1024)).ToString("n2")))
End With
Console.WriteLine(sb.ToString)
End Sub
Private Sub SerializeXml()
Utils.SerializationUtil.Serialize(Me.fileSystemPaths, xmlFilePath, SerializationFormat.Xml)
End Sub
Private Sub SerializeBin()
Utils.SerializationUtil.Serialize(Me.fileSystemPaths, binFilePath, SerializationFormat.Binary)
End Sub
Private Sub DeserializeXml()
Dim fileSystemFromXml As String() = Utils.SerializationUtil.Deserialize(Of String())(xmlFilePath, SerializationFormat.Xml)
End Sub
Private Sub DeserializeBin()
Dim fileSystemFromBin As String() = Utils.SerializationUtil.Deserialize(Of String())(binFilePath, SerializationFormat.Binary)
End Sub
End Class
El código fuente de la solución completa:
http://www.mediafire.com/download/u167fme23z6p5ju/WindowsApplication1.rarPD: C# y VB.Net son dos lenguajes (casi)idénticos internamente hablando, ya que ambos forman parte de la plataforma .Net, compilan mediante el CIL de Microsoft y se administra u optimiza mediante el JIT/NGen, así que podemos asumir que el test es igual de válido para dicho lenguaje, por si alguien tenía dudas.
Saludos.