简介
在部署了Hadoop机器的服务器上, 可以直接使用hadoop相关命令操作HDFS文件系统,参考 hadoop命令;或者编写可用hadoop命令执行的代码打成jar包,在服务器上运行。
本文主要介绍如何利用Java API 在Windows或未进行Hadoop部署的Linux环境远程访问Hadoop的HDFS系统。
Jar包依赖
- hadoop-hdfs
- hadoop-common
- hadoop-client
// Spring 依赖示例
dependencies {
compile('org.apache.hadoop:hadoop-hdfs:3.1.0')
compile('org.apache.hadoop:hadoop-common:3.1.0')
compile('org.apache.hadoop:hadoop-client:3.1.0')
}
Java API远程访问
实现功能将本地文件存储到hdfs,拷贝hdfs文件到本地,示例代码如下:
package com.notepad.hdfs;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IOUtils;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.URI;
/**
* Description: Hdfs远程访问示例
* <p>
* Create: 2018/6/21 23:59
*
* @author Yang Meng([email protected])
*/
public class HdfsProcess {
/**
* 构造FileSystem
*
* @return true, 构造成果
* @throws Exception 构造异常
*/
public boolean load() throws Exception {
Configuration conf = new Configuration();
conf.set("fs.hdfs.impl", "org.apache.hadoop.hdfs.DistributedFileSystem");
fileSystem = FileSystem.get(new URI(HDFS_URI), conf, USER);
return fileSystem != null;
}
/**
* 根据指定的hdfs路径创建hdfs目录
*
* @param hdfsDir 指定的hdfs目录
* @return true, hdfs目录构造完成
* @throws Exception 构造异常
*/
public boolean makeDir(Path hdfsDir) throws Exception {
return fileSystem.exists(hdfsDir) || fileSystem.mkdirs(hdfsDir);
}
/**
* 本地文件存储到hdfs目录
* 示例:
* String localFile = "D:\\log\\text.demo";
* String hdfsDir = "/test/";
*
* // 存储为hdfs://xxx/test/text.demo
* put(localFile, hdfsDir);
*
* @param localFile 本地文件路径
* @param hdfsDir hdfs目录
* @return true, 存储
* @throws Exception 导入异常
*/
public boolean put(String localFile, String hdfsDir) throws Exception {
if (!makeDir(new Path(hdfsDir))) {
return false;
}
File local = new File(localFile);
if (!local.isFile()) {
return false;
}
fileSystem.copyFromLocalFile(new Path(localFile), new Path(hdfsDir + "/" + local.getName()));
return true;
}
/**
* hdfs目录的文件存储到本地
* 示例:
* String localDir = "D:\\log\\";
* String fileName = "text.demo";
* String hdfsDir = "/test/";
*
* //将hdfs://xxx/test/text.demo存储到本地D:\\log\\
* get(hdfsDir, fileName, localDir);
*
* @param hdfsDir hdfs目录
* @param fileName 指定文件
* @param localDir 本地目录
* @return true, 存储正常
* @throws Exception 存储异常
*/
public boolean get(String hdfsDir, String fileName, String localDir) throws Exception {
InputStream in = fileSystem.open(new Path(hdfsDir + "/" + fileName));
FileOutputStream out = new FileOutputStream(new File(localDir + "/" + fileName));
IOUtils.copyBytes(in, out, 2048, true);
return true;
}
private FileSystem fileSystem;
private static final String HDFS_URI = "hdfs://{host}:{port}/";
private static final String USER = "hdfs";
}
遇到的问题集合
Windows环境报错:failed to locate the winutils binary in the hadoop binary path java.io.IOException: Could not locate executable null\bin\winutils.exe in the hadoop binaryies.
- 问题:缺失winutils.exe
- 解决方法:
下载winutils.exe,并放置在指定位置的bin目录下, 假设为放在D盘”D:\\bin\\”
设置环境变量HADOOP_HOME 或代码中设置路径,System.setProperty("hadoop.home.dir", "D:\\")
Linux环境设置HADOOP_HOME
- 解决方法:
下载hadoop部署包,并设置HADOOP_HOME,修改用户目录下 .bashrc
// .bashrc export HADOOP_HOME="xxx" // shell: 设置生效 $ source ~/.bashrc
- 解决方法:
Linux环境报错:java.io.IOException: No FileSystem for scheme: hdfs
- 解决方法:
构造Configuration时显示设置"org.apache.hadoop.hdfs.DistributedFileSystem"
类
// 构造Configuration Configuration conf = new Configuration(); conf.set("fs.hdfs.impl", "org.apache.hadoop.hdfs.DistributedFileSystem");
- 解决方法:
报错:Exception in thread “main” java.net.ConnectException: Call From xx to yy
- 解决方法
利用HDFS的URI构造FileSystem
URI: 参考hadoop的部署文件hdfs-site. xml中 “dfs.namenode.rpc-address”前缀的property对应的值作为uri。
//hdfs uri URI hdfsUri = new URI("hdfs://{host}:{port}/"); //无user FileSystem fileSystem = FileSystem.get(hdfsUri, new Configuration())); //有user: 针对有user的需设置user, 否则会报出无访问权限的错误 String user = "HDFS" FileSystem userFileSystem = FileSystem.get(hdfsUri, new Configuration()), user);
- 解决方法