在读取InputStream时修改读取的字节,而不是稍后修改。

3

我需要做一个简单的加密,以便普通用户无法轻易访问某些文件。

由FileInputStream读取的文件包括HTML文件、PNG、JPEG和不同的简单文本文件(JavaScript、XML等)

目前我所做的是:

public static byte[] toEncryptedByteArray(InputStream input) throws IOException {
    ByteArrayOutputStream output = new ByteArrayOutputStream();
    copy(input, output, true);
    return output.toByteArray();
}

public synchronized static final int copy(final InputStream input, final OutputStream output, final boolean modify) throws IOException {
    if (input == null || output == null) {
        throw new IOException("One stream is null!");
    }
    byte[] mBuffer = new byte[DEFAULT_BUFFER_SIZE];
    int count = 0;
    int n;
    while ((n = input.read(mBuffer)) != -1) {
        if (modify) {
            for ( int i = 0 ; i < n ; i++ ) {
                mBuffer[i] = (byte) ~mBuffer[i]; // byte manipulation
            }
        }
        output.write(mBuffer, 0, n);
        output.flush();
        count += n;
    }
    mBuffer = null;
    return count;
}

由于我在内存中有完整的字节数组(我们谈论的是内存中超过2MB的位图),因此内存占用量很大。

我曾以为可以简单地扩展FileInputStream类,在读取文件内容时进行字节操作。这将减少内存使用量,因为我可以使用Bitmap.decodeStream(inputstream)而不是创建一个字节数组来获取位图...但现在我完全陷入了困境。 read()readBytes(...)方法是本地方法,因此我无法覆盖它们。

请在我的黑暗中传递光明...


只有final方法不能被覆盖。 - Dan S
1
read()和readBytes(...)方法可能是本地的,但据我所知,调用super并没有过时。 - Perception
@Dan,你能覆盖一个本地方法吗?我觉得不行... - WarrenFaith
是的,这是可能的,因为我已经编写了能够实现这一点的代码。 - Dan S
2个回答

2

流是为了包装而设计的。这就是为什么你经常会看到这样的行:

InputStream is=new BufferedInputStream(new FileInputStream(file));

因此,创建一个DecryptingInputStream来进行解密,它会包装另一个InputStream

尽管如此,这种方法很容易被破解,因为任何反编译你的应用程序的人都可以轻松地确定你的解密密钥和算法。


这种解密只是为了混淆SD卡上的文件,以防止普通用户从手机复制文件。包装不会减少内存使用量,对吧?我修改字节的方式是一样的。或者我错了吗? - WarrenFaith
@WarrenFaith: “包装不会减少内存使用量,对吧?” -- 它将会像覆盖方法一样减少内存使用量。 - CommonsWare

0

FileInputStream不是你的问题。read()函数每次调用不会读取超过DEFAULT_BUFFER_SIZE。是你使用的ByteArrayOutputStream正在大量消耗内存,因为你正在向其中写入数据。

如果你想减少所需的内存量,我建议你直接写入FileOutputStream而不是ByteArrayOutputStream。因此,当从InputStream读取DEFAULT_BUFFER_SIZE时,加密并写入磁盘。


我不会将它保存在磁盘上。它已经加密并保存在磁盘上了。我需要在从磁盘读取时进行即时解密。由于我的当前实现是在InputStream之外进行解密,因此我需要一个字节数组来执行解密。这就是我需要该数组的原因。我将尝试像CommonsWare建议的那样进行包装。 - WarrenFaith

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接