以 Hadoop 权威指南 (第三版) 3.5.2 为例.
import java.io.InputStream; import java.net.URI; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.FileSystem; import org.apache.hadoop.fs.Path; import org.apache.hadoop.io.IOUtils; public class FileSystemCat { public static void main(String[] args) throws Exception { String uri = args[0]; FileSystem fs = FileSystem.get(URI.create(uri), new Configuration()); InputStream in = null; try { in = fs.open(new Path(uri)); IOUtils.copyBytes(int, System.out, 4096, false); } finally { IOUtils.closeStream(in); } } }
代码就不解释了, 主要记录一下环境设置.
环境变量
如果你是参考我的 Wiki 搭建 Hadoop 分布式实验环境 搭建的实验环境, 那环境变量应该是已经配好了.
vim ~/.bashrc
export JAVA_HOME=/usr/java/jdk1.8.0_101 export HADOOP_HOME=/usr/smallcpp/hadoop-2.7.3 export PATH=$PATH:$JAVA_HOME/bin:$HADOOP_HOME/bin:$HADOOP_HOME/sbin
运行 source ~/.bashrc
刷新环境变量.
Hadoop 类目录
这个类目录的作用是当运行 hadoop 或者 hdfs 的命令时, 命令的搜索目录.
首先到 Hadoop 的根目录下创建一个新目录:
cd /usr/smallcpp/hadoop-2.7.3/
mkdir myclass
然后 vim hadoop-env.sh
设置 HADOOP_CLASSPATH
:
# Extra Java CLASSPATH elements. Automatically insert capacity-scheduler. export HADOOP_CLASSPATH=/usr/smallcpp/hadoop-2.7.3/myclass for f in $HADOOP_HOME/contrib/capacity-scheduler/*.jar; do if [ "$HADOOP_CLASSPATH" ]; then export HADOOP_CLASSPATH=$HADOOP_CLASSPATH:$f else export HADOOP_CLASSPATH=$f fi done
这样当执行 hdfs FileSystemCat
的时候, 就会去 /usr/smallcpp/hadoop-2.7.3/myclass
找我们写好的 FileSystemCat
应用了.
编译源码
要将 Java 源码文件编译成 .class
文件才能被 Hadoop 识别, 编译 Hdfs 应用需要导入 Hadoop 的 jar 包, 这些包位于以下目录:
- /usr/smallcpp/hadoop-2.7.1/share/hadoop/common
- /usr/smallcpp/hadoop-2.7.1/share/hadoop/common/lib
- /usr/smallcpp/hadoop-2.7.1/share/hadoop/hdfs
- /usr/smallcpp/hadoop-2.7.1/share/hadoop/hdfs/lib
我们这里的例子用到的是 /usr/smallcpp/hadoop-2.7.3/share/hadoop/common/hadoop-common-2.7.3.jar
包, 执行 javac
命令时用 -cp
指定下就好.
javac -cp /usr/smallcpp/hadoop-2.7.3/share/hadoop/common/hadoop-common-2.7.3.jar FileSystemCat.java
然后 /usr/smallcpp/hadoop-2.7.3/myclass
下就多了个 FileSystemCat.class
文件.
这时执行 hdfs FileSystemCat /xxx
就能查看到 xxx
文件的内容啦, 类似 linux 的 cat
命令.
ant
由于编译源码时需要指定 Hadoop 的 jar 包, 当引入的 jar 包多时, 这样就特别麻烦, 我们可以借用 ant 工具来编译源码, ant 可以在 bulid.xml
中设定 jar 包的所在目录, 这样就比较方便了.
这里仅作介绍, 因为我是使用 Eclipse 进行开发的, 导入 jar 包相对于说, 还是比较方便的.
其他例子
例 1
读入本地文件系统一个大约一百多字节的文本文件, 并将其第 101-120 字节的内容写入 HDFS 成为一个新文件.
import java.io.BufferedInputStream; import java.io.FileInputStream; import java.io.InputStream; import java.io.OutputStream; import java.net.URI; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.FileSystem; import org.apache.hadoop.fs.Path; import org.apache.hadoop.io.IOUtils; public class CopyLocalToHdfs { public static void main(String[] args) throws Exception { String local_uri = args[0]; String hdfs_uri = args[1]; InputStream in = new BufferedInputStream(new FileInputStream(local_uri)); in.skip(100); FileSystem fs = FileSystem.get(URI.create(hdfs_uri), new Configuration(), "martin"); OutputStream out = fs.create(new Path(hdfs_uri)); IOUtils.copyBytes(in, out, (long)20, true); } }
例 2
例 1 的反向操作, 读入 HDFS 文件系统一个大约一百多字节的文本文件, 并将其第 101-120 字节的内容写入本地文件系统成为一个新文件.
import java.io.BufferedOutputStream; import java.io.FileOutputStream; import java.io.InputStream; import java.io.OutputStream; import java.net.URI; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.FileSystem; import org.apache.hadoop.fs.Path; import org.apache.hadoop.io.IOUtils; public class CopyHdfsToLocal { public static void main(String[] args) throws Exception { String hdfs_uri = args[0]; String local_uri = args[1]; FileSystem fs = FileSystem.get(URI.create(hdfs_uri), new Configuration(), "martin"); InputStream in = fs.open(new Path(hdfs_uri)); in.skip(100); OutputStream out = new BufferedOutputStream(new FileOutputStream(local_uri)); IOUtils.copyBytes(in, out, (long)20, true); } }
使用 Eclipse 开发 Hdfs 应用
参考我的 Wiki: 使用 Eclipse 开发 HDFS