一、Maven 安装配置
我使用 Eclipse 及 Maven 作为编程环境,Eclipse 的安装比较简单,只需要下载解压即可,现在来安装 Maven。
1. 下载解压:
我在这里选择3.3.9版本,解压到 /opt/maven 目录下,此时 Maven 的主目录就是 /opt/maven/apache-maven-3.3.9
2. Maven 下载配置
Maven 默认下载库使用的是国外的镜像,速度比较慢,因此需要选择在配置文件中改为国内的镜像。
打开 /opt/maven/apache-maven-3.3.9/conf 目录下的 settings.xml 文件,在 <mirrors> 标签中添加如下镜像:
<!-- 阿里云仓库 -->
<mirror>
<id>alimaven</id>
<mirrorOf>central</mirrorOf>
<name>aliyun maven</name>
<url>http://maven.aliyun.com/nexus/content/repositories/central/</url>
</mirror>
<!-- 中央仓库1 -->
<mirror>
<id>repo1</id>
<mirrorOf>central</mirrorOf>
<name>Human Readable Name for this Mirror.</name>
<url>http://repo1.maven.org/maven2/</url>
</mirror>
<!-- 中央仓库2 -->
<mirror>
<id>repo2</id>
<mirrorOf>central</mirrorOf>
<name>Human Readable Name for this Mirror.</name>
<url>http://repo2.maven.org/maven2/</url>
</mirror>
3. 系统配置
使用 vi 或者 gedit 修改系统的配置文件,我这里使用 gedit:
$ sudo gedit /etc/profile
在该文件最后添加:
# Maven
export MAVEN_HOME=/opt/maven/apache-maven-3.3.9
export PATH=$PATH:$MAVEN_HOME/bin
使用 source 命令使配置文件的修改生效:
$ source /etc/profile
此时可以使用 Maven 命令检查是否安装成功:
$ mvn -v
安装成功结果如下:
4. Eclipse 中配置 Maven
Eclipse 中选择 Window->Preferences 中的 Maven
首先在 Installations 中将 Maven 的目录改为刚刚手动安装的 Maven3.3.9:
之后在 User Settings 中修改配置文件的目录为我们自己安装的 Maven 的配置文件,将两处的配置文件目录都修改为 /opt/maven/apache-maven-3.3.9/conf/settings.xml, Loacl Repository 为 Maven 下载的库的目录,这里使用默认目录。
5. 新建 Maven 项目并添加 Hadoop 依赖
在 Eclipse 中 File->new->Maven Project,点击两次 next,填写包名及项目名:
选择项目中的 pom.xml,在 <dependencies> 中添加如下标签,此时 Maven 会自动去下载标签中的库,也就是 Hadoop2.5.0 对应的 Java 库。
<!-- https://mvnrepository.com/artifact/org.apache.hadoop/hadoop-client -->
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-client</artifactId>
<version>2.5.0</version>
<scope>compile</scope>
</dependency>
二、Java 操作 HDFS
简介
本地访问 HDFS 最主要的方式是 HDFS 提供的 Java 应用程序接口,其他的访问方式都是建立在这些应用程序接口之上。为了访问 HDFS,HDFS 客户端必须拥有一份 HDFS 的配置文件 hfds-site.xml 来获取 NameNode 的相关信息。
Java程序
1. 读取 HDFS 中的文件
创建类 HDFSCat 用于读取 HDFS 文件系统中的文件内容并打印在控制台。
代码中使用 static 静态代码块执行 URL.setURLStreamHandlerFactory(new FsUrlStreamHandlerFactory()),该段代码的作用是让 Java 程序可以识别 Hadoop 的 HDFS url。静态代码块会随着类的加载而执行并只执行一次,它的执行优于主函数。
在主函数中,代码使用 InputStream 读取文件流,并使用 IOUtils 中的 copyBytes 函数将文件内容打印到控制台,false 表示操作结束后不关闭文件流。
完整代码如下:
public class HDFSCat {
static {
URL.setURLStreamHandlerFactory(new FsUrlStreamHandlerFactory());
}
public static void main(String[] args) {
InputStream inputStream = null;
try {
String url = "hdfs://localhost:9000/datas/test/mapred/example1/test_input";
inputStream = new URL(url).openStream();
IOUtils.copyBytes(inputStream, System.out, 4096, false);
} catch (Exception e) {
e.printStackTrace();
} finally {
IOUtils.closeStream(inputStream);
}
}
}
2. 使用 FileSystem 读取文件内容
Hadoop 库中的 Configuration 和 FileSystem 这两个类可以用来操作 HDFS 文件系统,Configuration 会从项目的 Resources 文件中读取 HDFS 的配置。因此我们需要将 Hadoop 的配置文件放入到项目中。
在项目上右击 new->source folder,在 src/main 下新建一个存放配置文件的文件夹 resources,如下所示:
之后将 core-site.xml 以及 hdfs-site.xml 拷贝到该文件夹内,最后的项目结构如下:
配置完成之后就可以使用 FileSystem 来读取文件了,只不过这次是通过 FileSystem 的对象来获取文件流,该类的 open() 方法返回 Hadoop 独有的 FSDataInputStream 对象。
public class FSCat {
public static void main(String[] args) throws IOException {
Configuration conf = new Configuration();
FileSystem fs = FileSystem.get(conf);
InputStream in = null;
try {
String uri = "hdfs://localhost:9000/datas/test/mapred/example1/test_input";
in = fs.open(new Path(uri));
IOUtils.copyBytes(in, System.out, 4096, false);
} finally {
IOUtils.closeStream(in);
}
}
}
3. 使用 FileSystem 向 HDFS 中写入文件
这里使用 InputStream 读取 Linux 文件流并输出到 HDFS 文件中,在读取文件的时候使用 BufferedInputStream 而不是 FileInputStream,因为使用 FileInputStream 时会频繁地访问磁盘,读取时效率较低。而是用 BufferedInputStream 时,该类会创建一个内部缓冲数组,在读取流中的字节时,可以根据需要从包含的输入流中填充内部缓冲区,一次填充多个字节。
public class CopyFileToHDFS {
public static void main(String[] args) throws IOException {
Configuration conf = new Configuration();
FileSystem fs = FileSystem.get(conf);
String source = "/opt/source";
String destination = "hdfs://localhost:9000/user/destination";
InputStream inputStream = new BufferedInputStream(
new FileInputStream(source));
OutputStream outputStream = fs.create(new Path(destination));
// 将 Linux 中的 source 文件拷贝到 HDFS 的 destination
// true 表示操作结束后自动关闭文件流,因此不需要手动关闭
IOUtils.copyBytes(inputStream, outputStream, 4096, true);
}
}
运行成功后去 HDFS 下查看 /user 目录,会发现多了 destination 文件。
4. 创建目录
public class CreateFolder {
public static void main(String[] args) throws IOException {
Configuration conf = new Configuration();
FileSystem fs = FileSystem.get(conf);
Path path = new Path("hdfs://localhost:9000/datas/new_folder");
fs.mkdirs(path);
}
}
5. 删除文件或目录
delete() 方法中如果传入 false 表示删除一个文件,如果传入 true 表示递归删除文件夹及文件。
public class DeleteFile {
public static void main(String[] args) throws IOException {
Configuration conf = new Configuration();
FileSystem fs = FileSystem.get(conf);
Path deletePath = new Path("/user/destination");
boolean isDeleted = fs.delete(deletePath, false);
System.out.println("result: " + isDeleted);
}
}
6. 列出目录下的文件或目录名
public class ListeFiles {
public static void main(String[] args) throws IOException {
Configuration conf = new Configuration();
FileSystem fs = FileSystem.get(conf);
String uri = "hdfs://localhost:9000/datas/test/mapred";
Path path = new Path(uri);
FileStatus[] status = fs.listStatus(path);
for (FileStatus fileStatus : status) {
System.out.println(fileStatus.getPath().toString());
}
fs.close();
}
}