Java 利用Linux Openssl 库计算文件校验码
2011-09-07 00:46
288 查看
在传统Java编程中, 我们可以另用ProcessBuilder类来创建系统进程或者Runtime类来取得JVM的接口对象运行我们指定的系统命令, 并且可以通过读入器来获取系统的out以及err输出.这里有一个简单的例子, 没有用过的同学可以参考一下.
http://wuhongyu.iteye.com/blog/461477
由于前段时间有这样的一个需求, 尽可能快的算出Hadoop系统里的MD码, 我曾经想过另用Java的Digest类来读取文件, 然后工作交给Digest类来完成, 可没想到的是Java的这个类算MD校验码,效率及其的低下,我在XP上算50M的文件, 居然花费8秒钟的时间.直接放弃. 这个Demo我也顺便推荐一下:
http://www.javablogging.com/?s=Java+Digest+SHA1+MD5
后来google该问题的解决方案, 有一个比较有意思的贴子Fast MD5 Implementation in Java, 呵呵, 由于时间关系, 没来的急看,分享一下:
http://www.twmacinta.com/myjava/fast_md5.php
Fast MD5.. 总给我一个不太舒服的感觉, 最后还是决定放弃使用. 由于Hadoop运行于Linux 环境, 回过神来我想到了Linux上的openssl库. 大伙都知道openssl 里其中就有计算数据的安全通信命令. $cat XXX | openssl sha1.
这里有一个问题, 由于hadoop的文件是存在于集群的, 而openssl 是接受本地文件作为参数的, 我可以把文件从HDFS里读出, 然后再构造文件供openssl 计算. 不过这种方式太囧.
我的解决方法是另用Runtime获取运行对象, 直接执行openssl sha1命令, 其实当系统执行该命令的时候会等待输入的. 此时我可以通过我的文件输入流把数据打印到等待输入的输出流上。
Java代码
// TODO this is a job. not a filedescriptor
protected void handle(FileDescriptor job) throws IOException {
if (job == null || job.path == null) {
log.warn("Invalid job: " + job);
}
// wait for GC.
Configuration conf = new Configuration();
Path path = new Path(job.path);
FileSystem fs = path.getFileSystem(conf);
if (!fs.exists(path) || !fs.isFile(path)) {
log.warn("*HADLEJOB file does not exist for path: " + path);
return;
}
InputStream is = fs.open(path);
// Run a command
String cmd = "openssl sha1";
boolean completed = false;
Process process = null; // Sub process used to execute the command
int exitCode;
process = Runtime.getRuntime().exec(cmd);
BufferedOutputStream os = new BufferedOutputStream(process.getOutputStream(), 4096);
byte buf[] = new byte[4096];
while (true) {
int bytesRead = is.read(buf);
if (bytesRead == -1) {
break;
}
os.write(buf, 0, bytesRead);
}
os.flush();
os.close();
final BufferedReader errReader =
new BufferedReader(new InputStreamReader(process.getErrorStream()));
BufferedReader inReader =
new BufferedReader(new InputStreamReader(process.getInputStream()));
final StringBuffer errMsg = new StringBuffer();
// read error and input streams as this would free up the buffers
// free the error stream buffer
Thread errThread = new Thread(){
public void run() {
try {
String line = errReader.readLine();
while ((line != null) && !isInterrupted()) {
errMsg.append(line);
errMsg.append(System.getProperty("line.separator"));
line = errReader.readLine();
}
} catch (IOException ioe) {
log.warn("Error reading the error stream", ioe);
}
}
};
try {
errThread.start();
} catch (IllegalStateException ise) {
}
try {
String line = inReader.readLine();
if (line == null) {
throw new IOException("Exception a line not the end of stream");
}
job.set_sha1(line.trim());
// clear the input stream buffer
line = inReader.readLine();
while (line != null) {
line = inReader.readLine();
}
// wait for the process to finish and check the exit code
exitCode = process.waitFor();
try {
errThread.join();
} catch (InterruptedException ie) {
log.warn("Interrupted while reading the error stream", ie);
}
completed = true;
if (exitCode != 0) {
throw new IOException(exitCode + errMsg.toString());
}
} catch (InterruptedException ie) {
throw new IOException(ie.toString());
} finally {
// close the input stream
try {
inReader.close();
} catch (IOException e) {
log.warn("Error whilke closing the input stream", e);
}
if (!completed) {
errThread.interrupt();
}
try {
errReader.close();
}catch(IOException ioe){
log.warn("Error while closing the error stream", ioe);
}
process.destroy();
}
}
该执行方法运行于线程池中, 下一个贴子我将记录真正应用中线程池的实现, 提供线程池的大小设置, shrink等实现.
http://wuhongyu.iteye.com/blog/461477
由于前段时间有这样的一个需求, 尽可能快的算出Hadoop系统里的MD码, 我曾经想过另用Java的Digest类来读取文件, 然后工作交给Digest类来完成, 可没想到的是Java的这个类算MD校验码,效率及其的低下,我在XP上算50M的文件, 居然花费8秒钟的时间.直接放弃. 这个Demo我也顺便推荐一下:
http://www.javablogging.com/?s=Java+Digest+SHA1+MD5
后来google该问题的解决方案, 有一个比较有意思的贴子Fast MD5 Implementation in Java, 呵呵, 由于时间关系, 没来的急看,分享一下:
http://www.twmacinta.com/myjava/fast_md5.php
Fast MD5.. 总给我一个不太舒服的感觉, 最后还是决定放弃使用. 由于Hadoop运行于Linux 环境, 回过神来我想到了Linux上的openssl库. 大伙都知道openssl 里其中就有计算数据的安全通信命令. $cat XXX | openssl sha1.
这里有一个问题, 由于hadoop的文件是存在于集群的, 而openssl 是接受本地文件作为参数的, 我可以把文件从HDFS里读出, 然后再构造文件供openssl 计算. 不过这种方式太囧.
我的解决方法是另用Runtime获取运行对象, 直接执行openssl sha1命令, 其实当系统执行该命令的时候会等待输入的. 此时我可以通过我的文件输入流把数据打印到等待输入的输出流上。
Java代码
// TODO this is a job. not a filedescriptor
protected void handle(FileDescriptor job) throws IOException {
if (job == null || job.path == null) {
log.warn("Invalid job: " + job);
}
// wait for GC.
Configuration conf = new Configuration();
Path path = new Path(job.path);
FileSystem fs = path.getFileSystem(conf);
if (!fs.exists(path) || !fs.isFile(path)) {
log.warn("*HADLEJOB file does not exist for path: " + path);
return;
}
InputStream is = fs.open(path);
// Run a command
String cmd = "openssl sha1";
boolean completed = false;
Process process = null; // Sub process used to execute the command
int exitCode;
process = Runtime.getRuntime().exec(cmd);
BufferedOutputStream os = new BufferedOutputStream(process.getOutputStream(), 4096);
byte buf[] = new byte[4096];
while (true) {
int bytesRead = is.read(buf);
if (bytesRead == -1) {
break;
}
os.write(buf, 0, bytesRead);
}
os.flush();
os.close();
final BufferedReader errReader =
new BufferedReader(new InputStreamReader(process.getErrorStream()));
BufferedReader inReader =
new BufferedReader(new InputStreamReader(process.getInputStream()));
final StringBuffer errMsg = new StringBuffer();
// read error and input streams as this would free up the buffers
// free the error stream buffer
Thread errThread = new Thread(){
public void run() {
try {
String line = errReader.readLine();
while ((line != null) && !isInterrupted()) {
errMsg.append(line);
errMsg.append(System.getProperty("line.separator"));
line = errReader.readLine();
}
} catch (IOException ioe) {
log.warn("Error reading the error stream", ioe);
}
}
};
try {
errThread.start();
} catch (IllegalStateException ise) {
}
try {
String line = inReader.readLine();
if (line == null) {
throw new IOException("Exception a line not the end of stream");
}
job.set_sha1(line.trim());
// clear the input stream buffer
line = inReader.readLine();
while (line != null) {
line = inReader.readLine();
}
// wait for the process to finish and check the exit code
exitCode = process.waitFor();
try {
errThread.join();
} catch (InterruptedException ie) {
log.warn("Interrupted while reading the error stream", ie);
}
completed = true;
if (exitCode != 0) {
throw new IOException(exitCode + errMsg.toString());
}
} catch (InterruptedException ie) {
throw new IOException(ie.toString());
} finally {
// close the input stream
try {
inReader.close();
} catch (IOException e) {
log.warn("Error whilke closing the input stream", e);
}
if (!completed) {
errThread.interrupt();
}
try {
errReader.close();
}catch(IOException ioe){
log.warn("Error while closing the error stream", ioe);
}
process.destroy();
}
}
该执行方法运行于线程池中, 下一个贴子我将记录真正应用中线程池的实现, 提供线程池的大小设置, shrink等实现.
相关文章推荐
- 如何利用Java虚拟Unix/Linux的文件路径
- java使用计算md5校验码方式比较两个文件是否相同
- Linux下利用openssl对文件进行加密和解密
- java使用计算md5校验码方式比较两个文件是否相同
- 关于java应用MD5校验文件和linux下md5Linux校验文件结果一致问题。
- 【java】 linux下利用nohup后台运行jar文件包程序
- Java利用ImageMagick调用linux系统命令实现Ai或者PSD文件转化为jpg或者png文件
- Java利用ssh协议实现本地文件到远程Linux服务器的上传。
- Linux下利用openssl对文件进行加密和解密
- md5sum命令_Linux md5sum 命令用法详解:计算和校验文件报文摘要的工具程序
- 如何利用openssl来计算一个文件的MD5值?
- 如何利用openSsl来计算一个文件的md5值?
- java上传文件到linux上 防止文件名中文乱码
- linux下利用openssl来实现证书的颁发(详细步骤)
- 用Java修改Window或者Linux下的hosts文件
- JAVA File类的hashCode()和计算文件hash值的区别
- Java基础回顾 : 利用字节流实现文件的拷贝
- 关于java读文件计算一个方法执行时间的程序的学习
- JAVA使用FTPClient类获取linux上的文件最后修改日期少了8小时
- 利用hadoop计算文件中的最大值