`
david.org
  • 浏览: 157458 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

Java 利用Linux Openssl 库计算文件校验码

阅读更多
在传统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命令, 其实当系统执行该命令的时候会等待输入的. 此时我可以通过我的文件输入流把数据打印到等待输入的输出流上。

// 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等实现.

分享到:
评论
10 楼 emuggle 2010-02-10  
david.org 写道
llyzq 写道
好帖子

不过我有个问题要请教了

JAVA里如何调用bat脚本文件?

我前段时间在项目中碰到这样的问题,后来公司的一位老师利用VB做了个壳

通过VB传入bat文件的地址作为参数来调用


你好, llyzq:

感谢对本贴的支持.
bat 在windows系统上是一个可执行(executable)程序, 但不同于exe文件, 他们俩运行起来最明显的区别是exe可以正常启动, 这就像打开notepad, 或者打开*.doc文档一样, 但bat不同, 它必须有一个Shell来读取它的输出,然后interpret这个bat进程.

你可以试一下以下代码:
pp=run.exec("cmd.com /c *.bat") ;


run.exec("cmd.exe /c *.bat");
9 楼 david.org 2010-02-09  
llyzq 写道
好帖子

不过我有个问题要请教了

JAVA里如何调用bat脚本文件?

我前段时间在项目中碰到这样的问题,后来公司的一位老师利用VB做了个壳

通过VB传入bat文件的地址作为参数来调用


你好, llyzq:

感谢对本贴的支持.
bat 在windows系统上是一个可执行(executable)程序, 但不同于exe文件, 他们俩运行起来最明显的区别是exe可以正常启动, 这就像打开notepad, 或者打开*.doc文档一样, 但bat不同, 它必须有一个Shell来读取它的输出,然后interpret这个bat进程.

你可以试一下以下代码:
pp=run.exec("cmd.com /c *.bat") ;
8 楼 llyzq 2010-02-09  
好帖子

不过我有个问题要请教了

JAVA里如何调用bat脚本文件?

我前段时间在项目中碰到这样的问题,后来公司的一位老师利用VB做了个壳

通过VB传入bat文件的地址作为参数来调用
7 楼 david.org 2010-02-09  
luanma 写道
执行系统命令其他工具还有Apache Common exec

http://commons.apache.org/exec/

也很方便,可以跨平台,建议参考一下


嗯, 刚才看了一下介绍, 还是使用了ProcessBuilder类来生成子进程完成系统命令执行的, 但在我这个场合, 主进程里的输入流是没有办法打印到子进程里的输出流上的.

再者, 方法的意图只是想高效率的计算文件的校验码, 不知luanma同学有什么推荐不, 呵呵
6 楼 david.org 2010-02-09  
chenlixun 写道
luanma 写道
执行系统命令其他工具还有Apache Common exec

http://commons.apache.org/exec/

也很方便,可以跨平台,建议参考一下


这个要顶,楼主莫生气啊.


哈哈, 没啥的, 哪个好用用哪个. 同样感谢chenlixun的分享, 先收下了, 这个确实没用过.
5 楼 david.org 2010-02-09  
hbbbs 写道
谢谢楼主经验介绍...

有点小建议:
1、我们帖子的主题希望能更凸显一下,比如说:
   a、我们的帖子重点是哪里?
   b、那段代码的核心部分是几个地方?

2、MD5那块我们可以放在最下面当作附录和你的探索过程,对MD5感兴趣的人将会去看这块。
3、整体代码可以作为附件,有需要的人将会去下载。


呵呵, 同样感谢你的经验分享. 写这个贴子最大的动机是为了记录与整理自己的思路.
4 楼 chenlixun 2010-02-09  
luanma 写道
执行系统命令其他工具还有Apache Common exec

http://commons.apache.org/exec/

也很方便,可以跨平台,建议参考一下


这个要顶,楼主莫生气啊.
3 楼 luanma 2010-02-09  
执行系统命令其他工具还有Apache Common exec

http://commons.apache.org/exec/

也很方便,可以跨平台,建议参考一下
2 楼 hbbbs 2010-02-09  
谢谢楼主经验介绍...

有点小建议:
1、我们帖子的主题希望能更凸显一下,比如说:
   a、我们的帖子重点是哪里?
   b、那段代码的核心部分是几个地方?

2、MD5那块我们可以放在最下面当作附录和你的探索过程,对MD5感兴趣的人将会去看这块。
3、整体代码可以作为附件,有需要的人将会去下载。
1 楼 david.org 2010-02-06  
犯了一个低级错误
# if (job == null || job.path == null) {  
#             log.warn("Invalid job: " + job);  
#         }  


改成:
if (job == null || job.path == null) {
			log.warn("Invalid job: " + job);
			return;
		}

相关推荐

    java调用openssl生成证书

    此外,`openssljava.jar`可能是封装了上述调用OpenSSL功能的Java库,这样可以更方便地在Java代码中生成和管理证书,而不需要直接操作系统命令。使用这样的库可以简化代码,降低安全风险,并提供更好的跨平台兼容性。...

    LinuxOpenssl-install安装包

    Linux OpenSSL 安装包是一个专为Linux系统设计的工具,旨在简化OpenSSL库的安装过程。OpenSSL是一个强大的安全套接层(SSL)密码库,包含各种加密算法、常用的密钥和证书封装管理功能,以及SSL协议,并提供丰富的...

    tc8 x64 openssl库文件补丁

    OpenSSL库文件是实现这些安全通信协议所必需的,它们提供了加密算法、证书管理和安全套接字层(SSL)/传输层安全(TLS)协议支持。 描述中提到的情况是,当用户尝试在Total Commander 8的64位环境下访问FTPS或HTTPS...

    openssl库文件

    OpenSSL库文件是用于开发和运行使用加密技术的软件的重要组件。这个压缩包包含了在Visual Studio 2013环境下编译完成的lib静态库、dll动态链接库以及相关的头文件,确保了开发者可以在该环境下顺利地进行项目构建。...

    linux升级openssl9.3,linux升级openssl9.3,linux升级openssl9.3,linux升级ope

    linux升级openssl9.3,linux升级openssl9.3,linux升级openssl9.3,linux升级opelinux升级openssl9.3,linux升级openssl9.3,linux升级openssl9.3,linux升级opelinux升级openssl9.3,linux升级openssl9.3,linux...

    openSSL头文件和静态库文件以及动态库

    3. 配置crtmpserver项目,指定OpenSSL头文件的位置和生成的静态库文件。 4. 编译并链接crtmpserver,确保没有OpenSSL相关的链接错误。 5. 如需使用动态库,还需将对应的dll文件与crtmpserver一起部署。 在实际应用...

    java的ssl客户端编程与LINUX的OpenSSL服务器通讯的实现及有关文

    java的ssl客户端编程与LINUX的OpenSSL服务器通讯的实现及有关文档 附件中包含本人开发工程中使用过的DEMO程序及制作证书的解本文件

    linux下的openssl安装包

    这会生成可执行文件和库文件。 5. **安装到系统**:最后,使用`make install`命令将OpenSSL安装到系统路径: ``` sudo make install ``` 通常需要管理员权限来完成此步骤。 6. **验证安装**:安装完成后,...

    Linux grpc+openssl库

    博客请参考:https://blog.csdn.net/ManagerUser/article/details/124878693#comments_22867458

    iOS版编译完成的OpenSSL库

    OpenSSL库主要包括两个主要部分:头文件(.h)和静态库文件(.a)。头文件包含了函数声明和数据结构定义,使得开发者可以在代码中调用OpenSSL提供的功能。静态库文件则包含预编译的二进制代码,这些代码在应用链接时...

    基于openssl的ftp文件传输系统源码.zip

    基于openssl的ftp文件传输系统源码基于openssl的ftp文件传输系统源码基于openssl的ftp文件传输系统源码基于openssl的ftp文件传输系统源码基于openssl的ftp文件传输系统源码基于openssl的ftp文件传输系统源码基于...

    curl需要的openssl库文件

    **openssl库文件详解** `openssl`库包含了加密算法、数字证书、哈希函数、随机数生成器等多种安全功能。其中,主要的库文件包括`libssl`和`libcrypto`: 1. **libssl**: 这个库主要负责SSL/TLS协议的实现,包括...

    openssl和openssl-devel离线rpm安装包.zip_OPENSSL 库_openssl_openssl-deve

    `openssl-devel` 是OpenSSL的开发库,包含了头文件和静态链接库,用于编译和链接到OpenSSL功能的应用程序。开发人员在编写需要使用OpenSSL的软件时,需要安装这个包,以便在编译时可以正确地引用OpenSSL的函数和结构...

    编译好的OpenSSL库

    6. **OpenSSL库文件内容** 压缩包中的文件可能包括以下部分: - lib文件夹:存放编译生成的静态库文件(.lib)和动态库文件(.dll)。 - include文件夹:包含OpenSSL的头文件,供开发人员在项目中引用。 - ...

    OpenSSLForJava.zip

    至于`OpenSSL`目录,这可能是包含OpenSSL库的文件,如动态链接库(dll文件在Windows上,so文件在Linux上)和其他必要的头文件和库文件。这些文件是Java程序调用OpenSSL功能的基础,开发者需要确保这些库文件与Java...

    openssl库已经编译的文件

    这通常涉及设置编译器选项以包含 OpenSSL 头文件(如 `#include <openssl/ssl.h>`)和链接到相应的库文件(如 `-lssl` 和 `-lcrypto`)。一旦链接正确,你就可以访问 OpenSSL 提供的各种功能了。 1. **加密算法**:...

    openssl rc4 java 实现

    "openssl rc4 算法 java版.doc" 这个文件可能是文档形式的教程或代码示例,详细介绍了如何在Java中实现RC4算法,可能包含步骤、代码示例以及与OpenSSL C++版本的对比。 **相关知识点:** 1. **RC4算法原理**:RC4...

    OpenSSL-1.0.2m静态库

    静态库在编译时会将库代码直接合并到可执行文件中,使得最终生成的程序不依赖于运行环境的库文件,因此在某些情况下更便于部署和分发。动态库则是在运行时由操作系统加载,可以节省磁盘空间和内存,但需要确保目标...

    X86_64 linux openssl1.0.0s 编译出的静态库

    开发项目需要使用1.0.0版本的Openssl的linux上的静态库,使用1.0.2版本Openssl会存在版本问题。开始试着在网上寻找此1.0.0版本已编译出静态库,然而此版本不是源代码,动态库,就是windows编译出的静态库,即使最终...

Global site tag (gtag.js) - Google Analytics