精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2010-02-06
最后修改:2010-02-09
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等实现. 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间: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; } |
|
返回顶楼 | |
发表时间:2010-02-09
最后修改:2010-02-09
谢谢楼主经验介绍...
有点小建议: 1、我们帖子的主题希望能更凸显一下,比如说: a、我们的帖子重点是哪里? b、那段代码的核心部分是几个地方? 2、MD5那块我们可以放在最下面当作附录和你的探索过程,对MD5感兴趣的人将会去看这块。 3、整体代码可以作为附件,有需要的人将会去下载。 |
|
返回顶楼 | |
发表时间:2010-02-09
执行系统命令其他工具还有Apache Common exec
http://commons.apache.org/exec/ 也很方便,可以跨平台,建议参考一下 |
|
返回顶楼 | |
发表时间:2010-02-09
luanma 写道 执行系统命令其他工具还有Apache Common exec
http://commons.apache.org/exec/ 也很方便,可以跨平台,建议参考一下 这个要顶,楼主莫生气啊. |
|
返回顶楼 | |
发表时间:2010-02-09
hbbbs 写道 谢谢楼主经验介绍... 有点小建议: 1、我们帖子的主题希望能更凸显一下,比如说: a、我们的帖子重点是哪里? b、那段代码的核心部分是几个地方? 2、MD5那块我们可以放在最下面当作附录和你的探索过程,对MD5感兴趣的人将会去看这块。 3、整体代码可以作为附件,有需要的人将会去下载。 呵呵, 同样感谢你的经验分享. 写这个贴子最大的动机是为了记录与整理自己的思路. |
|
返回顶楼 | |
发表时间:2010-02-09
chenlixun 写道 luanma 写道 执行系统命令其他工具还有Apache Common exec http://commons.apache.org/exec/ 也很方便,可以跨平台,建议参考一下 这个要顶,楼主莫生气啊. 哈哈, 没啥的, 哪个好用用哪个. 同样感谢chenlixun的分享, 先收下了, 这个确实没用过. |
|
返回顶楼 | |
发表时间:2010-02-09
luanma 写道 执行系统命令其他工具还有Apache Common exec http://commons.apache.org/exec/ 也很方便,可以跨平台,建议参考一下 嗯, 刚才看了一下介绍, 还是使用了ProcessBuilder类来生成子进程完成系统命令执行的, 但在我这个场合, 主进程里的输入流是没有办法打印到子进程里的输出流上的. 再者, 方法的意图只是想高效率的计算文件的校验码, 不知luanma同学有什么推荐不, 呵呵 |
|
返回顶楼 | |
发表时间:2010-02-09
好帖子
不过我有个问题要请教了 JAVA里如何调用bat脚本文件? 我前段时间在项目中碰到这样的问题,后来公司的一位老师利用VB做了个壳 通过VB传入bat文件的地址作为参数来调用 |
|
返回顶楼 | |
发表时间: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") ; |
|
返回顶楼 | |