在Java中将文件读入字节[]数组的优雅方法[重复]
Posted
技术标签:
【中文标题】在Java中将文件读入字节[]数组的优雅方法[重复]【英文标题】:Elegant way to read file into byte[] array in Java [duplicate] 【发布时间】:2011-08-28 19:37:03 【问题描述】:可能重复:File to byte[] in Java
我想从文件中读取数据并将其解组到 Parcel。 在文档中并不清楚 FileInputStream 有读取其所有内容的方法。为了实现这一点,我做了以下工作:
FileInputStream filein = context.openFileInput(FILENAME);
int read = 0;
int offset = 0;
int chunk_size = 1024;
int total_size = 0;
ArrayList<byte[]> chunks = new ArrayList<byte[]>();
chunks.add(new byte[chunk_size]);
//first I read data from file chunk by chunk
while ( (read = filein.read(chunks.get(chunks.size()-1), offset, buffer_size)) != -1)
total_size+=read;
if (read == buffer_size)
chunks.add(new byte[buffer_size]);
int index = 0;
// then I create big buffer
byte[] rawdata = new byte[total_size];
// then I copy data from every chunk in this buffer
for (byte [] chunk: chunks)
for (byte bt : chunk)
index += 0;
rawdata[index] = bt;
if (index >= total_size) break;
if (index>= total_size) break;
// and clear chunks array
chunks.clear();
// finally I can unmarshall this data to Parcel
Parcel parcel = Parcel.obtain();
parcel.unmarshall(rawdata,0,rawdata.length);
我认为这段代码看起来很难看,我的问题是: 如何漂亮地将文件中的数据读入 byte[]? :)
【问题讨论】:
【参考方案1】:很久以前:
调用其中任何一个
byte[] org.apache.commons.io.FileUtils.readFileToByteArray(File file)
byte[] org.apache.commons.io.IOUtils.toByteArray(InputStream input)
来自
http://commons.apache.org/io/
如果库对于您的 android 应用来说太大,您可以使用 commons-io 库中的相关类
今天(Java 7+ 或 Android API 级别 26+)
幸运的是,我们现在在 nio 包中有几个方便的方法。例如:
byte[] java.nio.file.Files.readAllBytes(Path path)
Javadoc here
【讨论】:
+1 -IOUtils.toByteArray(InputStream)
也可以,尽管FileUtils
方法应该更有效。
但是如果文件的内容是你想要的字节数组的值呢?
@AdamJohns:新问题的完美材料,在 Stack Overflow 上
如何在 Android 中做同样的事情? byte[] java.nio.file.Files.readAllBytes(Path path) 在Andorid中不存在..?有什么想法吗?
@NikhilGeorge:使用 Apache Commons IO,或类似答案中提到的东西......这里还有其他答案展示了如何使用旧的java.io.InputStream
API 来做到这一点......
【参考方案2】:
这也可以:
import java.io.*;
public class IOUtil
public static byte[] readFile(String file) throws IOException
return readFile(new File(file));
public static byte[] readFile(File file) throws IOException
// Open file
RandomAccessFile f = new RandomAccessFile(file, "r");
try
// Get and check length
long longlength = f.length();
int length = (int) longlength;
if (length != longlength)
throw new IOException("File size >= 2 GB");
// Read file and return data
byte[] data = new byte[length];
f.readFully(data);
return data;
finally
f.close();
【讨论】:
这里的问题可能是一个可能的(不太可能的)竞争条件(IMO)。如果您检查 f.length(),那不一定是您打开的文件,以防其他应用程序同时替换它。 @sstn 但您对所有其他解决方案都有同样的问题。 @ChristoperSanwaldt 我不了解这些库,但是在到达 EOF 之前手动读取 ByteArrayOutputStream 是安全的(如果文件将被锁定以进行写入,不知道 java 是否会…… . 默认情况下就是这样)。 这被标记为 android,所以我无法想象这将是一个 android 应用程序中的问题 +1 表示不添加库。【参考方案3】:如果您使用Google Guava(如果您不使用,则应该使用),您可以致电:ByteStreams.toByteArray(InputStream)
或 Files.toByteArray(File)
【讨论】:
但是 guava jar 是 1.6mb,对于 Android 应用来说是不是太大了? @PauloCesar:也许吧。我不熟悉Android开发,所以我无法评论。 对不起,我以为这个问题与Android有关,但现在我意识到它只是纯Java 不,它被标记为 Android。但是谷歌端点服务的Android客户端需要Guava,所以我猜他们认为它适合Android。无论如何,未使用的代码将在发布版本中删除。 @Tom 几乎是对的。默认情况下它不会被删除,但如果您设置 Proguard,它将删除所有未使用的代码。在写这篇文章的时候,Guava 默认会增加大约 2.2MB 到一个 APK。但是使用 Proguard 只增加了大约 250KB。【参考方案4】:这对我有用:
File file = ...;
byte[] data = new byte[(int) file.length()];
try
new FileInputStream(file).read(data);
catch (Exception e)
e.printStackTrace();
【讨论】:
此方法不保证读取整个文件。 你是对的,为了确保read()的返回值必须与file.length()匹配,然后如果文件不完整则继续读取...【参考方案5】:使用ByteArrayOutputStream
。流程如下:
InputStream
以读取数据
创建一个ByteArrayOutputStream
。
将所有InputStream
复制到OutputStream
使用toByteArray()
方法从ByteArrayOutputStream
获取您的byte[]
【讨论】:
我有一个 OutputStream 那么如何从中获取 ByteArrayOutputStream(因为我想检索 byte[])?【参考方案6】:看看下面的apache commons函数:
org.apache.commons.io.FileUtils.readFileToByteArray(File)
【讨论】:
以上是关于在Java中将文件读入字节[]数组的优雅方法[重复]的主要内容,如果未能解决你的问题,请参考以下文章