java.lang.outofmemoryerror在加密Android中的大文件



我正在尝试使用Android中的AES算法对23 MB文件进行加密。当文件大小约为3-4 MB时,代码可以工作。但是,当我用23 MB文件测试时,它给了我java.lang.OutOfMemoryError

这是代码 -

                 try{
                        SecretKeySpec skey = new SecretKeySpec(Hex.decodeHex(key.toCharArray()), "AES");
                        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
                        cipher.init(Cipher.ENCRYPT_MODE, skey);
                        output = cipher.doFinal(bFile);
                        String SD_CARD_PATH = Environment.getExternalStorageDirectory().toString();
                        FileOutputStream fileOuputStream = new FileOutputStream(SD_CARD_PATH+ "/" + "abcd.db"); 
                        fileOuputStream.write(output);
                        fileOuputStream.close();
                        //System.out.println(output);
                    }catch(Exception e){
                        System.out.println("Error: "+e);
                    }

我在线路output = cipher.doFinal(bFile);中遇到此错误还有其他方法吗?我该怎么办?

您有一个OOME,因为bFile是一个数组,因此您可能在内存中拥有整个输入文件。output是另一个字节数组,因此您还将整个输出文件持有RAM。如您所知

这是"数组方法"的主要缺点之一。另一个是与阵列缓冲区大小有关的填充问题。不幸的是,搜索引擎返回的大多数代码示例都显示了数组方法,因此,存在很多问题。

您应该知道有一种替代流方式。事实证明,它更容易更安全。它涉及使用CipherInputStream(解密)和CipherOutputStream进行加密。示例:

    InputStream is = new FileInputStream(...); //Input stream
    SecretKeySpec skey = new SecretKeySpec(Hex.decodeHex(key.toCharArray()), "AES");
    Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
    cipher.init(Cipher.ENCRYPT_MODE, skey); 
    FileOutputStream fileOuputStream = new FileOutputStream(SD_CARD_PATH+ "/" + "abcd.db"); 
    CipherOutputStream cos = new CipherOutputStream(fileOuputStream, cipher);
    //Now read from input and write to output using your favorite utilities library
    //Guava and Apache Commons IO are good examples.
    FooUtils.copy(is, cos);
    //Remember to close streams if the previous call didn't (preferably in a finally block)

您在内存中加密整个文件,然后编写它。您应该做的是在多个部分操作中逐渐编写。

我认为您应该查看:Java 256位基于密码的加密

看第二个答案。方法

public void WriteEncryptedFile (File input, File output)

应该准确地做您需要做的事情。希望这会有所帮助。