(点击
上方公众号
,可快速关注)
来源:伯乐在线专栏作者 - Code4Android
链接:http://android.jobbole.com/85154/
点击 → 了解如何加入专栏作者
接上文
RandomAccessFile 方式
/**
* RandomAccessFile 获取文件的MD5值
*
* @param file 文件路径
* @return md5
*/
public
static
String
getFileMd53
(
File
file
)
{
MessageDigest
messageDigest
;
RandomAccessFile
randomAccessFile
=
null
;
try
{
messageDigest
=
MessageDigest
.
getInstance
(
"MD5"
);
if
(
file
==
null
)
{
return
""
;
}
if
(
!
file
.
exists
())
{
return
""
;
}
randomAccessFile
=
new
RandomAccessFile
(
file
,
"r"
);
byte
[]
bytes
=
new
byte
[
1024
*
1024
*
10
];
int
len
=
0
;
while
((
len
=
randomAccessFile
.
read
(
bytes
))
!=-
1
){
messageDigest
.
update
(
bytes
,
0
,
len
);
}
BigInteger
bigInt
=
new
BigInteger
(
1
,
messageDigest
.
digest
());
String
md5
=
bigInt
.
toString
(
16
);
while
(
md5
.
length
()
32
)
{
md5
=
"0"
+
md5
;
}
return
md5
;
}
catch
(
NoSuchAlgorithmException
e
)
{
// TODO Auto-generated catch block
e
.
printStackTrace
();
}
catch
(
FileNotFoundException
e
)
{
// TODO Auto-generated catch block
e
.
printStackTrace
();
}
catch
(
IOException
e
)
{
// TODO Auto-generated catch block
e
.
printStackTrace
();
}
finally
{
try
{
if
(
randomAccessFile
!=
null
)
{
randomAccessFile
.
close
();
randomAccessFile
=
null
;
}
}
catch
(
IOException
e
)
{
// TODO Auto-generated catch block
e
.
printStackTrace
();
}
}
return
""
;
}
性能对比
我们选了一个小的文件,大概1M左右,观察执行时间
11
-
09
11
:
49
:
20.210
12678
-
12678
/
com
.
example
.
xh
I
/
System
.
out
:
FileInputStream
执行时间:
179
11
-
09
11
:
49
:
20.266
12678
-
12678
/
com
.
example
.
xh
I
/
System
.
out
:
FileChannel
执行时间:
55
11
-
09
11
:
49
:
20.322
12678
-
12678
/
com
.
example
.
xh
I
/
System
.
out
:
RandomAccessFile
执行时间:
58
但是我选择大概10M的文件FileChannel+MappedByteBuffer性能并不明显,最后通过查询资料学习发现MappedByteBuffer这个东西很可怕,这个回收是不确定的,在手机上测试FileChannel效率并不是最好的。如果要计算一个几百兆的大文件,发现FileChannel+MappedByteBuffer还很容易OOM,原因就是MappedByteBuffer内存占用、文件关闭不确定,被其打开的文件只有在垃圾回收的才会被关闭,而且这个时间点是不确定的。当文件达到100M时就出现OOM如下
FATAL
EXCEPTION
:
main
java
.
lang
.
OutOfMemoryError
at
java
.
security
.
MessageDigestSpi
.
engineUpdate
(
MessageDigestSpi
.
java
:
85
)
at
java
.
security
.
MessageDigest
.
update
(
MessageDigest
.
java
:
369
)
所以在Android设备上尽量不要使用nio中的内存映射。在官方文档中有这样的一句话:A mapped byte buffer and the file mapping that it represents remain valid until the buffer itself is garbage-collected.
那么我们来计算一个大文件的MD5,此时我测试的文件是300多兆
11
-
09
16
:
06
:
49.930
3101
-
3101
/
com
.
example
.