Como guardar un índice de ficheros

Iniciado por Bob_Ale, 9 Octubre 2015, 20:21 PM

0 Miembros y 1 Visitante están viendo este tema.

Bob_Ale

Hola!

Estoy haciendo un programa en C# para crear un índice de ficheros para despues usar este índice en otras aplicaciones.

La verdad es que creo que ya lo tengo terminado pero tengo una duda.
¿Como o en que formato o estructura guardar el índice?

Por ahora busco todos los directorios que quiero indexar y los guardo en una estructura.
Después estoy salvando dicha estructura en un fichero XML. Que en C# guardar una estructura en un XML es super sencillo y rápido.

¿Pero es la mejor manera,  guardar un índice en un XML?

Enviado desde mi GT-I9300 mediante Tapatalk

Eleкtro

#1
Cita de: Bob_Ale en  9 Octubre 2015, 20:21 PMEstoy 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/protobuf

En 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:

Cita de: Resultado de ejecuciónTotal 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. )
Código (vbnet) [Seleccionar]
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.rar

PD: 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.








Bob_Ale

Muchas gracias Elektro!
Una respuesta muy completa. La estudiare con mucha atención.

Me preocupa (obsesiona) el rendimiento.
Esta índice se construirá en local, pero el acceso al índice será por red y desde distintos equipos.
No me preocupa si es legible o no.

Enviado desde mi GT-I9300 mediante Tapatalk

Bob_Ale

Cita de: Eleкtro en  9 Octubre 2015, 23:15 PM
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/protobuf

En 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:

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. )
Código (vbnet) [Seleccionar]
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.rar

PD: 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.
Hola!

He estado revisando mi código y es similar al que tengo yo (formato XML).

Me gusta el rendimiento y el tamaño del fichero binario pero he sido incapaz de leerlo con VB6.
He leído por ahi que con VB6 no es posible deserializar binarios.
Hasta que no encuentre una solución me quedaré con el XML normal.

¿Sería interesante que compartiera mi código, lo veo tan simple?

Enviado desde mi GT-I9300 mediante Tapatalk