在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中将文件读入字节[]数组的优雅方法[重复]的主要内容,如果未能解决你的问题,请参考以下文章

如何在Scala中将文件作为字节数组读取

在Java中将字节[]转换为“文件”[重复]

在java中将字符串数组元素转换为字节数组[重复]

如何在Go中将字节数组转换为字符串[重复]

如何在c ++中将int数组转换为字节数组[重复]

在python中将字节转换为BufferedReader [重复]