Leer datos de archivo binario

11/05/2010 - 18:54 por Saga | Informe spam
Saludos. En esta ocasion tengo un archivo que contiene datos, tales como
numeros, fechas y bytes. Desarrolle el siguiente codigo para leer esta
informaicon:

Dim TheBytes() As Byte
Dim strNombre As String = ""
Dim bytHeader(3) As Byte
Dim bytByte As Byte
Dim lngTimeStamp As Integer
Dim bytExtra(1) As Byte
Dim intFH As Integer

On Error GoTo ehUncompressFile


intFH = FreeFile()

FileOpen(intFH, strArchivoDatos, OpenMode.Binary)

FileGet(intFH, (bytHeader))


If bytHeader(0) = 225 And bytHeader(1) = 179 Then

'Consigue la fecha y hora (num de segundos desde fecha en 1970).
FileGet(intFH, lngTimeStamp)

'Lee otros 2 bytes.
FileGet(intFH, (bytExtra))

If (bytHeader(3) And 16) = 16 Then

'Consigue el nombre.
Do
FileGet(intFH, bytByte)

If bytByte > 0 Then
strNombre = strNombre & Chr(bytByte)
End If
Loop Until bytByte = 0
End If


ReDim TheBytes(CInt(LOF(intFH) - 1))

FileGet(intFH, (TheBytes))

Basicamente, leo una cabecaera de 4 bytes, reviso que la "llave" sea la
correcta en los primeros dos bytes. Si lo es, consigo 4 bytes que tienen
una fecha y hora y otros dos byte, luego si el 5o bit del cuarto byte esta
puesto (-1) entonces consigo un nombre. Por fin el leo resto de los datos
a un arreglo (The Bytes)

Esta rutina la converti de otra en VB6 y estaba probada y funcionando
bien, solo que hoy que regrese a hacer algunas pruebas finales me
encuentro que no esta funcoinando. La primera instruccion de lectura
que lee los 4 bytes al arreglo byeCabecera() solo lee ceros. Ya revise
el archivo y efectivamente estan ahi los primeros 4 bytes tal como los
espero. No se porque ahora esta leyendo ceros. Cualquier orientacion
es bienvenida, o bien un metodo alterno mas confiable para poder
realizar la equivalente funcion. Gracias, Saga

Preguntas similare

Leer las respuestas

#1 SoftJaén
13/05/2010 - 14:57 | Informe spam
Hola, Saga:

No sabría decirte donde está el problema. Pero ya que estás utilizando
Visual Basic .NET, prueba a utilizar un objeto BinaryWriter (para escribir
en un archivo binario) y un objeto BinaryReader (para su posterior lectura).
Ambas clases se encuentran dentro del espacio de nombres System.IO, espacio
que deberás de importar en tu proyecto.

Por ejemplo, vamos a guardar en un archivo binario, un entero de 4 bytes
(Integer), seguidos de los ticks de una fecha cualquiera (un valor Long), y
a continuación, una cadena alfanumérica (String):

Imports System.IO

' Creamos un nuevo archivo binario con
' permisos de escritura.
'
Dim st As Stream = _
File.Open("C:\Temp\Archivo.dat", _
FileMode.Create, FileAccess.Write)

' Creamos un objeto BinaryWriter que lo
' asociaremos a la secuencia del archivo.
'
Using bw As New BinaryWriter(st)

' Escribimos un valor entero.
'
Dim n As Integer = 12345
bw.Write(n)

' Escribimos la fecha y hora actual, o mejor dicho, los
' Ticks correspondientes a la fecha y hora actual.
'
bw.Write(DateTime.Now.Ticks)

' Escribimos una valor alfanumérico
bw.Write("¡Hola, Mundo!")

' Cerramos los objetos
bw.Close()
st.Close()

End Using

Como sabemos el orden de los datos, significa que sabemos los tipos de datos
que contienen. Por tanto, bastaría con utilizar los métodos ReadXXX de un
objeto BinaryReader:

' Creamos una secuencia para leer el archivo binario
'
Dim st As Stream = _
File.Open("C:\Temp\Archivo.dat", _
FileMode.Open, FileAccess.Read)

' Creamos un objeto BinaryReader que lo
' asociaremos a la secuencia del archivo.
'
Using br As New BinaryReader(st)

' Leemos el primer valor que sabemos
' que es un Integer
'
Dim n As Integer = br.ReadInt32()

Debug.WriteLine(n)

' Leemos los Ticks de la fecha
'
Dim fecha As DateTime = New DateTime(br.ReadInt64)

Debug.WriteLine(fecha)

' Leemos el valor alfanumérico
Dim s As String = br.ReadString()

Debug.WriteLine(s)

' Cerramos los objetos
br.Close()
st.Close()

End Using

Mira a ver si de ésta manera puedes leer tu archivo binario.

Un saludo

Enrique Martínez
[MS MVP - VB]

Nota informativa: La información contenida en este mensaje, así como el
código fuente incluido en el mismo, se proporciona «COMO ESTÁ», sin
garantías de ninguna clase, y no otorga derecho alguno. Usted asume
cualquier riesgo al poner en práctica, utilizar o ejecutar lo recomendado o
sugerido en el presente mensaje.
Respuesta Responder a este mensaje
#2 Saga
13/05/2010 - 20:47 | Informe spam
Muchas gracias SoftJaén!

La solucion que encontre fue remover los parentesis que le puse al
nombre del arreglo de bytes:

FileGet(intFH, (bytHeader)) 'No funciona

FileGet(intFH, bytHeader) 'Si funciona

El problema se presento cuando decidi configurar Option Strict ON.

Aun asi, otros que he consultado me han recomendado no usar fileget()
y los otros comandos de esta familia. Mi objetivo es cambiar a usar el
binary reader, tal como recomiendas.

Una pregunta mas... veo que usas el estatuto "Using". Aunque lo he
buscado varias veces y visto ejemplos de su uso, aun no me queda
completamente claro para que se usa. Segun entiendo, su unico
uso es para crear bloques de codigo donde la variable que se
declara dentro del estatuto using sea local a ese bloque. Por
ejemplo, puedo hacer esto:

for i as integer = 0 to 10
x = x
next i

La variable i solo es valida dentro del bloque del for.

using i as integer
for i = 0 to 10
x = x
next i
end using

Este bloque seria equivalente al anterior con respecto al
alcance de i. ¿Es correcto como estoy viendo esto? De nuevo
gracias! Saga



"SoftJaén" wrote in message
news:
Hola, Saga:

No sabría decirte donde está el problema. Pero ya que estás utilizando
Visual Basic .NET, prueba a utilizar un objeto BinaryWriter (para escribir
en un archivo binario) y un objeto BinaryReader (para su posterior
lectura).
Ambas clases se encuentran dentro del espacio de nombres System.IO,
espacio
que deberás de importar en tu proyecto.

Por ejemplo, vamos a guardar en un archivo binario, un entero de 4 bytes
(Integer), seguidos de los ticks de una fecha cualquiera (un valor Long),
y
a continuación, una cadena alfanumérica (String):

Imports System.IO

' Creamos un nuevo archivo binario con
' permisos de escritura.
'
Dim st As Stream = _
File.Open("C:\Temp\Archivo.dat", _
FileMode.Create, FileAccess.Write)

' Creamos un objeto BinaryWriter que lo
' asociaremos a la secuencia del archivo.
'
Using bw As New BinaryWriter(st)

' Escribimos un valor entero.
'
Dim n As Integer = 12345
bw.Write(n)

' Escribimos la fecha y hora actual, o mejor dicho, los
' Ticks correspondientes a la fecha y hora actual.
'
bw.Write(DateTime.Now.Ticks)

' Escribimos una valor alfanumérico
bw.Write("¡Hola, Mundo!")

' Cerramos los objetos
bw.Close()
st.Close()

End Using

Como sabemos el orden de los datos, significa que sabemos los tipos de
datos
que contienen. Por tanto, bastaría con utilizar los métodos ReadXXX de un
objeto BinaryReader:

' Creamos una secuencia para leer el archivo binario
'
Dim st As Stream = _
File.Open("C:\Temp\Archivo.dat", _
FileMode.Open, FileAccess.Read)

' Creamos un objeto BinaryReader que lo
' asociaremos a la secuencia del archivo.
'
Using br As New BinaryReader(st)

' Leemos el primer valor que sabemos
' que es un Integer
'
Dim n As Integer = br.ReadInt32()

Debug.WriteLine(n)

' Leemos los Ticks de la fecha
'
Dim fecha As DateTime = New DateTime(br.ReadInt64)

Debug.WriteLine(fecha)

' Leemos el valor alfanumérico
Dim s As String = br.ReadString()

Debug.WriteLine(s)

' Cerramos los objetos
br.Close()
st.Close()

End Using

Mira a ver si de ésta manera puedes leer tu archivo binario.

Un saludo

Enrique Martínez
[MS MVP - VB]

Nota informativa: La información contenida en este mensaje, así como el
código fuente incluido en el mismo, se proporciona «COMO ESTÁ», sin
garantías de ninguna clase, y no otorga derecho alguno. Usted asume
cualquier riesgo al poner en práctica, utilizar o ejecutar lo recomendado
o
sugerido en el presente mensaje.


Respuesta Responder a este mensaje
#3 SoftJaén
14/05/2010 - 00:42 | Informe spam
"Saga" escribió:

La solucion que encontre fue remover los parentesis que
le puse al nombre del arreglo de bytes:

FileGet(intFH, (bytHeader)) 'No funciona

FileGet(intFH, bytHeader) 'Si funciona

El problema se presento cuando decidi configurar
Option Strict ON.



¡Claro! Es que si tienes activada la instrucción Option Strict On (que es lo
recomendable), no puedes pasar una matriz a la función FileGet, cuyo segundo
parámetro del tipo System.Array se encuentra definido «por referencia»
(ByRef), ya que se puede dar una restricción al cargar de nuevo el parámetro
System.Array en la matriz definida del tipo Byte, de ahí que tengas que
encerrar entre paréntesis el argumento de llamada, para pasarlo «por valor»
(ByVal). Y puede ser que al pasar el array por valor no te funcione. Tienes
que activar Option Strict On y utilizar un objeto BinariReader, que para eso
estamos en .NET. :-)

Una pregunta mas... veo que usas el estatuto "Using". Aunque lo he
buscado varias veces y visto ejemplos de su uso, aun no me queda
completamente claro para que se usa. Segun entiendo, su unico
uso es para crear bloques de codigo donde la variable que se
declara dentro del estatuto using sea local a ese bloque. Por
ejemplo, puedo hacer esto:

for i as integer = 0 to 10
x = x
next i

La variable i solo es valida dentro del bloque del for.

using i as integer
for i = 0 to 10
x = x
next i
end using

Este bloque seria equivalente al anterior con respecto al
alcance de i. ¿Es correcto como estoy viendo esto?



No, en ningún caso es equivalente, ni tampoco se puede usar una variable
Integer, Long, String, etc., para definir un bloque Using ... End Using.

En el bloque For ... Next, el ámbito de la variable «i» sería el propio
bloque donde se encuentra declarada. E igual ámbito de visibilidad tendría
dentro del bloque Using si el tipo de dato de la variable declarada
implementara la interfaz System.IDisponsable, que es el requisito que debe
de cumplir el tipo de dato de la variable que se defina en un bloque Using
... End Using. Pero los tipos de datos básicos no implementan IDisponsable,
al igual que otras muchas clases del marco de trabajo de .NET, por tanto,
obtendrás una excepción en tiempo de diseño.

El utilizar un bloque Using es porque de ésta manera nos aseguramos de que
al final se llamará automáticamente al método Dispose del objeto declarado,
con lo que se destruirá el objeto. Podemos obviar la instrucción Using y
efectuar una llamada explícita al método Dispose del objeto, pero hay que
acordarse de hacerlo, y muchas veces, como que no nos acordamos de hacerlo,
y es recomendable y hasta necesario porque estamos trabajando con apertura y
cierre de archivos, que en el argot de .NET se tratan de «recursos no
administrados», por tanto, no están en manos del «recolector de elementos no
utilizados» y hay que destruirlos expresamente para liberarlos.

Enrique Martínez
[MS MVP - VB]

Nota informativa: La información contenida en este mensaje, así como el
código fuente incluido en el mismo, se proporciona «COMO ESTÁ», sin
garantías de ninguna clase, y no otorga derecho alguno. Usted asume
cualquier riesgo al poner en práctica, utilizar o ejecutar lo recomendado o
sugerido en el presente mensaje.
Respuesta Responder a este mensaje
#4 Saga
14/05/2010 - 17:04 | Informe spam
Gracias por la informacion otorgada. Se agradece el tiempo que tomaste
en redactarla. Me ha sido muy util, considerando que en ningun lugar
encontre una explicacion tan sencilla y concisa.

Este pasado 12 de Febrero fue mi primer encuentro con el mundo de
.NET. Lo he encontrado fascinante, pero no sin sus detalles. El
problema mas grande con el que me he topado es determinar la
mejor practica para realizar alguna funcion que se puede hacer
usando sintaxis tomado directamente de VB6. Un ejemplo pudiera
ser el uso de la funcion fileget(). Este metodo funciona, aunque se
que no es la tecnica mas recomendada. Hasta esta semana que
pregunte es que me recomendaron el uso del lector binario. Espero
implementar y documentar esta informacion para que no quede en el
olvido. De nuevo, gracias.

Saludos! Saga
email Siga el debate Respuesta Responder a este mensaje
Ads by Google
Help Hacer una preguntaRespuesta Tengo una respuesta
Search Busqueda sugerida