文件到byte[]在Java

如何将java.io.File转换为byte[]

1348958 次浏览
// Returns the contents of the file in a byte array.public static byte[] getBytesFromFile(File file) throws IOException {// 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 largethrow new IOException("File is too large!");}
// Create the byte array to hold the databyte[] bytes = new byte[(int)length];
// Read in the bytesint 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 inif (offset < bytes.length) {throw new IOException("Could not completely read file "+file.getName());}return bytes;}

这取决于什么对您最有利。生产力明智,不要重新发明轮子并使用Apache Commons。这是这里的FileUtils.readFileToByteArray(File input)

您也可以使用NIO api来执行此操作。只要总文件大小(以字节为单位)适合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 blocke.printStackTrace();} finally {try {if (fin != null) {fin.close();}if (ch != null) {ch.close();}} catch (IOException e) {e.printStackTrace();}}

我认为这是非常快的,因为它使用了MappdByteBuffer。

正如有人所说,Apache Commons文件Utils可能有你正在寻找的东西

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

示例使用(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 filebyte[] data = FileUtils.readFileToByteArray(file);...}}

基本上,您必须在内存中读取它。打开文件,分配数组,然后将文件中的内容读取到数组中。

最简单的方法类似于这样:

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();}

这有一些不必要的文件内容复制(实际上数据被复制了三次:从文件到buffer,从bufferByteArrayOutputStream,从ByteArrayOutputStream到实际结果数组)。

您还需要确保仅在内存中读取一定大小的文件(这通常取决于应用程序):-)。

您还需要处理函数外部的IOException

另一种方法是这样的:

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;}

这没有不必要的复制。

FileTooBigException是一个自定义应用程序异常。MAX_FILE_SIZE常量是应用程序参数。

对于大文件,您可能应该考虑流处理算法或使用内存映射(请参阅java.nio)。

让我添加另一个不使用第三方库的解决方案。它重用了斯科特链接)提出的异常处理模式。我将丑陋的部分移动到单独的消息中(我会隐藏在一些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;}

JDK7开始,您可以使用Files.readAllBytes(Path)

示例:

import java.io.File;import java.nio.file.Files;
File file;// ...(file is initialised)...byte[] fileContent = Files.readAllBytes(file.toPath());
import java.io.RandomAccessFile;RandomAccessFile f = new RandomAccessFile(fileName, "r");byte[] b = new byte[(int)f.length()];f.readFully(b);

Java的文档:http://docs.oracle.com/javase/8/docs/api/java/io/RandomAccessFile.html

使用与社区wiki答案相同的方法,但更清晰和开箱即用(如果您不想导入Apache Commons库,例如在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();}

如果您想将字节读取到预分配的字节缓冲区中,此答案可能会有所帮助。

你的第一个猜测可能是使用InputStream read(byte[])。然而,这种方法有一个缺陷,使得它难以使用:不能保证数组实际上会被完全填充,即使没有遇到EOF。

相反,看看DataInputStream readFully(byte[])。这是输入流的包装器,没有上述问题。此外,当遇到EOF时,此方法会抛出。更好。

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);}}}

番石榴为您提供Files.toByteArray()。它有几个优点:

  1. 它涵盖了文件报告长度为0但仍有内容的角落情况
  2. 它是高度优化的,如果试图在加载文件之前读取一个大文件,你会得到一个OutOfMemoryException。(通过巧妙地使用file.length())
  3. 你不必重新发明轮子。

从文件中读取字节的最简单方法

import java.io.*;
class ReadBytesFromFile {public static void main(String args[]) throws Exception {// getBytes from anyWhere// I'm getting byte array from FileFile file = null;FileInputStream fileStream = new FileInputStream(file = new File("ByteArrayInputStreamClass.java"));
// Instantiate arraybyte[] arr = new byte[(int) file.length()];
// read All bytes of File streamfileStream.read(arr, 0, arr.length);
for (int X : arr) {System.out.print((char) X);}}}

我相信这是最简单的方法:

org.apache.commons.io.FileUtils.readFileToByteArray(file);

从文件中读取字节的另一种方法

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();}}

ReadFully从此文件中读取b.length字节到字节数组中,从当前文件指针开始。此方法从文件中重复读取,直到读取请求的字节数。此方法阻塞,直到读取请求的字节数、检测到流的结束或抛出异常。

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

由于JDK 7-一个班轮:

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

不需要外部依赖。

如果你没有Java8,并且同意我的观点,包括一个庞大的库来避免编写几行代码是一个坏主意:

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();}

调用者负责关闭流。

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);

简单的方法来做到这一点:

File fff = new File("/path/to/file");FileInputStream fileInputStream = new FileInputStream(fff);
// int byteLength = fff.length();
// In android the result of file.length() is longlong byteLength = fff.length(); // byte count of the file-content
byte[] filecontent = new byte[(int) byteLength];fileInputStream.read(filecontent, 0, (int) byteLength);

以下方式不仅将java.io.文件转换为字节[],我还发现它是读取文件的最快方式,当测试许多不同的Java文件读取方法时:

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);}}}

JDK8

Stream<String> lines = Files.lines(path);String data = lines.collect(Collectors.joining("\n"));lines.close();

试试这个:

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);}
//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"

可以做到这么简单(静态编程语言版)

val byteArray = File(path).inputStream().readBytes()

编辑

我读过readBytes方法的文档。它说:

将此流完全读入字节数组。注意:关闭此流是调用者的责任。

因此,为了能够关闭流,同时保持一切干净,请使用以下代码:

val byteArray = File(path).inputStream().use { it.readBytes() }

感谢@user2768856指出这一点。

这是最简单的方法之一

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

如果您的目标版本小于26 API,请尝试此操作

 private static byte[] readFileToBytes(String filePath) {
File file = new File(filePath);byte[] bytes = new byte[(int) file.length()];
// funny, if can use Java 7, please uses Files.readAllBytes(path)try(FileInputStream fis = new FileInputStream(file)){fis.read(bytes);return bytes;} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}return null;
}