读取代码如下
InputStream in = new ClassPathResource("binary_file.dat").getInputStream();
out = new ByteArrayOutputStream();
byte[] b = new byte[1024];
while(in.read(b) != -1){
out.write(b);
}
log.info("data size = {}", out.size());
俺使用两种方式执行
发现两种方式的 size 不一样.
文件大小在 28M 左右.
奇怪啊~~~
1
asanelder OP 神奇啊, 使用 guava 中的工具类来读取就没这个问题了...
in = new ClassPathResource("binary_file.dat").getInputStream(); data = ByteStreams.toByteArray(in); log.info("data size = {}", out.size()); |
2
AoEiuV020CN 2022-01-05 18:05:29 +08:00 1
首先,代码有误,read 会返回长度 length ,write 时应当只 write 一个范围 0, length ,
|
3
asanelder OP @AoEiuV020CN #2 就算有误的话, 相同的代码, 相同的文件, 一个是打包后执行, 一个是打包前执行, 按道理说, 应该结果也是一样的吧
|
4
AoEiuV020CN 2022-01-05 18:25:07 +08:00
@asanelder #3 具体原因我不知道,read 方法很容易涉及到框架内部或者 jvm 内部,要说直接运行和打包后运行保证这些内部环境完全一样我看也不能保证,没准当时内存占用多了一比特就导致不同的缓存处理进而导致其他其他不同,
不是很想深究错误的代码为什么会引发另一个错误, |
5
codehz 2022-01-05 18:46:58 +08:00
@asanelder 打包之后被压缩了啊,然后就需要边解压边读取,zip 压缩也不是固定输出大小的压缩,解压的时候也很难预测要读多少内容才能得到 1024 ,通常的思路就是读固定大小,然后解出多少就提供多少(
|
6
Jwyt 2022-01-05 19:05:50 +08:00
@codehz 楼主说的是打 jar 包,不是被读的文件
不过代码确实有问题,应该是 (len=in.read(b)) !=-1; out.write(b,0,len); 当然为啥会不一样我也不清楚,楼主可以把代码改了之后再打包试试 |
7
AoEiuV020CN 2022-01-05 19:26:41 +08:00 1
@Jwyt #6 应该就是打包压缩的问题,楼主代码中的 ClassPathResource 读取的文件是会被打包到 jar 里的,
边解压边读取导致无法指定读取 1024 字节,可能比如一次解压出了 500 个字节,read 就直接返回 500 ,下次 read 再解压读取剩下的, |
8
GuuJiang 2022-01-05 19:39:27 +08:00 1
@asanelder 你这样读到 out 里的内容都是错误的,更别说长度了,一次 read 可能小于 1024 ,但是每次 write 都是写入整个 b 数组,导致多出了一些垃圾数据
|
9
Jwyt 2022-01-05 20:30:27 +08:00
@AoEiuV020CN 对 我忘了这一茬了
|
10
asanelder OP |
11
asanelder OP @AoEiuV020CN #4
@codehz #5 @Jwyt #6 @AoEiuV020CN #7 @GuuJiang #8 嗯, 确实是代码有问题, 俺按照铁子们的说法修改后 byte[] b = new byte[1024]; int len = in.read(b); while(len != -1){ out.write(b, 0, len); len = in.read(b); } log.info("data size = {}", data.length); 就正常了 至于具体原因~~~ 看样子还是得按照文档正确调用接口, 这样其行为才和预期一样. 至于之前没有指定 length 导致在 jar 中和非 jar 中形为不一致. 就忽略吧 |