之前已經(jīng)在服務(wù)器上安裝好了hadoop,下面紀(jì)錄下用java操作hdfs和中間遇到的一些問題,使用的是分布式模式
hdfs的介紹此處不贅述,可以自己去查閱相關(guān)資料進(jìn)行了解
一 本地配置hadoop環(huán)境變量
此處默認(rèn)已經(jīng)具備jdk環(huán)境.
將hadoop的壓縮包解壓到任意目錄
在環(huán)境變量中配置HADOOP_HOME變量,值為hadoop所在的目錄
打開cmd窗口,在其中輸入hadoop version
,出現(xiàn)如下界面即為環(huán)境變量配置成功
二 建立項(xiàng)目
我使用的ide是idea,采用maven來管理項(xiàng)目.
建立好maven項(xiàng)目之后,在pom文件下引入下述依賴.
<!--hadoop 通用依賴-->
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-common</artifactId>
<version>2.9.0</version>
</dependency>
<!--hadoop hdfs依賴-->
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-hdfs</artifactId>
<version>2.9.0</version>
</dependency>
<!--hadoop 客戶端依賴-->
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-client</artifactId>
<version>2.9.0</version>
</dependency>
三 編寫測(cè)試類及解決遇到的問題
新建一個(gè)java文件,HdfsTest.java
package com.example.hadoopdemo.hdfs;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.fs.permission.FsPermission;
import org.junit.Test;
import java.io.IOException;
public class HdfsTest {
/**
* 測(cè)試在hdfs文件系統(tǒng)中
*/
@Test
public void testHdfsCreateDir() throws IOException {
//創(chuàng)建配置對(duì)象
Configuration conf = new Configuration();
//設(shè)置文件系統(tǒng)
conf.set("fs.defaultFS","hdfs://hadoop01:8020/");
try {
//獲取文件系統(tǒng)
FileSystem fileSystem = FileSystem.get(conf);
} catch (IOException e) {
e.printStackTrace();
}
//新建path對(duì)象
Path path = new Path("/data");
//創(chuàng)建path對(duì)象所對(duì)應(yīng)的目錄
fileSystem.mkdirs(path, FsPermission.getDefault());
}
}
運(yùn)行上面的測(cè)試方法,發(fā)現(xiàn)報(bào)了如下錯(cuò)誤
這是因?yàn)樵诒镜剡\(yùn)行hadoop程序需要依賴一些依賴庫和工具類,hadoop 2.9.0的依賴版本可以從下面百度云鏈接中下載
鏈接:https://pan.baidu.com/s/1-hmTd7avPFpR8DK3GRgIBg 密碼:tcnw
下載完成后根據(jù)本機(jī)的位數(shù)選擇對(duì)應(yīng)的版本
將其中的所有文件都放到hadoop的bin目錄下
此時(shí)在運(yùn)行發(fā)現(xiàn)又報(bào)了錯(cuò),錯(cuò)誤信息如下
這是因?yàn)槲襤adoop文件系統(tǒng)是用用戶hadoop進(jìn)行初始化的,而我本地windows的用戶并不是hadoop,所以沒有權(quán)限操作這個(gè)文件系統(tǒng)
解決辦法如下:
一 是配置環(huán)境變量,HADOOP_USER_NAME,值為用戶名,為hadoop
二 是在程序運(yùn)行時(shí)加jvm參數(shù) -DHADHOOP_USER_NAME=hadoop
三 是使用get的重載方法,直接提供用戶名
此時(shí)再運(yùn)行測(cè)試方法,可以看到運(yùn)行成功
這時(shí)我們?nèi)シ?wù)器上執(zhí)行一下hadoop dfs -ls -R /
可以看到文件夾創(chuàng)建成功
四 基本的hdfs操作
下面貼出一些hdfs基本操作
package com.example.hadoopdemo.hdfs;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.*;
import org.apache.hadoop.fs.permission.FsPermission;
import org.junit.Test;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class HdfsTest {
/**
* 靜態(tài)初始化配置對(duì)象和文件系統(tǒng)對(duì)象
*/
private static Configuration conf;
static FileSystem fileSystem;
static {
conf = new Configuration();
conf.set("fs.defaultFS", "hdfs://hadoop01:8020/", "aaaa");
try {
fileSystem = FileSystem.get(conf);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 創(chuàng)建目錄
*
* @throws IOException
*/
@Test
public void testHdfsCreateDir() throws IOException {
Path path = new Path("/data");
fileSystem.mkdirs(path, FsPermission.getDefault());
}
/**
* 創(chuàng)建文件
*
* @throws IOException
*/
@Test
public void testHdfsCreateFile() throws IOException {
Path path = new Path("/data/hello.txt");
FSDataOutputStream fos = fileSystem.create(path);
fos.write("你好".getBytes());
fos.close();
}
/**
* 讀取文件內(nèi)容
*
* @throws IOException
*/
@Test
public void testHdfsReadFile() throws IOException {
Path path = new Path("/data/hello.txt");
FSDataInputStream fis = fileSystem.open(path);
byte[] buffer = new byte[1024];
fis.read(buffer);
System.out.println(new String(buffer));
}
/**
* 獲取文件信息
*
* @throws IOException
*/
@Test
public void testHdfsGetFileStatus() throws IOException {
Path path = new Path("/data/hello.txt");
FileStatus fileStatus = fileSystem.getFileStatus(path);
//fileStatus下有很多get方法獲取文件的基礎(chǔ)屬性,下面列出幾個(gè)
//獲取文件擁有者
String owner = fileStatus.getOwner();
//是否是目錄
boolean isDirectory = fileStatus.isDirectory();
//是否是文件
boolean isFile = fileStatus.isFile();
//文件大小
long len = fileStatus.getLen();
System.out.println("文件擁有者:" + owner);
System.out.println("是否是目錄:" + isDirectory);
System.out.println("是否是文件:" + isFile);
System.out.println("文件大小:" + len);
}
/**
* 通過反射獲取文件的所有可獲取的屬性
*
* @throws IOException
*/
@Test
public void testHdfsReflectGetFileStatus() throws IOException, InvocationTargetException,IllegalAccessException {
Path path = new Path("/data/hello.txt");
FileStatus fileStatus = fileSystem.getFileStatus(path);
Class<? extends FileStatus> fileStatusClass = fileStatus.getClass();
Method[] methods = fileStatusClass.getMethods();
//如果path不是symbolic的話 調(diào)用getSymbolic方法會(huì)報(bào)錯(cuò),所以排除下
for (Method method : methods) {
String name = method.getName();
if (name.startsWith("get") && !name.equals("getSymlink")) {
Object result = method.invoke(fileStatus);
System.out.println(name.substring(3) + ":" + result);
} else if(name.startsWith("is")){
Object result = method.invoke(fileStatus);
System.out.println(name + ":" + result);
}
}
}
}