none
Usar FileStream.Read o Write con un fichero de Lenth mayor que Int32.Length RRS feed

  • Pregunta

  • Buenas noches,

    Estoy usando VB.NET VB para crear un ZIP de un archivo de gran tamaño (3GB) el problema es que al leer el fichero con el método FileStream.Read este método tiene un límite de Int32 que dicho archivo lo supera por lo que falla la función.

    Este es el código:

    Dim strmZipOutputStream As ZipOutputStream
    strmZipOutputStream = New ZipOutputStream(File.Create("fichero.zip"))
    Dim strmFile As FileStream = File.OpenRead(strFile)
    Dim abyBuffer(Convert.ToInt32(strmFile.Length - 1)) As Byte
    'La siguiente línea falla porque abybuffer.legth es > Int32
    strmFile.Read(abyBuffer, 0, abyBuffer.Length)
    ...
    ...
    'También falla el .Write para añadirlo al ZIP
    strmZipOutputStream.Write(abyBuffer, 0, abyBuffer.Length)
    

    Por lo que he pensado en ir leyendo el fichero en bloques para evitar sobrepasar el máximo del Int32 pero tampoco me funciona, en este caso el error es OutOfMemory. Este es el código que yo creo que está bien:

    Const maxLength As Integer = Int32.MaxValue 
    Dim buffer As Byte() = New Byte(maxLength - 1) {}
    Dim totalBytesRead As Integer = 0
    
    While totalBytesRead < buffer.Length
         Dim bytesRead As Integer = strmFile.Read(buffer, totalBytesRead, buffer.Length - totalBytesRead)
       If bytesRead = 0 Then Exit While
    
      strmZipOutputStream.Write(buffer, totalBytesRead, buffer.Length - totalBytesRead)
       totalBytesRead += bytesRead
    End While

    He buscado posibles soluciones y he visto que existe un método .CopyTo pero si lo invoco me da error dice que FileStream no acepta CopyTo:

    strFile.CopyTo(strmZipOutputStream)

    Alguna idea de cómo resolverlo??

    Gracias desde ya!

    lunes, 21 de mayo de 2018 20:58

Respuestas

  • a) No hace falta que leas bloques de 2GB. puedes usar un buffer más pequeño, y así no te quedas sin memoria. Simplemente tendrá que dar hacer más iteraciones el While.

    b) La variable totalBytesRead tendrá que ser un Long, no vale con un Int si quieres leer más de 2Gb. Per en realidad no necesitas sumar los bytes totales, basta con iterar hasta que lea menos de los solicitados.

    Const bufLen As Integer = 65536
    Dim buffer As Byte() = New Byte(bufLen)
    Dim bytesRead As Integer
    
    Do 
         bytesRead = strmFile.Read(buffer, 0, bufLen)
         strmZipOutputStream.Write(buffer, 0, bytesRead)
    Until bytesRead < bufLen

    lunes, 21 de mayo de 2018 21:23