Archivo al byte [] en Java

757

¿Cómo convierto java.io.Filea a byte[]?

Ben Noland
fuente
Un uso que se me ocurre es leer objetos serializados del archivo.
Mahm00d
2
Otro es encontrar el tipo de archivo usando el encabezado.
James P.
Pruebe este byte [] bytes = nulo; BufferedInputStream fileInputStream = null; pruebe {File file = new File (filePath); fileInputStream = new BufferedInputStream (nuevo FileInputStream (archivo)); // fileInputStream = Thread.currentThread (). getContextClassLoader (). getResourceAsStream (this.filePath); bytes = nuevo byte [(int) file.length ()]; fileInputStream.read (bytes); } catch (FileNotFoundException ex) {throw ex; }
Rohit Chaurasiya

Respuestas:

486

Depende de lo que sea mejor para ti. En cuanto a la productividad, no reinvente la rueda y use Apache Commons. Que esta aqui IOUtils.toByteArray(InputStream input).

svachon
fuente
29
@ymajoros: ¡Tan cierto! Prefiero tener algunas líneas de código adicionales que otra dependencia más. Las dependencias tienen costos ocultos. Debe mantenerse actualizado con esa biblioteca, incluir la dependencia en sus scripts de compilación, etc., comunicarlo a las personas que usan su código, etc. escríbelo tú mismo.
Stijn de Witt
11
Esto responde la pregunta de cómo leer un archivo, pero no la pregunta de cómo convertir un objeto de tipo java.IO.File a byte [].
Ingo
55
¿Cómo se usa esto para leer un Fileto byte[]? Estoy usando Java6, así que no puedo usar los métodos NIO :(
PASTELERO
44
@ymajoros, ¿podría compartir con nosotros cualquier "solución estándar de 3 líneas" para que no tengamos que confiar en una reinvención de la dependencia de la rueda?
matteo
3
@matteo: ¿alguno? Ver otras respuestas, por ejemplo, Files.readAllBytes (). Simple, sin dependencia.
ymajoros
1293

Desde JDK 7 puedes usar Files.readAllBytes(Path).

Ejemplo:

import java.io.File;
import java.nio.file.Files;

File file;
// ...(file is initialised)...
byte[] fileContent = Files.readAllBytes(file.toPath());
Michael Pollmeier
fuente
10
Tengo un objeto File, no una ruta (desde la solicitud de publicación http)
aldo.roman.nurena
81
@ aldo.roman.nurena JDK7 introdujo un método File.toPath () que le dará un objeto de ruta.
KevinL
66
Puede obtener una ruta desde un archivo. Pruebe: Archivo de archivo = Archivo nuevo ("/ ruta"); Ruta ruta = Paths.get (file.getAbsolutePath ()); byte [] data = Files.readAllBytes (ruta);
gfelisberto
2
¿Cómo se maneja el cierre del archivo en java.nio? En otras palabras, ¿debería el código anterior cerrar algo?
akauppi
44
@akauppi Vea el enlace en la respuesta: "El método asegura que el archivo esté cerrado ..."
Bernhard Barker
226

Desde JDK 7 - un revestimiento:

byte[] array = Files.readAllBytes(Paths.get("/path/to/file"));

No se necesitan dependencias externas.

Paulius Matulionis
fuente
13
Esta es ahora una mejor opción que la respuesta aceptada, que requiere Apache Commons.
james.garriss
1
Gracias :) También necesitaba este: String text = new String (Files.readAllBytes (new File ("/ path / to / file"). ToPath ())); que es originalmente de stackoverflow.com/a/26888713/1257959
cgl
55
En Android, requiere un nivel mínimo de API para ser 26.
Ashutosh Chamoli
2
Tendrá que agregar import java.nio.file.Files;y import java.nio.file.Paths;si aún no lo ha hecho.
Sam
164
import java.io.RandomAccessFile;
RandomAccessFile f = new RandomAccessFile(fileName, "r");
byte[] b = new byte[(int)f.length()];
f.readFully(b);

Documentación para Java 8: http://docs.oracle.com/javase/8/docs/api/java/io/RandomAccessFile.html

Dmitry Mitskevich
fuente
2
Debe verificar el valor de retorno de f.read (). Aquí a veces puede suceder que no leerá todo el archivo.
bugs_
8
Tal situación solo puede ocurrir si el archivo está cambiando mientras lo está leyendo. En todos los demás casos, se produce IOException. Para resolver este problema, sugiero abrir el archivo en modo de lectura y escritura: RandomAccessFile (fileName, "rw")
Dmitry Mitskevich
55
Podría imaginar otras fuentes para solo leer una parte del archivo (el archivo está en un recurso compartido de red ...) readFully () tiene el contrato que está buscando.
DThought
3
Recuerde que RandomAccessFile no es seguro para subprocesos. Por lo tanto, la sincronización puede ser necesaria en algunos casos.
bancer
@DmitryMitskevich También hay otros casos, en sistemas de archivos que posiblemente no son conformes. por ejemplo, leer "archivos" en / proc / on linux puede causar lecturas cortas (es decir, necesita un bucle para leerlo todo)
nos
78

Básicamente hay que leerlo en la memoria. Abra el archivo, asigne la matriz y lea el contenido del archivo en la matriz.

La forma más simple es algo similar a esto:

public byte[] read(File file) throws IOException, FileTooBigException {
    if (file.length() > MAX_FILE_SIZE) {
        throw new FileTooBigException(file);
    }
    ByteArrayOutputStream ous = null;
    InputStream ios = null;
    try {
        byte[] buffer = new byte[4096];
        ous = new ByteArrayOutputStream();
        ios = new FileInputStream(file);
        int read = 0;
        while ((read = ios.read(buffer)) != -1) {
            ous.write(buffer, 0, read);
        }
    }finally {
        try {
            if (ous != null)
                ous.close();
        } catch (IOException e) {
        }

        try {
            if (ios != null)
                ios.close();
        } catch (IOException e) {
        }
    }
    return ous.toByteArray();
}

Esto tiene una copia innecesaria del contenido del archivo (en realidad, los datos se copian tres veces: de archivo a buffer, de buffera ByteArrayOutputStream, de ByteArrayOutputStreama la matriz resultante real).

También debe asegurarse de leer en la memoria solo archivos de un cierto tamaño (esto generalmente depende de la aplicación) :-).

También debe tratar el IOExceptionexterior de la función.

Otra forma es esta:

public byte[] read(File file) throws IOException, FileTooBigException {
    if (file.length() > MAX_FILE_SIZE) {
        throw new FileTooBigException(file);
    }

    byte[] buffer = new byte[(int) file.length()];
    InputStream ios = null;
    try {
        ios = new FileInputStream(file);
        if (ios.read(buffer) == -1) {
            throw new IOException(
                    "EOF reached while trying to read the whole file");
        }
    } finally {
        try {
            if (ios != null)
                ios.close();
        } catch (IOException e) {
        }
    }
    return buffer;
}

Esto no tiene copia innecesaria.

FileTooBigExceptiones una excepción de aplicación personalizada. La MAX_FILE_SIZEconstante es una aplicación de parámetros.

Para archivos grandes, probablemente deberías pensar en un algoritmo de procesamiento de flujo o usar mapeo de memoria (ver java.nio).

Mihai Toader
fuente
iOS debe declararse fuera del intento
Daryl Spitzer
La declaración "ios.read (buffer)" en el segundo ejemplo solo se leerá en los primeros 4096 bytes del archivo (suponiendo el mismo buffer 4k que se usó en el primer ejemplo). Para que el segundo ejemplo funcione, creo que la lectura tiene que estar dentro de un ciclo while que verifica el resultado para -1 (final del archivo alcanzado).
Stijn de Witt
Lo sentimos, descarte mi comentario anterior, se perdió la instrucción que establece el búfer en la longitud del archivo Aún así, el primer ejemplo me gusta mucho más. Leer un archivo completo en un búfer de una vez no es escalable. Se arriesgará a quedarse sin memoria cuando el archivo sea grande.
Stijn de Witt
La forma "más simple" haría uso de probar con recursos.
Sina Madani
Genial, pero un poco detallado.
Sapphire_Brick
77

Como alguien dijo, Apache Commons File Utils podría tener lo que estás buscando

public static byte[] readFileToByteArray(File file) throws IOException

Ejemplo de uso ( Program.java):

import org.apache.commons.io.FileUtils;
public class Program {
    public static void main(String[] args) throws IOException {
        File file = new File(args[0]);  // assume args[0] is the path to file
        byte[] data = FileUtils.readFileToByteArray(file);
        ...
    }
}
Tom
fuente
23

También puede usar la API de NIO para hacerlo. Podría hacer esto con este código siempre que el tamaño total del archivo (en bytes) se ajuste a un int.

File f = new File("c:\\wscp.script");
FileInputStream fin = null;
FileChannel ch = null;
try {
    fin = new FileInputStream(f);
    ch = fin.getChannel();
    int size = (int) ch.size();
    MappedByteBuffer buf = ch.map(MapMode.READ_ONLY, 0, size);
    byte[] bytes = new byte[size];
    buf.get(bytes);

} catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
} finally {
    try {
        if (fin != null) {
            fin.close();
        }
        if (ch != null) {
            ch.close();
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
}

Creo que es muy rápido ya que está usando MappedByteBuffer.

Amit
fuente
2
no hay absolutamente ninguna necesidad de usar la asignación de memoria si solo va a leer el archivo una vez, y terminará usando el doble de memoria que con un FileInputStream normal.
james
1
Lamentablemente, MappedByteBuffer no se lanza automáticamente.
Tom Hawtin - tackline
2
impresionante, el nuevo ejemplo incluye printStackTrace, manejo clásico de excepciones rotas.
james
Estoy de acuerdo ... Es el material predeterminado que pone eclipse. ¡Creo que debería volver a lanzar la excepción!
Amit
He estado comparando nio para crear un byte [] desde un archivo. Aparte de usar un búfer directo, de hecho toma el doble de memoria. Aunque es más rápido para archivos muy grandes (aproximadamente el doble de rápido que un IO almacenado en memoria intermedia para 200M), parece perder un factor de 5 para archivos de alrededor de 5M.
Chaffers
22

Si no tiene Java 8, y está de acuerdo conmigo en que incluir una biblioteca masiva para evitar escribir algunas líneas de código es una mala idea:

public static byte[] readBytes(InputStream inputStream) throws IOException {
    byte[] b = new byte[1024];
    ByteArrayOutputStream os = new ByteArrayOutputStream();
    int c;
    while ((c = inputStream.read(b)) != -1) {
        os.write(b, 0, c);
    }
    return os.toByteArray();
}

La persona que llama es responsable de cerrar la transmisión.

Jeffrey Blattman
fuente
21
// Returns the contents of the file in a byte array.
    public static byte[] getBytesFromFile(File file) throws IOException {        
        // Get the size of the file
        long length = file.length();

        // You cannot create an array using a long type.
        // It needs to be an int type.
        // Before converting to an int type, check
        // to ensure that file is not larger than Integer.MAX_VALUE.
        if (length > Integer.MAX_VALUE) {
            // File is too large
            throw new IOException("File is too large!");
        }

        // Create the byte array to hold the data
        byte[] bytes = new byte[(int)length];

        // Read in the bytes
        int offset = 0;
        int numRead = 0;

        InputStream is = new FileInputStream(file);
        try {
            while (offset < bytes.length
                   && (numRead=is.read(bytes, offset, bytes.length-offset)) >= 0) {
                offset += numRead;
            }
        } finally {
            is.close();
        }

        // Ensure all the bytes have been read in
        if (offset < bytes.length) {
            throw new IOException("Could not completely read file "+file.getName());
        }
        return bytes;
    }
Cuga
fuente
Además, ponga numRead dentro del bucle. Declare variables en el alcance válido más pequeño que pueda. Ponerlo fuera del ciclo while solo es necesario para habilitar esa complicada prueba "while"; sería mejor hacer la prueba de EOF dentro del bucle (y lanzar una EOFException si ocurre).
erickson
throw new IOException("File is too large!");¿Qué debemos hacer cuando el archivo es demasiado grande? ¿Hay también algún ejemplo al respecto?
Fer
21

Manera simple de hacerlo:

File fff = new File("/path/to/file");
FileInputStream fileInputStream = new FileInputStream(fff);

// int byteLength = fff.length(); 

// In android the result of file.length() is long
long byteLength = fff.length(); // byte count of the file-content

byte[] filecontent = new byte[(int) byteLength];
fileInputStream.read(filecontent, 0, (int) byteLength);
Sudip Bhandari
fuente
Hay formas más simples, como las frases que ya se han mencionado.
Sapphire_Brick
@Sapphire_Brick Formas más simples, sí, pero los revestimientos únicos no se ajustan a todas las situaciones. Tal como Android.
Behr
17

La forma más simple de leer bytes del archivo

import java.io.*;

class ReadBytesFromFile {
    public static void main(String args[]) throws Exception {
        // getBytes from anyWhere
        // I'm getting byte array from File
        File file = null;
        FileInputStream fileStream = new FileInputStream(file = new File("ByteArrayInputStreamClass.java"));

        // Instantiate array
        byte[] arr = new byte[(int) file.length()];

        // read All bytes of File stream
        fileStream.read(arr, 0, arr.length);

        for (int X : arr) {
            System.out.print((char) X);
        }
    }
}
Muhammad Sadiq
fuente
1
Discuto
¿Puedes explicar aquí? ¿Por qué tienes una discusión?
Muhammad Sadiq
3
Nada especial, pero usted dice más simple y veo soluciones más simples -> en mi opinión, no es la más simple. Tal vez fue hace un par de años, pero el mundo está cambiando. No etiquetaría mis propias soluciones con tal declaración. ;) Si solo escribieras "En mi opinión, lo más simple es ..." o "Lo más simple que encontré ..." No quiero molestarte, solo pensé que era bueno comunicar esto.
BlondCode
@ MuhammadSadiq: no importe nada .*, se considera una mala práctica.
Sapphire_Brick
13

Guava tiene Files.toByteArray () para ofrecerte. Tiene varias ventajas:

  1. Cubre el caso de la esquina donde los archivos informan una longitud de 0 pero aún tienen contenido
  2. Está altamente optimizado, obtienes una OutOfMemoryException si intentas leer un archivo grande antes de intentar cargar el archivo. (Mediante el uso inteligente de file.length ())
  3. No tienes que reinventar la rueda.
jontejj
fuente
12
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Path;

File file = getYourFile();
Path path = file.toPath();
byte[] data = Files.readAllBytes(path);
BlondCode
fuente
¿Qué nivel de JDK es este?
Jonathan S. Fisher
11

Usando el mismo enfoque que la respuesta wiki de la comunidad, pero más limpio y compilado de fábrica (enfoque preferido si no desea importar las bibliotecas de Apache Commons, por ejemplo, en Android):

public static byte[] getFileBytes(File file) throws IOException {
    ByteArrayOutputStream ous = null;
    InputStream ios = null;
    try {
        byte[] buffer = new byte[4096];
        ous = new ByteArrayOutputStream();
        ios = new FileInputStream(file);
        int read = 0;
        while ((read = ios.read(buffer)) != -1)
            ous.write(buffer, 0, read);
    } finally {
        try {
            if (ous != null)
                ous.close();
        } catch (IOException e) {
            // swallow, since not that important
        }
        try {
            if (ios != null)
                ios.close();
        } catch (IOException e) {
            // swallow, since not that important
        }
    }
    return ous.toByteArray();
}
manmal
fuente
8

Creo que esta es la forma más fácil:

org.apache.commons.io.FileUtils.readFileToByteArray(file);
Cristian Tetic
fuente
77
Ya hay una respuesta con esta sugerencia de Tom en 2009
Knut Herrmann
7

ReadFully Lee b.length bytes de este archivo en la matriz de bytes, comenzando en el puntero del archivo actual. Este método lee repetidamente del archivo hasta que se lee el número de bytes solicitado. Este método bloquea hasta que se lee el número de bytes solicitado, se detecta el final de la secuencia o se produce una excepción.

RandomAccessFile f = new RandomAccessFile(fileName, "r");
byte[] b = new byte[(int)f.length()];
f.readFully(b);
Tarun M
fuente
5

Si desea leer bytes en un búfer de bytes preasignado, esta respuesta puede ayudar.

Su primera suposición probablemente sería usar InputStream read(byte[]). Sin embargo, este método tiene una falla que lo hace irrazonablemente difícil de usar: no hay garantía de que la matriz se llene completamente, incluso si no se encuentra EOF.

En cambio, échale un vistazo DataInputStream readFully(byte[]). Este es un contenedor para flujos de entrada y no tiene el problema mencionado anteriormente. Además, este método se produce cuando se encuentra EOF. Mucho más bonito.

Laurens Holst
fuente
4

La siguiente manera no solo convierte un archivo java.io.File a un byte [], también descubrí que es la forma más rápida de leer un archivo, al probar muchos métodos diferentes de lectura de archivos Java entre sí:

java.nio.file.Files.readAllBytes ()

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;

public class ReadFile_Files_ReadAllBytes {
  public static void main(String [] pArgs) throws IOException {
    String fileName = "c:\\temp\\sample-10KB.txt";
    File file = new File(fileName);

    byte [] fileBytes = Files.readAllBytes(file.toPath());
    char singleChar;
    for(byte b : fileBytes) {
      singleChar = (char) b;
      System.out.print(singleChar);
    }
  }
}
gomisha
fuente
3

Permítanme agregar otra solución sin usar bibliotecas de terceros. Reutiliza un patrón de manejo de excepciones propuesto por Scott ( enlace ). Y moví la parte fea a un mensaje separado (me escondería en alguna clase de FileUtils;))

public void someMethod() {
    final byte[] buffer = read(new File("test.txt"));
}

private byte[] read(final File file) {
    if (file.isDirectory())
        throw new RuntimeException("Unsupported operation, file "
                + file.getAbsolutePath() + " is a directory");
    if (file.length() > Integer.MAX_VALUE)
        throw new RuntimeException("Unsupported operation, file "
                + file.getAbsolutePath() + " is too big");

    Throwable pending = null;
    FileInputStream in = null;
    final byte buffer[] = new byte[(int) file.length()];
    try {
        in = new FileInputStream(file);
        in.read(buffer);
    } catch (Exception e) {
        pending = new RuntimeException("Exception occured on reading file "
                + file.getAbsolutePath(), e);
    } finally {
        if (in != null) {
            try {
                in.close();
            } catch (Exception e) {
                if (pending == null) {
                    pending = new RuntimeException(
                        "Exception occured on closing file" 
                             + file.getAbsolutePath(), e);
                }
            }
        }
        if (pending != null) {
            throw new RuntimeException(pending);
        }
    }
    return buffer;
}
Andreas Dolk
fuente
3
public static byte[] readBytes(InputStream inputStream) throws IOException {
    byte[] buffer = new byte[32 * 1024];
    int bufferSize = 0;
    for (;;) {
        int read = inputStream.read(buffer, bufferSize, buffer.length - bufferSize);
        if (read == -1) {
            return Arrays.copyOf(buffer, bufferSize);
        }
        bufferSize += read;
        if (bufferSize == buffer.length) {
            buffer = Arrays.copyOf(buffer, bufferSize * 2);
        }
    }
}
mazatwork
fuente
1

Otra forma de leer bytes del archivo

Reader reader = null;
    try {
        reader = new FileReader(file);
        char buf[] = new char[8192];
        int len;
        StringBuilder s = new StringBuilder();
        while ((len = reader.read(buf)) >= 0) {
            s.append(buf, 0, len);
            byte[] byteArray = s.toString().getBytes();
        }
    } catch(FileNotFoundException ex) {
    } catch(IOException e) {
    }
    finally {
        if (reader != null) {
            reader.close();
        }
    }
Muhammad Aamir Ali
fuente
No use bloques huecos. dificulta la depuración.
Sapphire_Brick
1
//The file that you wanna convert into byte[]
File file=new File("/storage/0CE2-EA3D/DCIM/Camera/VID_20190822_205931.mp4"); 

FileInputStream fileInputStream=new FileInputStream(file);
byte[] data=new byte[(int) file.length()];
BufferedInputStream bufferedInputStream=new BufferedInputStream(fileInputStream);
bufferedInputStream.read(data,0,data.length);

//Now the bytes of the file are contain in the "byte[] data"
Usama Mehmood
fuente
1
Si bien este código puede proporcionar una solución a la pregunta, es mejor agregar contexto sobre por qué / cómo funciona. Esto puede ayudar a los futuros usuarios a aprender y aplicar ese conocimiento a su propio código. También es probable que reciba comentarios positivos de los usuarios en forma de votos a favor, cuando se explique el código.
borchvm
Bueno, esa es la parte importante que tendré en cuenta en futuras publicaciones. Gracias por tus ideas útiles.
Usama Mehmood
0

Prueba esto :

import sun.misc.IOUtils;
import java.io.IOException;

try {
    String path="";
    InputStream inputStream=new FileInputStream(path);
    byte[] data=IOUtils.readFully(inputStream,-1,false);
}
catch (IOException e) {
    System.out.println(e);
}
Maifee Ul Asad
fuente
Eso requiere una implementación particular de JRE que romperá la aplicación si se ejecuta en otro JRE.
Rattaman 01 de
2
pequeño error: es IOException y no IOexception, pero gracias :)
Matan Marciano
1
@MatanMarciano: my bad
Sapphire_Brick
-7

En JDK8

Stream<String> lines = Files.lines(path);
String data = lines.collect(Collectors.joining("\n"));
lines.close();
Beaucequebec
fuente
2
Lea la pregunta, amigo francés, acerca de la conversión a un "byte []" y su respuesta no proporciona eso.
Kaiser Keister
2
¡Esto no proporciona una opción remota remota para responder para convertir a byte []!
Anddo