ChatGPT解决这个技术问题 Extra ChatGPT

Java中的文件到字节[]

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

我能想到的一种用途是从文件中读取序列化对象。
另一种是使用标头查找文件类型。
试试这个 byte[] bytes = null; BufferedInputStream fileInputStream = null;尝试{文件文件 = 新文件(文件路径); fileInputStream = new BufferedInputStream(new FileInputStream(file)); //fileInputStream = Thread.currentThread().getContextClassLoader().getResourceAsStream(this.filePath);字节 = 新字节[(int) file.length()]; fileInputStream.read(字节); } catch(FileNotFoundException ex){ 抛出 ex; }

1
12 revs, 11 users 24%

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

例子:

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

File file;
// ...(file is initialised)...
byte[] fileContent = Files.readAllBytes(file.toPath());

@aldo.roman.nurena JDK7 引入了一个 File.toPath() 方法,它会给你一个 Path 对象。
您可以从文件中获取路径。试试: File file = new File("/path");路径路径 = Paths.get(file.getAbsolutePath());字节[] 数据 = Files.readAllBytes(path);
java.nio 中的文件关闭是如何处理的——换句话说,上面的代码是否应该关闭一些东西?
@akauppi 请参阅答案中的链接:“该方法确保文件已关闭......”
如果针对 SDK 版本 26 及更高版本,这现在适用于 Android。
L
LAX1DUDE

这取决于对您来说最好的方式。提高生产力,不要重新发明轮子并使用 Apache Commons。这是FileUtils.readFileToByteArray(File input)


@ymajoros:太真实了!我宁愿有一些额外的代码行而不是另一个依赖项。依赖有隐藏的成本。您需要与该库保持同步,在您的构建脚本等中包含依赖项,将其传达给使用您的代码等的人等。如果您已经在使用具有代码的库而不是使用它,否则我会说自己写。
这回答了如何读取文件的问题,但没有回答如何将 java.IO.File 类型的对象转换为 byte[] 的问题。
这如何用于读取 Filebyte[]?我正在使用 Java6,所以我不能使用 NIO 方法:(
@ymajoros 您愿意与我们分享任何“标准 3 行解决方案”吗,这样我们就不必依赖重新发明轮子了?
@matteo:有吗?查看其他答案,例如 Files.readAllBytes()。很简单,没有依赖。
C
Community

从 JDK 7 开始 - 一个班轮:

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

不需要外部依赖。


现在这是比接受的答案更好的选择,后者需要 Apache Commons。
谢谢 :) 我也需要这个: String text = new String(Files.readAllBytes(new File("/path/to/file").toPath()));最初来自 stackoverflow.com/a/26888713/1257959
在 Android 中,它要求最低 API 级别为 26。
如果您尚未添加 import java.nio.file.Files;import java.nio.file.Paths;,则需要添加。
这对 java8 也很有用
T
Thomas Mueller
import java.io.RandomAccessFile;
RandomAccessFile f = new RandomAccessFile(fileName, "r");
byte[] b = new byte[(int)f.length()];
f.readFully(b);

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


您必须检查 f.read() 的返回值。有时可能会发生这种情况,您不会读取整个文件。
只有在您阅读文件时文件正在更改时才会发生这种情况。在所有其他情况下,都会抛出 IOException。为了解决这个问题,我建议以读写模式打开文件: RandomAccessFile(fileName, "rw")
我可以想象其他来源仅读取文件的一部分(文件在网络共享上......) readFully() 具有您正在搜索的合同。
请记住,RandomAccessFile 不是线程安全的。因此,在某些情况下可能需要同步。
@DmitryMitskevich 在文件系统上还有其他可能不符合格式的情况。例如,在 Linux 上的 /proc/ 中读取“文件”可能会导致短读(即您需要一个循环来读取所有内容)
7
7 revs, 5 users 71%

基本上你必须在内存中阅读它。打开文件,分配数组,将文件中的内容读入数组。

最简单的方法与此类似:

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

这对文件内容进行了一些不必要的复制(实际上数据被复制了 3 次:从文件到 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)。


ios需要在try之外声明
第二个示例中的语句“ios.read(buffer)”将仅读取文件的前 4096 个字节(假设与第一个示例中使用的 4k 缓冲区相同)。为了使第二个示例起作用,我认为读取必须在检查结果是否为 -1 的 while 循环内(到达文件末尾)。
对不起,忽略我上面的评论,错过了将缓冲区设置为文件长度的语句。不过,我更喜欢第一个例子。一次性将整个文件读入缓冲区是不可扩展的。当文件很大时,您将面临内存不足的风险。
“最简单”的方法是使用 try-with-resources。
很酷,但有点冗长。
P
Palec

正如有人所说,Apache Commons File 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 file
        byte[] data = FileUtils.readFileToByteArray(file);
        ...
    }
}

O
Oleksandr Pyrohov

如果您没有 Java 8,并且同意我的观点,那么包含一个庞大的库以避免编写几行代码是一个坏主意:

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

调用者负责关闭流。


谢谢你。这就是我需要的
O
Oleksandr Pyrohov

您也可以使用 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 block
    e.printStackTrace();
} finally {
    try {
        if (fin != null) {
            fin.close();
        }
        if (ch != null) {
            ch.close();
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
}

我认为它非常快,因为它使用了 MappedByteBuffer。


如果您只打算读取文件一次,则绝对不需要使用内存映射,并且最终使用的内存将是使用普通 FileInputStream 的两倍。
不幸的是 MappedByteBuffer 不会自动释放。
太棒了,新示例包括 printStackTrace,经典的损坏异常处理。
我同意..它是 eclipse 放入的默认内容。我想我应该重新抛出异常!
我一直在对 nio 进行基准测试,以便从文件中创建一个 byte[]。除了使用直接缓冲区之外,它确实需要两倍的内存。虽然它对于非常大的文件更快(大约是 200M 的缓冲 IO 的两倍),但对于 5M 左右的文件,它似乎损失了 5 倍。
m
maaartinus
// 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;
    }

此外,将 numRead 放入循环中。在最小的有效范围内声明变量。将它放在 while 循环之外只是为了启用那个复杂的“while”测试;最好在循环内对 EOF 进行测试(如果发生则抛出 EOFException)。
throw new IOException("File is too large!"); 文件过大怎么办?还有关于它的例子吗?
O
Oleksandr Pyrohov

简单的方法:

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

还有更简单的方法,比如已经提到的单行。
@Sapphire_Brick 更简单的方法是的 - 但一个衬垫并不适合所有情况。比如安卓。
O
Oleksandr Pyrohov

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

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

我争论成为“最简单的方式”:)
你能在这里解释一下吗?你为什么吵架?
没什么特别的,但你说最简单,我看到更简单的解决方案->在我看来这不是最简单的。也许是几年前的事了,但世界正在发生变化。我不会用这样的声明来标记我自己的解决方案。 ;) 如果您只写“在我看来最简单的是..”或“我发现的最简单的..”不想打扰您,只是想很好地传达这一点。
@MuhammadSadiq:不要导入任何东西.*,这被认为是不好的做法。
j
jontejj

Guava 有 Files.toByteArray() 可以提供给您。它有几个优点:

它涵盖了文件报告长度为 0 但仍有内容的极端情况。它经过高度优化,如果在尝试加载文件之前尝试读取大文件,则会收到 OutOfMemoryException。 (通过巧妙地使用 file.length())您不必重新发明轮子。


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

这是什么JDK级别?
m
manmal

使用与社区 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();
}

S
Sachin Kumar

这是最简单的方法之一

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

l
likeitlikeit

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

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

汤姆在 2009 年的这个建议已经有了答案
T
Tarun M

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

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

L
Laurens Holst

如果您想将字节读入预先分配的字节缓冲区,这个答案可能会有所帮助。

您的第一个猜测可能是使用 InputStream read(byte[])。但是,这种方法有一个缺陷,使用起来非常困难:即使没有遇到 EOF,也不能保证数组实际上会被完全填满。

相反,请查看 DataInputStream readFully(byte[])。这是输入流的包装器,不存在上述问题。此外,遇到 EOF 时会抛出此方法。好多了。


g
gomisha

以下方法不仅可以将 java.io.File 转换为 byte[],而且在测试许多不同的 Java file reading methods 时,我还发现它是读取文件的最快方法:

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

C
Community

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

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

U
Usama Mehmood
//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"

虽然此代码可能会为问题提供解决方案,但最好添加有关其工作原理/方式的上下文。这可以帮助未来的用户学习并将这些知识应用到他们自己的代码中。在解释代码时,您也可能会以赞成票的形式从用户那里获得积极的反馈。
嗯,这是我在以后的帖子中要记住的重要部分。感谢您提供有用的见解。
M
Muhammad Aamir Ali

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

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

不要使用空心接块。它使调试变得困难。
S
Sapphire_Brick

尝试这个 :

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

这需要一个特定的 JRE 实现,如果在另一个 JRE 上运行,它将破坏应用程序。
小错误:是 IOException 而不是 IOexception,但谢谢:)
@MatanMarciano:我的错
T
Tamim Attafi

可以这么简单(Kotlin 版本)

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

编辑:

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

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

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

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

感谢@user2768856 指出这一点。


使用 File(path).inputStream().use { it.readBytes() } 它会关闭你的流。
M
Mohd Qasim

如果您的目标版本低于 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;

}

J
J-Alex

在JDK8中

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

阅读我讲法语的朋友的问题,它询问有关转换为“字节 []”的问题,而您的答案没有提供。
这没有提供一个更远程的选项来回答转换为 byte[] !