Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/386.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/file/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 将文件读入多字节数组_Java_File_File Io - Fatal编程技术网

Java 将文件读入多字节数组

Java 将文件读入多字节数组,java,file,file-io,Java,File,File Io,我有一个加密算法(AES),它接受转换为数组字节的文件并对其进行加密。 因为我要处理一个非常大的文件,JVM可能会内存不足。 我计划读取多字节数组中的文件,每个数组包含文件的某些部分。然后我迭代地输入算法。最后,我合并它们以生成一个加密文件 所以我的问题是:有没有办法将文件一部分一部分地读取到多字节数组中 我想我可以使用以下方法将文件读入字节数组: IOUtils.toByteArray(InputStream input). 然后使用以下命令将阵列拆分为多个字节: Array

我有一个加密算法(AES),它接受转换为数组字节的文件并对其进行加密。 因为我要处理一个非常大的文件,JVM可能会内存不足。 我计划读取多字节数组中的文件,每个数组包含文件的某些部分。然后我迭代地输入算法。最后,我合并它们以生成一个加密文件

所以我的问题是:有没有办法将文件一部分一部分地读取到多字节数组中

我想我可以使用以下方法将文件读入字节数组:

    IOUtils.toByteArray(InputStream input).
然后使用以下命令将阵列拆分为多个字节:

    Arrays.copyOfRange()

<>但是我担心读取文件到<代码> ByteArray < /C> >的代码会使JVM内存不足。

如果你使用<代码> IUTILLS ,也许你应该考虑

并指定a作为输出。然后,您可以使用offset/length遍历并加载文件的各个部分

从文档:

将大(超过2GB)输入流中的部分或所有字节复制到 OutputStream,可以选择跳过输入字节


在Java中查找密码流。您可以使用它们动态加密/解密流,这样就不必将整个内容存储在内存中。您所要做的就是将源文件的常规
FileInputStream
复制到
cipheroutstream
中,该文件将为加密的接收器文件包装
FileOutputStream
IOUtils
甚至可以方便地包含一个
copy(InputStream,OutputStream)
方法来为您执行此复制

例如:

public static void main(String[] args) {
    encryptFile("exampleInput.txt", "exampleOutput.txt");
}

public static void encryptFile(String source, String sink) {
    FileInputStream fis = null;
    try {
        fis = new FileInputStream(source);
        CipherOutputStream cos = null;
        try {
            cos = new CipherOutputStream(new FileOutputStream(sink), getEncryptionCipher());
            IOUtils.copy(fis, cos);
        } finally {
            if (cos != null)
                cos.close();
        }
    } finally {
        if (fis != null)
            fis.close();
    }
}

private static Cipher getEncryptionCipher() {
    // Create AES cipher with whatever padding and other properties you want
    Cipher cipher = ... ;
    // Create AES secret key
    Key key = ... ;
    cipher.init(Cipher.ENCRYPT_MODE, key);
}
如果需要知道复制的字节数,如果文件大小超过
Integer.MAX_值
字节(2 GB),则可以使用
IOUtils.copyragle
而不是
IOUtils.copy

要解密文件,请执行相同的操作,但使用
CipherInputStream
而不是
CipherOutputStream
,并使用
Cipher.decrypt\u模式
初始化您的
密码

查看有关Java中密码流的更多信息

这将为您节省空间,因为您不再需要存储自己的
byte
数组。此系统中唯一存储的
字节[]
密码的内部
字节[]
,每次输入足够的输入并且
密码返回加密块时,该字节将被清除。更新
,或关闭
CipherOutputStream
时打开
密码.doFinal
。然而,你不必担心这些,因为这些都是内部的,一切都是为你管理的

编辑:请注意,这可能会导致忽略某些加密异常,尤其是
BadPaddingException
IllegalBlockSizeException
。此行为可以在中找到。(当然,这个源代码来自OpenJDK,但它在Sun JDK中可能做了同样的事情。)另外,来自javadocs:

该类严格遵守其祖先类
java.io.OutputStream
java.io.FilterOutputStream
的语义,尤其是失败语义。该类正好具有在其祖先类中指定的那些方法,并重写它们此外,该类捕获其祖先类未引发的所有异常。


这里粗体的一行意味着加密异常将被忽略,而实际上它们是。这可能会在尝试读取加密文件时导致一些意外行为,尤其是对于块和/或填充加密算法(如AES)。记住这一点,加密(或解密为
CipherInputStream
)文件将获得零或部分输出。

大多数加密算法在数据块上工作,不需要一次完整的数据。这完全是为了避免您正在讨论的问题,您需要将整个明文存储在内存中,以便基于它计算密文。也许只需使用
read(byte[],int,int)
函数一次读取一个块并将其提供给您的算法。在Java中查找密码流。您可以使用它们动态加密/解密流,这样就不必将整个内容存储在内存中。然后,您需要做的就是将源文件的常规
FileInputStream
复制到
CipherOutputStream
中,该文件将为加密的接收器文件包装
FileOutputStream
IOUtils
甚至方便地包含一个
copy(InputStream,OutputStream)
方法来为您执行此复制。如果您要复制到ByteArrayOutputStream中,这对内存使用有何帮助?因为您一次只复制部分。我本以为这是显而易见的,但我会修正的,我不明白为什么需要这样做。您可以改为使用缓冲流,尽管大部分时间磁盘I/O都是缓冲的,所以这并不重要。也许您不理解我的评论。为什么在将整个文件放入ByteArrayOutputStream(即“一个大字节数组”)时,一次复制部分文件很重要?(换句话说,您的ByteArrayOutputStream将导致内存问题)。@jtahlborn如果我没有弄错的话,他所提倡的是通过偏移量/长度将文件的一部分复制到BAS,从BAS获取字节,对它们进行加密,然后将加密的字节写入接收器输出流,然后用一个干净的包来完成整个过程。请记住,您可以重置BAO并限制其缓冲区大小。但此时,您也可以使用普通的
byte[]
和输入流的
int-read(byte[])
方法,完全跳过BAO。Java密码流可能会将异常推到表下,尤其是
BadPaddingException
s。你已经被警告过了。嗯,会的。我会用这些信息更新我的答案。
public static void main(String[] args) {
    encryptFile("exampleInput.txt", "exampleOutput.txt");
}

public static void encryptFile(String source, String sink) {
    FileInputStream fis = null;
    try {
        fis = new FileInputStream(source);
        CipherOutputStream cos = null;
        try {
            cos = new CipherOutputStream(new FileOutputStream(sink), getEncryptionCipher());
            IOUtils.copy(fis, cos);
        } finally {
            if (cos != null)
                cos.close();
        }
    } finally {
        if (fis != null)
            fis.close();
    }
}

private static Cipher getEncryptionCipher() {
    // Create AES cipher with whatever padding and other properties you want
    Cipher cipher = ... ;
    // Create AES secret key
    Key key = ... ;
    cipher.init(Cipher.ENCRYPT_MODE, key);
}