Los archivos descargados están dañados cuando la longitud del búfer es> 1

Estoy tratando de escribir una función que descargue un archivo en una URL específica. La función produce un archivo corrupto a menos que convierta el búfer en una matriz de tamaño 1 (como está en el código a continuación).

La declaración ternaria sobre la inicialización del búfer (que planeo usar) junto con valores enteros codificados distintos de 1 fabricará un archivo dañado.

Nota: MAX_BUFFER_SIZE es una constante, definida como 8192 (2 ^ 13) en mi código.

public static void downloadFile(String webPath, String localDir, String fileName) {
    try {
        File localFile;
        FileOutputStream writableLocalFile;
        InputStream stream;

        url = new URL(webPath);
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();

        int size = connection.getContentLength(); //File size in bytes
        int read = 0; //Bytes read

        localFile = new File(localDir);

        //Ensure that directory exists, otherwise create it.
        if (!localFile.exists())
            localFile.mkdirs();

        //Ensure that file exists, otherwise create it.
        //Note that if we define the file path as we do below initially and call mkdirs() it will create a folder with the file name (I.e. test.exe). There may be a better alternative, revisit later.
        localFile = new File(localDir + fileName);
        if (!localFile.exists())
            localFile.createNewFile();

        writableLocalFile = new FileOutputStream(localFile);
        stream = connection.getInputStream();

        byte[] buffer;
        int remaining;
        while (read != size) {
            remaining = size - read; //Bytes still to be read
            //remaining > MAX_BUFFER_SIZE ? MAX_BUFFER_SIZE : remaining
            buffer = new byte[1]; //Adjust buffer size according to remaining data (to be read).

            read += stream.read(buffer); //Read buffer-size amount of bytes from the stream.
            writableLocalFile.write(buffer, 0, buffer.length); //Args: Bytes to read, offset, number of bytes
        }

        System.out.println("Read " + read + " bytes.");

        writableLocalFile.close();
        stream.close();
    } catch (Throwable t) {
        t.printStackTrace();
    }
}

La razón por la que lo he escrito de esta manera es para que pueda proporcionar una barra de progreso en tiempo real al usuario mientras se está descargando. Lo he eliminado del código para reducir el desorden.

Respuesta 1
len = stream.read(buffer);
read += len;
writableLocalFile.write(buffer, 0, len); 

No debe usar buffer.length como lectura de bytes, debe usar el valor de retorno de la llamada de lectura. Debido a que podría devolver una lectura corta y luego su búfer contiene basura (0 bytes o datos de lecturas anteriores) después de los bytes leídos.

Y además de calcular el resto y usar buffers dinámicos, solo tienes que ir a 16k o algo así. La última lectura será corta, lo cual está bien.

Respuesta: 2

¿Existe alguna función en algún lugar que divida los números enteros o decimales en partes que sean lo más iguales posible y sumen el valor de entrada? Estoy buscando algo que funcione así: ...

¿Es posible convertir un archivo .class (de la biblioteca externa .jar) a un archivo .java? Estoy tratando de averiguar si es posible o no porque la fuente de la biblioteca externa no está disponible ...

Quiero construir mi proyecto, pero tengo dos errores a continuación: app / build / intermedtes / incremental / mergeDebugResources / merged.dir / values ​​/ values.xml y .gradle / caches / transforms-1 / files-1.1 / appcompat-v7- 27 ....

Posible duplicado: Proyecto Euler Problema 12 - C ++ Estoy tratando de obtener el primer número de triángulo con más de 400 divisores (número de triángulo, por ejemplo: 1,3,6,10). Por ejemplo, el triángulo número 6 tiene ...