ByteArrayOutputStream的内存溢出问题

svgr314 2011-05-30 11:53:55

最近在研究文件的加密解密(AES),但是在文件流的读写方面不是很熟。请熟悉的朋友帮看看下面的异常是怎么回事,谢谢啦


protected static byte[] readbyte(InputStream stream) {
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int length = 0;

while ((length = stream.read(buffer)) > 0) {
baos.write(buffer, 0, length); // 异常
}
return baos.toByteArray();

} catch (Exception exception) {
return exception.getMessage().getBytes();
}
}


当传入大文件的时候会出现内存溢出异常:

Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
...全文
4999 10 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
svgr314 2011-06-03
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 mtv0199 的回复:]
看下4楼的方法吧,你的加密方法是把文件一次性读入内存,整个进行加密的,这样文件过大的话肯定会有溢出。7楼的方法是边加密边写入文件。我觉得问题就能出现在这里。比如你一次性对123加密和分别对1,2,3加密得到的序列应该是不同的吧。如果你还是采用对123整体解密的方法,可能会有问题。
[/Quote]

OK 解决了! 现在在考虑跟C++互解的问题。C这一端是要根据算法自己写的。请问是不是要知道java这端AES是使用哪种工作模式才能实现互解呀? 我的代码是属于哪种模式?
svgr314 2011-05-31
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 yeecheng 的回复:]

Java code

public static void EncryptFile(String pwd, File fileIn, File fileOut)
throws Exception {
try {
// ????
FileInputStream fis = new FileInputS……
[/Quote]


谢谢~这样可以加密了 。可是解密的时候会出异常:
Exception in thread "main" java.lang.Exception: Given final block not properly padded
网上找了蛮多方法都无能为力…… 莫名其妙啊!
mtv0199 2011-05-31
  • 打赏
  • 举报
回复
看下4楼的方法吧,你的加密方法是把文件一次性读入内存,整个进行加密的,这样文件过大的话肯定会有溢出。7楼的方法是边加密边写入文件。我觉得问题就能出现在这里。比如你一次性对123加密和分别对1,2,3加密得到的序列应该是不同的吧。如果你还是采用对123整体解密的方法,可能会有问题。
svgr314 2011-05-30
  • 打赏
  • 举报
回复
额~还是把调用的代码也一起贴出来吧:


// 加密文件
public static void EncryptFile(String pwd, File fileIn, File fileOut)
throws Exception {
try {
// 读取文件
FileInputStream fis = new FileInputStream(fileIn);
byte[] bytIn = readbyte(fis);
// AES加密
KeyGenerator kgen = KeyGenerator.getInstance("AES");
kgen.init(128, new SecureRandom(pwd.getBytes()));
SecretKey skey = kgen.generateKey();
byte[] raw = skey.getEncoded();
SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
// 写文件
byte[] bytOut = cipher.doFinal(bytIn);
FileOutputStream fos = new FileOutputStream(fileOut);
InputStream sbs = new ByteArrayInputStream(bytOut);
fos.write(readbyte(sbs));
fos.close();
fis.close();
} catch (Exception e) {
throw new Exception(e.getMessage());
}
}


// 读取InputStream转换为byte函数 ----2011-02-23 by hrg
protected static byte[] readbyte(InputStream stream) {
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int length = 0;

while ((length = stream.read(buffer)) > 0) {
baos.write(buffer, 0, length);
}
return baos.toByteArray();

} catch (Exception exception) {
return exception.getMessage().getBytes();
}
}






现在传入小文件没事,大一点的(比如100M以上)就报内存溢出了。高手来帮看一下该如何改撒!
yeecheng 2011-05-30
  • 打赏
  • 举报
回复

public static void EncryptFile(String pwd, File fileIn, File fileOut)
throws Exception {
try {
// ????
FileInputStream fis = new FileInputStream(fileIn);

KeyGenerator kgen = KeyGenerator.getInstance("AES");
kgen.init(128, new SecureRandom(pwd.getBytes()));
SecretKey skey = kgen.generateKey();
byte[] raw = skey.getEncoded();
SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
// ???

FileOutputStream fos = new FileOutputStream(fileOut);

byte[] buffer = new byte[1024];
int length = 0;
while ((length = fis.read(buffer)) > 0) {
byte[] bytOut = cipher.doFinal(buffer, 0, length);
fos.write(bytOut, 0, byteOut.length);
}

fos.close();
fis.close();
} catch (Exception e) {
throw new Exception(e.getMessage());
}
}



没验证过是不是正确
svgr314 2011-05-30
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 yeecheng 的回复:]

不要用ByteArrayOutputStream/ByteArrayOutputStream, 这两个类都会把数据保存在内存中。可以直接用FileOutputStream/FileInputStream
[/Quote]

对文件流不是很懂,能稍微说一下用fileInputStream该怎么改吗?
svgr314 2011-05-30
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 wenbodong 的回复:]

就是内存溢出。虚拟机运行的时候,是有内存上限的,默认的应该是几十兆。但是你可以手动设置的。
java name -Xms100m -Xmx800m
-Xms设置的是虚拟机初始化name程序时的内存分配,这里是100m,-Xmx是name程序可获得的最大的内存,这里是800m。
如果你是使用IDE的话,就更方便,可以设置工程属性中的运行参数,将-Xms100m -Xmx800m添加上去,
……
[/Quote]


这个要设置多少呢? 就算设置内存再大也有可能会超过的吧?
zx8813443 2011-05-30
  • 打赏
  • 举报
回复
我百度了下,发现一个帖子,看看你可以参考一下不

http://www.blogjava.net/midstr/archive/2008/08/30/225744.html
yeecheng 2011-05-30
  • 打赏
  • 举报
回复
不要用ByteArrayOutputStream/ByteArrayOutputStream, 这两个类都会把数据保存在内存中。可以直接用FileOutputStream/FileInputStream
wenbodong 2011-05-30
  • 打赏
  • 举报
回复
就是内存溢出。虚拟机运行的时候,是有内存上限的,默认的应该是几十兆。但是你可以手动设置的。
java name -Xms100m -Xmx800m
-Xms设置的是虚拟机初始化name程序时的内存分配,这里是100m,-Xmx是name程序可获得的最大的内存,这里是800m。
如果你是使用IDE的话,就更方便,可以设置工程属性中的运行参数,将-Xms100m -Xmx800m添加上去,
比如,使用NetBean,在项目列表中选中某个工程,右击--属性,在左边的类别中选择--运行,将-Xms100m -Xmx800m添加在VM选项中。

62,635

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧