将SeqReader打包成可执行的jar包
SeqReader是我定义的一个读取SequenceFile文件,并将部分(key,value)打印到控制台窗口的类,其完整代码如下:
1 /** 2 * Created with IntelliJ IDEA. 3 * User: hadoop 4 * Date: 16-3-14 5 * Time: 上午9:57 6 * To change this template use File | Settings | File Templates. 7 */ 8 import org.apache.hadoop.conf.Configuration; 9 import org.apache.hadoop.fs.FileSystem; 10 import org.apache.hadoop.fs.Path; 11 import org.apache.hadoop.io.SequenceFile; 12 import org.apache.hadoop.io.Writable; 13 import org.apache.hadoop.io.IntWritable; 14 import org.apache.hadoop.io.DoubleWritable; 15 import org.apache.hadoop.io.ArrayWritable; 16 import org.apache.hadoop.util.ReflectionUtils; 17 18 import java.io.IOException; 19 import java.net.URI; 20 21 public class SeqReader { 22 public static void main(String[] args) throws IOException { 23 String uri=args[0]; 24 //String uri="/home/hadoop/2016Test/SeqTest/10IntArray"; 25 Configuration conf=new Configuration(); 26 FileSystem fs =FileSystem.get(URI.create(uri),conf); 27 Path path=new Path(uri); 28 SequenceFile.Reader reader=null; 29 //DoubleWritable[] doubleWritableArray=new DoubleWritable[Integer.parseInt(args[1])]; 30 31 /* for (int i=0;i<doubleWritableArray.length;++i){ 32 doubleWritableArray[i]=new DoubleWritable(0.0); 33 } 34 */ 35 try { 36 reader=new SequenceFile.Reader(fs,path,conf); 37 IntWritable key =(IntWritable) ReflectionUtils.newInstance(reader.getKeyClass(), conf); 38 DoubleArrayWritable value=(DoubleArrayWritable)ReflectionUtils.newInstance(reader.getValueClass(),conf); 39 long position=reader.getPosition(); 40 String[] sValue=null; 41 int index; 42 int counter=0; 43 StringBuilder sb=new StringBuilder(); 44 while(reader.next(key,value)){ 45 if(key.get()%Integer.parseInt(args[1])==0){ 46 System.out.println("key:"+key.get()); 47 index=-1; 48 for (Writable val:value.get()){ 49 //doubleWritableArray[++index].set(((DoubleWritable)val).get()); 50 if (counter>10){ 51 break; 52 } 53 counter++; 54 sb.append(((DoubleWritable)val).get()).append(","); 55 } 56 System.out.println("value:"+sb.toString()); 57 58 } 59 60 } 61 } 62 finally { 63 //IOUtils.closeStream(reader); 64 } 65 } 66 67 } 68 class DoubleArrayWritable extends ArrayWritable { 69 public DoubleArrayWritable(){ 70 super(DoubleWritable.class); 71 } 72 /* 73 public String toString(){ 74 StringBuilder sb=new StringBuilder(); 75 for (Writable val:get()){ 76 DoubleWritable doubleWritable=(DoubleWritable)val; 77 sb.append(doubleWritable.get()); 78 sb.append(","); 79 } 80 sb.deleteCharAt(sb.length()-1); 81 return sb.toString(); 82 } 83 */ 84 }
关于生成可执行jar包,这里只说几点需要注意的地方,详细信息可以参考:http://www.cnblogs.com/lz3018/p/5228639.html
1)首先就是MANIFEST.MF文件的配置,应该保证配置完成之后,文件有一个空白行,使用gedit编辑此文件,打开“显示行号”功能。
前4行是我们配置的有效内容,第5行就是我们文件需要的空白行,第6行是目前准备写入字符的行,此时我们就保存文件,那我们文件内容就是包含有字符的前四行,外加一个空白行,也就是我们文件总共有5行。
2)对于Main-Class,当我们的类中没有定义包名的话,那么只需要写主类名称就可以了。(只有eclipse中采用默认包名就是类名这一说法吧)
3)当我们使用jar cfm SeqWriter.jar MANIFEST.MF *.class重新打jar包之后,使用命令java -jar SeqWriter.jar part-r-00000 1000运行jar包时,提示"NoClassDefFoundError":
也就是找不到类 /org/apache/commons/logging/LogFactorty,这个类是在commons-logging-1.1.1中,我们只需要添加这个jar包就可以了,怎么添加了,就是在MANIFEST.MF文件在添加Class-Path属性,给属性配置这个jar包的路径就可以了(多个jar包用空格分隔),完成上述操作之后,使用jar命令重新生成jar包,再使用java -jar执行jar包,然后又出现如下提示:
还是找不到类,仍然是按照上述方法将commons-configuration-1.6.jar的路径添加到Class-Path中,再重新打包、运行·,如下:
同样的,将comons.lang-2.4.jar的路径添加到Class-Path中,然后重新打包、运行,结果如下所示:
成功运行。