【问题标题】:File to byte[] in JavaJava中的文件到字节[]
【发布时间】:2010-10-25 22:20:06
【问题描述】:

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

【问题讨论】:

  • 我能想到的一个用途是从文件中读取序列化对象。
  • 另一种是使用header查找文件类型。
  • 试试这个 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; }

标签: java file-io


【解决方案1】:
// 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!");文件过大怎么办?有没有例子?
【解决方案2】:

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

【讨论】:

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

您也可以使用 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 倍。
【解决方案4】:

正如有人所说,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);
        ...
    }
}

【讨论】:

    【解决方案5】:

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

    最简单的方法是这样的:

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

    【讨论】:

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

    让我在不使用第三方库的情况下添加另一个解决方案。它重用了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;
    }

    【讨论】:

      【解决方案7】:

      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() 方法,该方法将为您提供路径对象。
      • 您可以从文件中获取路径。试试: File file = new File("/path");路径路径 = Paths.get(file.getAbsolutePath()); byte[] data = Files.readAllBytes(path);
      • java.nio 中文件关闭是如何处理的——换句话说,上面的代码是否应该关闭一些东西?
      • @akauppi 查看答案中的链接:“该方法确保文件已关闭...”
      • 如果面向 SDK 版本 26 及更高版本,现在可以在 Android 上运行。
      【解决方案8】:
      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/ 中读取“文件”可能会导致短读(即你需要一个循环来读取它)
      【解决方案9】:

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

      【讨论】:

        【解决方案10】:

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

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

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

        【讨论】:

          【解决方案11】:
          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);
                  }
              }
          }
          

          【讨论】:

            【解决方案12】:

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

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

            【讨论】:

              【解决方案13】:

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

              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:不要导入任何东西.*,这被认为是不好的做法。
              【解决方案14】:

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

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

              【讨论】:

              • Tom 在 2009 年的这个建议已经有了答案
              【解决方案15】:

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

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

              【讨论】:

              • 不要使用空心挡块。它使调试变得困难。
              【解决方案16】:

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

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

              【讨论】:

                【解决方案17】:

                从 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 也很有用
                【解决方案18】:

                如果您没有 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();
                }
                

                调用者负责关闭流。

                【讨论】:

                • 谢谢。这就是我需要的
                【解决方案19】:
                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级别?
                【解决方案20】:

                简单的方法:

                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 更简单的方法是的 - 但一个衬垫并不适合所有情况。比如安卓。
                【解决方案21】:

                以下方法不仅可以将 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);
                    }
                  }
                }
                

                【讨论】:

                  【解决方案22】:

                  JDK8

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

                  【讨论】:

                  • 阅读我的法语朋友的问题,它询问关于转换为“byte[]”的问题,而您的答案没有提供。
                  • 这没有提供一个更远程的选项来回答转换为 byte[] !
                  【解决方案23】:

                  试试这个:

                  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:我的错
                  【解决方案24】:
                  //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"
                  

                  【讨论】:

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

                  可以这么简单(Kotlin 版本)

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

                  编辑

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

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

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

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

                  感谢@user2768856 指出这一点。

                  【讨论】:

                  • 使用 File(path).inputStream().use { it.readBytes() } 它会关闭你的流。
                  【解决方案26】:

                  这是最简单的方法之一

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

                  【讨论】:

                    【解决方案27】:

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

                    【讨论】:

                      猜你喜欢
                      • 1970-01-01
                      • 2021-12-17
                      • 1970-01-01
                      • 1970-01-01
                      • 2023-03-05
                      • 2017-02-24
                      • 1970-01-01
                      • 1970-01-01
                      相关资源
                      最近更新 更多