Java通过块将大文件读入字节数组块

h0l*_*sxx 3 java

所以我一直在尝试制作一个将文件输入字节数组的小程序,然后将该字节数组转换为十六进制,然后转换为二进制.然后它将播放二进制值(我没有想到当我到达这个阶段时该怎么做),然后将其保存为自定义文件.

我研究了很多互联网代码,我可以将文件转换为字节数组并转换为十六进制,但问题是我无法将大文件转换为字节数组(内存不足).

这是完全失败的代码

public void rundis(Path pp) {
    byte bb[] = null;

    try {
        bb = Files.readAllBytes(pp); //Files.toByteArray(pathhold);
        System.out.println("byte array made");
    } catch (Exception e) {
        e.printStackTrace();
    }
    if (bb.length != 0 || bb != null) {
        System.out.println("byte array filled");
        //send to method to turn into hex
    } else {
        System.out.println("byte array NOT filled");
    }

}
Run Code Online (Sandbox Code Playgroud)

我知道这个过程应该怎么做,但我不知道如何正确编码.

如果你有兴趣,这个过程:

  • 输入文件使用 File
  • 通过文件块将块读取为字节数组.防爆.每个字节数组记录保持600个字节
  • 将该块发送为十六进制值 - > Integer.tohexstring
  • 将该十六进制值块发送为二进制值 - > Integer.toBinarystring
  • 乱用二进制值
  • 逐行保存到自定义文件

问题 ::我不知道如何通过要处理的块将一个巨大的文件转换为字节数组块.任何和所有的帮助将不胜感激,谢谢你阅读:)

Lyn*_*242 11

要对输入进行分块,请使用FileInputStream:

    Path pp = FileSystems.getDefault().getPath("logs", "access.log");
    final int BUFFER_SIZE = 1024*1024; //this is actually bytes

    FileInputStream fis = new FileInputStream(pp.toFile());
    byte[] buffer = new byte[BUFFER_SIZE]; 
    int read = 0;
    while( ( read = fis.read( buffer ) ) > 0 ){
        // call your other methodes here...
    }

    fis.close();
Run Code Online (Sandbox Code Playgroud)


tka*_*usl 6

要流式传输文件,您需要远离Files.readAllBytes()。对于小文件,这是一个不错的实用程序,但是您注意到,对于大文件,它不是那么多。

用伪代码看起来像这样:

while there are more bytes available
    read some bytes
    process those bytes
    (write the result back to a file, if needed)
Run Code Online (Sandbox Code Playgroud)

在Java中,您可以使用逐字节逐块FileInputStream读取文件。假设我们要回写已处理的字节。首先我们打开文件:

FileInputStream is = new FileInputStream(new File("input.txt"));
FileOutputStream os = new FileOutputStream(new File("output.txt"));
Run Code Online (Sandbox Code Playgroud)

我们需要将FileOutputStream结果写回-我们不想只丢弃宝贵的处理数据,对吗?接下来,我们需要一个缓冲区,其中包含一个字节块:

byte[] buf = new byte[4096];
Run Code Online (Sandbox Code Playgroud)

多少字节取决于您,我有点像4096字节的块。然后我们需要实际读取一些字节

int read = is.read(buf);
Run Code Online (Sandbox Code Playgroud)

这将读取最多buf.length字节并将其存储在中buf。它将返回读取的总字节数。然后我们处理字节:

//Assuming the processing function looks like this:
//byte[] process(byte[] data, int bytes);
byte[] ret = process(buf, read);
Run Code Online (Sandbox Code Playgroud)

process()在上面的示例中是您的处理方法。它接受一个字节数组,它应处理的字节数并将结果作为字节数组返回。

最后,我们将结果写回到文件中:

os.write(ret);
Run Code Online (Sandbox Code Playgroud)

我们必须循环执行此操作,直到文件中没有字节为止,因此让我们为其编写一个循环:

int read = 0;
while((read = is.read(buf)) > 0) {
    byte[] ret = process(buf, read);
    os.write(ret);
}
Run Code Online (Sandbox Code Playgroud)

最后关闭流

is.close();
os.close();
Run Code Online (Sandbox Code Playgroud)

就是这样。我们以4096字节的块为单位处理文件,并将结果写回到文件中。由您决定如何处理结果,也可以通过TCP发送结果,或者在不需要时丢弃它,甚至可以从TCP 读取而不是从文件读取,基本逻辑是相同的。

这仍然需要一些适当的错误处理来解决丢失的文件或错误的权限,但这取决于您实现。


处理方法的示例实现:

//returns the hex-representation of the bytes
public static byte[] process(byte[] bytes, int length) {
    final char[] hexchars = "0123456789ABCDEF".toCharArray();
    char[] ret = new char[length * 2];
    for ( int i = 0; i < length; ++i) {
        int b = bytes[i] & 0xFF;
        ret[i * 2] = hexchars[b >>> 4];
        ret[i * 2 + 1] = hexchars[b & 0x0F];
    }
    return ret;
}
Run Code Online (Sandbox Code Playgroud)