Cela dépend de ce que signifie le mieux pour vous. Côté productivité, ne réinventez pas la roue et utilisez Apache Commons. C'est ici IOUtils.toByteArray(InputStream input).
@ymajoros: Tellement vrai! Je préfère avoir quelques lignes de code supplémentaires qu'une autre dépendance. Les dépendances ont des coûts cachés. Vous devez rester à jour avec cette bibliothèque, inclure la dépendance dans votre script de construction, etc., la communiquer aux personnes utilisant votre code, etc. Si vous utilisez déjà une bibliothèque qui a du code pour l'utiliser, utilisez-la, autrement je dirais écris-le toi-même.
Stijn de Witt
11
Cela répond à la question de savoir comment lire un fichier, mais pas à la question de savoir comment convertir un objet de type java.IO.File en octet [].
Ingo
5
Comment est-ce utilisé pour lire un Fileà byte[]? J'utilise Java6, je ne peux donc pas utiliser les méthodes NIO :(
PASTRY
4
@ymajoros aimeriez-vous partager avec nous toute "solution standard à 3 lignes", afin que nous n'ayons pas à compter sur une dépendance réinventant la roue?
matteo
3
@matteo: tout? Voir d'autres réponses, par exemple Files.readAllBytes (). Simple, pas de dépendance.
J'ai un objet File, pas un chemin (à partir de la demande de publication http)
aldo.roman.nurena
81
@ aldo.roman.nurena JDK7 a introduit une méthode File.toPath () qui vous donnera un objet Path.
KevinL
6
Vous pouvez obtenir un chemin d'accès à partir d'un fichier. Essayez: File file = new File ("/ path"); Path path = Paths.get (file.getAbsolutePath ()); byte [] data = Files.readAllBytes (chemin);
gfelisberto
2
Comment la fermeture de fichiers est-elle gérée dans java.nio - en d'autres termes, le code ci-dessus devrait-il fermer quelque chose?
akauppi
4
@akauppi Voir le lien dans la réponse: "La méthode garantit la fermeture du dossier ..."
C'est maintenant un meilleur choix que la réponse acceptée, qui nécessite Apache Commons.
james.garriss
1
Merci :) J'avais aussi besoin de celui-ci: String text = new String (Files.readAllBytes (new File ("/ path / to / file"). ToPath ())); qui est originaire de stackoverflow.com/a/26888713/1257959
cgl
5
Sous Android, le niveau d'API minimum doit être de 26.
Ashutosh Chamoli
2
Vous devrez ajouter import java.nio.file.Files;et import java.nio.file.Paths;si vous ne l'avez pas déjà fait.
Sam
164
import java.io.RandomAccessFile;RandomAccessFile f =newRandomAccessFile(fileName,"r");byte[] b =newbyte[(int)f.length()];
f.readFully(b);
Vous devez vérifier la valeur de retour de f.read (). Cela peut parfois arriver, que vous ne lirez pas le fichier entier.
bugs_
8
Une telle situation ne peut se produire que si le fichier change pendant que vous le lisez. Dans tous les autres cas, IOException est levée. Pour résoudre ce problème, je suggère d'ouvrir le fichier en mode lecture-écriture: RandomAccessFile (fileName, "rw")
Dmitry Mitskevich
5
Je pourrais imaginer d'autres sources pour ne lire qu'une partie du fichier (le fichier est sur un partage réseau ...) readFully () a le contrat que vous recherchez.
DThought
3
N'oubliez pas que RandomAccessFile n'est pas sûr pour les threads. Ainsi, la synchronisation peut être nécessaire dans certains cas.
danseur
@DmitryMitskevich Il existe également d'autres cas, sur des systèmes de fichiers qui sont peut-être non conformes. Par exemple, la lecture de "fichiers" dans / proc / sous linux peut provoquer de courtes lectures (c'est-à-dire que vous avez besoin d'une boucle pour tout lire)
nos
78
Fondamentalement, vous devez le lire en mémoire. Ouvrez le fichier, allouez le tableau et lisez le contenu du fichier dans le tableau.
Cela a une copie inutile du contenu du fichier (en fait, les données sont copiées trois fois: du fichier à buffer, de bufferà ByteArrayOutputStream, de ByteArrayOutputStreamau tableau résultant réel).
Vous devez également vous assurer de ne lire en mémoire que les fichiers jusqu'à une certaine taille (cela dépend généralement de l'application) :-).
Vous devez également traiter l' IOExceptionextérieur de la fonction.
Une autre façon est la suivante:
publicbyte[] read(File file)throwsIOException,FileTooBigException{if(file.length()> MAX_FILE_SIZE){thrownewFileTooBigException(file);}byte[] buffer =newbyte[(int) file.length()];InputStream ios =null;try{
ios =newFileInputStream(file);if(ios.read(buffer)==-1){thrownewIOException("EOF reached while trying to read the whole file");}}finally{try{if(ios !=null)
ios.close();}catch(IOException e){}}return buffer;}
Cela n'a pas de copie inutile.
FileTooBigExceptionest une exception d'application personnalisée. La MAX_FILE_SIZEconstante est un paramètre d'application.
Pour les gros fichiers, vous devriez probablement penser à un algorithme de traitement de flux ou utiliser le mappage de mémoire (voir java.nio).
L'instruction "ios.read (buffer)" dans le deuxième exemple ne lira que dans les 4096 premiers octets du fichier (en supposant le même tampon 4k que celui utilisé dans le premier exemple). Pour que le deuxième exemple fonctionne, je pense que la lecture doit être à l'intérieur d'une boucle while qui vérifie le résultat pour -1 (fin de fichier atteinte).
Stijn de Witt
Désolé, rejetez ma remarque ci-dessus, vous avez manqué le tampon de définition de la déclaration pour la longueur du fichier. Pourtant, j'aime davantage le premier exemple. La lecture d'un fichier entier dans un tampon en une seule fois n'est pas évolutive. Vous risquez de manquer de mémoire lorsque le fichier est volumineux.
Stijn de Witt
La manière "la plus simple" consisterait à essayer avec des ressources.
import org.apache.commons.io.FileUtils;publicclassProgram{publicstaticvoid main(String[] args)throwsIOException{File file =newFile(args[0]);// assume args[0] is the path to filebyte[] data =FileUtils.readFileToByteArray(file);...}}
Vous pouvez également utiliser l'API NIO pour le faire. Je pourrais faire cela avec ce code tant que la taille totale du fichier (en octets) tiendrait dans un int.
File f =newFile("c:\\wscp.script");FileInputStream fin =null;FileChannel ch =null;try{
fin =newFileInputStream(f);
ch = fin.getChannel();int size =(int) ch.size();MappedByteBuffer buf = ch.map(MapMode.READ_ONLY,0, size);byte[] bytes =newbyte[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();}}
Je pense que c'est très rapide depuis son utilisation de MappedByteBuffer.
il n'est absolument pas nécessaire d'utiliser le mappage de mémoire si vous ne lisez le fichier qu'une seule fois, et il finira par utiliser deux fois plus de mémoire que l'utilisation d'un FileInputStream normal.
james
1
Malheureusement, MappedByteBuffer n'est pas automatiquement publié.
Tom Hawtin - tackline
2
génial, le nouvel exemple inclut printStackTrace, la gestion classique des exceptions cassées.
james
Je suis d'accord .. C'est le truc par défaut qu'éclipse met. Je pense que je devrais repousser l'exception!
Amit
J'ai comparé nio afin de créer un octet [] à partir d'un fichier. Outre l'utilisation d'un tampon direct, il prend en effet deux fois plus de mémoire. Bien qu'il soit plus rapide pour les très gros fichiers (environ deux fois plus rapide qu'un IO tamponné pour 200M), il semble perdre par un facteur de 5 pour les fichiers autour de 5M.
Chaffers
22
Si vous n'avez pas Java 8, et convenez avec moi qu'inclure une bibliothèque massive pour éviter d'écrire quelques lignes de code est une mauvaise idée:
publicstaticbyte[] readBytes(InputStream inputStream)throwsIOException{byte[] b =newbyte[1024];ByteArrayOutputStream os =newByteArrayOutputStream();int c;while((c = inputStream.read(b))!=-1){
os.write(b,0, c);}return os.toByteArray();}
L'appelant est responsable de la fermeture du flux.
// Returns the contents of the file in a byte array.publicstaticbyte[] getBytesFromFile(File file)throwsIOException{// Get the size of the filelong 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 largethrownewIOException("File is too large!");}// Create the byte array to hold the databyte[] bytes =newbyte[(int)length];// Read in the bytesint offset =0;int numRead =0;InputStream is =newFileInputStream(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 inif(offset < bytes.length){thrownewIOException("Could not completely read file "+file.getName());}return bytes;}
Mettez également numRead dans la boucle. Déclarez les variables dans la plus petite étendue valide possible. Le placer en dehors de la boucle while n'est nécessaire que pour activer ce test "while" compliqué; il serait préférable de faire le test d'EOF à l'intérieur de la boucle (et de lancer une EOFException si cela se produit).
erickson
throw new IOException("File is too large!");que devons-nous faire lorsque le fichier est trop volumineux? Y a-t-il également un exemple à ce sujet?
Fer
21
Un moyen simple de le faire:
File fff =newFile("/path/to/file");FileInputStream fileInputStream =newFileInputStream(fff);// int byteLength = fff.length(); // In android the result of file.length() is longlong byteLength = fff.length();// byte count of the file-contentbyte[] filecontent =newbyte[(int) byteLength];
fileInputStream.read(filecontent,0,(int) byteLength);
Pouvez-vous expliquer ici? Pourquoi avez-vous une dispute?
Muhammad Sadiq
3
Rien de spécial, mais vous dites le plus simple et je vois des solutions plus simples -> à mon avis, ce n'est pas le plus simple. C'était peut-être il y a quelques années, mais le monde change. Je ne voudrais pas étiqueter mes propres solutions avec une telle déclaration. ;) Si seulement vous écriviez "À mon avis, le plus simple est .." ou "le plus simple que j'ai trouvé .." Je ne veux pas vous déranger, je vous ai juste fait plaisir de communiquer cela.
BlondCode
@MuhammadSadiq: n'importez rien .*, c'est considéré comme une mauvaise pratique.
Il couvre le cas du coin où les fichiers signalent une longueur de 0 mais ont toujours du contenu
Il est hautement optimisé, vous obtenez une OutOfMemoryException si vous essayez de lire un gros fichier avant même d'essayer de charger le fichier. (Grâce à une utilisation intelligente de file.length ())
En utilisant la même approche que la réponse du wiki de la communauté, mais plus propre et compilant hors de la boîte (approche préférée si vous ne voulez pas importer des bibliothèques Apache Commons, par exemple sur Android):
publicstaticbyte[] getFileBytes(File file)throwsIOException{ByteArrayOutputStream ous =null;InputStream ios =null;try{byte[] buffer =newbyte[4096];
ous =newByteArrayOutputStream();
ios =newFileInputStream(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();}
il y a déjà une réponse avec cette suggestion de Tom en 2009
Knut Herrmann
7
ReadFully Lit les octets b.length de ce fichier dans le tableau d'octets, en commençant par le pointeur de fichier actuel. Cette méthode lit à plusieurs reprises à partir du fichier jusqu'à ce que le nombre d'octets demandé soit lu. Cette méthode se bloque jusqu'à ce que le nombre d'octets demandé soit lu, que la fin du flux soit détectée ou qu'une exception soit levée.
RandomAccessFile f =newRandomAccessFile(fileName,"r");byte[] b =newbyte[(int)f.length()];
f.readFully(b);
Si vous souhaitez lire des octets dans un tampon d'octets pré-alloué, cette réponse peut vous aider.
Votre première supposition serait probablement d'utiliser InputStream read(byte[]). Cependant, cette méthode a un défaut qui la rend excessivement difficile à utiliser: il n'y a aucune garantie que la baie sera réellement complètement remplie, même si aucun EOF n'est rencontré.
Jetez plutôt un œil à DataInputStream readFully(byte[]). Ceci est un wrapper pour les flux d'entrée et n'a pas le problème mentionné ci-dessus. En outre, cette méthode se déclenche lorsque EOF est rencontré. Beaucoup mieux.
Non seulement la manière suivante convertit un fichier java.io.File en octet [], mais je l'ai également trouvé comme le moyen le plus rapide de lire un fichier, lors du test de nombreuses méthodes de lecture de fichiers Java les unes contre les autres:
Permettez-moi d'ajouter une autre solution sans utiliser de bibliothèques tierces. Il réutilise un modèle de gestion des exceptions qui a été proposé par Scott ( lien ). Et j'ai déplacé la partie laide dans un message séparé (je me cacherais dans une classe FileUtils;))
publicvoid someMethod(){finalbyte[] buffer = read(newFile("test.txt"));}privatebyte[] read(finalFile file){if(file.isDirectory())thrownewRuntimeException("Unsupported operation, file "+ file.getAbsolutePath()+" is a directory");if(file.length()>Integer.MAX_VALUE)thrownewRuntimeException("Unsupported operation, file "+ file.getAbsolutePath()+" is too big");Throwable pending =null;FileInputStream in =null;finalbyte buffer[]=newbyte[(int) file.length()];try{
in =newFileInputStream(file);
in.read(buffer);}catch(Exception e){
pending =newRuntimeException("Exception occured on reading file "+ file.getAbsolutePath(), e);}finally{if(in !=null){try{
in.close();}catch(Exception e){if(pending ==null){
pending =newRuntimeException("Exception occured on closing file"+ file.getAbsolutePath(), e);}}}if(pending !=null){thrownewRuntimeException(pending);}}return buffer;}
n'utilisez pas de blocs d'accrochage creux. cela rend le débogage difficile.
Sapphire_Brick
1
//The file that you wanna convert into byte[]File file=newFile("/storage/0CE2-EA3D/DCIM/Camera/VID_20190822_205931.mp4");FileInputStream fileInputStream=newFileInputStream(file);byte[] data=newbyte[(int) file.length()];BufferedInputStream bufferedInputStream=newBufferedInputStream(fileInputStream);
bufferedInputStream.read(data,0,data.length);//Now the bytes of the file are contain in the "byte[] data"
Bien que ce code puisse fournir une solution à la question, il est préférable d'ajouter du contexte pour expliquer pourquoi / comment cela fonctionne. Cela peut aider les futurs utilisateurs à apprendre et à appliquer ces connaissances à leur propre code. Vous êtes également susceptible d'avoir des commentaires positifs des utilisateurs sous la forme de votes positifs, lorsque le code est expliqué.
borchvm
Eh bien, c'est la partie importante que je garderai à l'esprit dans les prochains articles. Merci pour vos informations utiles.
Réponses:
Cela dépend de ce que signifie le mieux pour vous. Côté productivité, ne réinventez pas la roue et utilisez Apache Commons. C'est ici
IOUtils.toByteArray(InputStream input)
.la source
File
àbyte[]
? J'utilise Java6, je ne peux donc pas utiliser les méthodes NIO :(Depuis JDK 7, vous pouvez utiliser
Files.readAllBytes(Path)
.Exemple:
la source
Depuis JDK 7 - une doublure:
Aucune dépendance externe requise.
la source
import java.nio.file.Files;
etimport java.nio.file.Paths;
si vous ne l'avez pas déjà fait.Documentation pour Java 8: http://docs.oracle.com/javase/8/docs/api/java/io/RandomAccessFile.html
la source
Fondamentalement, vous devez le lire en mémoire. Ouvrez le fichier, allouez le tableau et lisez le contenu du fichier dans le tableau.
La manière la plus simple est similaire à ceci:
Cela a une copie inutile du contenu du fichier (en fait, les données sont copiées trois fois: du fichier à
buffer
, debuffer
àByteArrayOutputStream
, deByteArrayOutputStream
au tableau résultant réel).Vous devez également vous assurer de ne lire en mémoire que les fichiers jusqu'à une certaine taille (cela dépend généralement de l'application) :-).
Vous devez également traiter l'
IOException
extérieur de la fonction.Une autre façon est la suivante:
Cela n'a pas de copie inutile.
FileTooBigException
est une exception d'application personnalisée. LaMAX_FILE_SIZE
constante est un paramètre d'application.Pour les gros fichiers, vous devriez probablement penser à un algorithme de traitement de flux ou utiliser le mappage de mémoire (voir
java.nio
).la source
Comme quelqu'un l'a dit, Apache Commons File Utils pourrait avoir ce que vous cherchez
Exemple d'utilisation (
Program.java
):la source
Vous pouvez également utiliser l'API NIO pour le faire. Je pourrais faire cela avec ce code tant que la taille totale du fichier (en octets) tiendrait dans un int.
Je pense que c'est très rapide depuis son utilisation de MappedByteBuffer.
la source
Si vous n'avez pas Java 8, et convenez avec moi qu'inclure une bibliothèque massive pour éviter d'écrire quelques lignes de code est une mauvaise idée:
L'appelant est responsable de la fermeture du flux.
la source
la source
throw new IOException("File is too large!");
que devons-nous faire lorsque le fichier est trop volumineux? Y a-t-il également un exemple à ce sujet?Un moyen simple de le faire:
la source
Manière la plus simple de lire des octets à partir d'un fichier
la source
.*
, c'est considéré comme une mauvaise pratique.Guava a Files.toByteArray () à vous offrir. Il présente plusieurs avantages:
la source
la source
En utilisant la même approche que la réponse du wiki de la communauté, mais plus propre et compilant hors de la boîte (approche préférée si vous ne voulez pas importer des bibliothèques Apache Commons, par exemple sur Android):
la source
Je crois que c'est la manière la plus simple:
la source
ReadFully Lit les octets b.length de ce fichier dans le tableau d'octets, en commençant par le pointeur de fichier actuel. Cette méthode lit à plusieurs reprises à partir du fichier jusqu'à ce que le nombre d'octets demandé soit lu. Cette méthode se bloque jusqu'à ce que le nombre d'octets demandé soit lu, que la fin du flux soit détectée ou qu'une exception soit levée.
la source
Si vous souhaitez lire des octets dans un tampon d'octets pré-alloué, cette réponse peut vous aider.
Votre première supposition serait probablement d'utiliser
InputStream read(byte[])
. Cependant, cette méthode a un défaut qui la rend excessivement difficile à utiliser: il n'y a aucune garantie que la baie sera réellement complètement remplie, même si aucun EOF n'est rencontré.Jetez plutôt un œil à
DataInputStream readFully(byte[])
. Ceci est un wrapper pour les flux d'entrée et n'a pas le problème mentionné ci-dessus. En outre, cette méthode se déclenche lorsque EOF est rencontré. Beaucoup mieux.la source
Non seulement la manière suivante convertit un fichier java.io.File en octet [], mais je l'ai également trouvé comme le moyen le plus rapide de lire un fichier, lors du test de nombreuses méthodes de lecture de fichiers Java les unes contre les autres:
java.nio.file.Files.readAllBytes ()
la source
Permettez-moi d'ajouter une autre solution sans utiliser de bibliothèques tierces. Il réutilise un modèle de gestion des exceptions qui a été proposé par Scott ( lien ). Et j'ai déplacé la partie laide dans un message séparé (je me cacherais dans une classe FileUtils;))
la source
la source
Une autre façon de lire les octets du fichier
la source
la source
Essaye ça :
la source
Dans JDK8
la source