hdfs在生產應用中主要是針對客戶端的開發,從hdfs提供的api中構造一個HDFS的訪問客戶端對象,然后通過該客戶端對象操作(增刪改查)HDFS上的文件。
搭建開發環境
方式一(windows環境下):
1、將官網下載的hadoop安裝包解壓,並記住下圖所示的目錄
2、創建java project,右鍵工程--->build path--->Configure build path
3、進行如下圖操作
4、進行如下圖操作
5、導入jar包(圖示目錄下的common包以及lib目錄下的所有包 還有hdfs包以及其lib目錄下的所有jar包)
6、配置環境變量
7、重要!重要!重要!!!
將安裝包下的lib和bin目錄用對應windows版本平台編譯的本地庫替換(編譯源碼包可自行百度一下相關步驟,或是直接下載別人編譯好的bin和lib)
方式二:
1、創建maven項目
2、將maven項目的JRE換成自己機器上的1.7(默認是1.5的版本)
3、寫入pom文件
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.xiaojie</groupId>
<artifactId>hdfs</artifactId>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
<!-- <hadoop.version>2.6.5</hadoop.version> -->
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-common</artifactId>
<version>2.6.5</version>
</dependency>
<dependency>
<groupId>jdk.tools</groupId>
<artifactId>jdk.tools</artifactId>
<version>1.7</version>
<scope>system</scope>
<systemPath>${JAVA_HOME}/lib/tools.jar</systemPath>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-hdfs</artifactId>
<version>2.6.5</version>
</dependency>
</dependencies>
</project>
上傳文件
package hadoop;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URI;
import java.util.Iterator;
import java.util.Map.Entry;
import org.apache.commons.io.IOUtils;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.BlockLocation;
import org.apache.hadoop.fs.FSDataInputStream;
import org.apache.hadoop.fs.FileStatus;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.LocatedFileStatus;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.fs.RemoteIterator;
import org.junit.Before;
import org.junit.Test;
public class HdfsClientDemo {
FileSystem fs = null;
Configuration conf = null;
@Before
public void init() throws Exception{
// new Configuration();的時候,它就會去加載jar包中的hdfs-default.xml
// 然后再加載classpath下的hdfs-site.xml
conf = new Configuration();
/* 如果我們的代碼中沒有指定fs.defaultFS,並且工程classpath下也沒有給定相應的配置,
conf中的默認值就來自於hadoop的jar包中的core-default.xml,默認值為:
file:///,則獲取的將不是一個DistributedFileSystem的實例,而是一個本地文件系統的客戶端對象*/
// 參數優先級: 1、客戶端代碼中設置的值 2、classpath下的用戶自定義配置文件 3、然后是服務器的默認配置
// 我們要訪問的hdfs的URI
conf.set( "fs.defaultFS", "hdfs://192.168.25.13:9000");
// 獲得hdfs文件系統實例對象,以root身份鏈接 java.net.URI
fs = FileSystem.get(new URI("hdfs://192.168.25.13:9000"),conf,"root");
}
// 上傳文件
@Test
public void upload() throws Exception{
fs.copyFromLocalFile(new Path("c:/test.txt"), new Path("/"));
fs.close();
}
// 使用流的方式上傳文件
@Test
public void upload() throws IllegalArgumentException, IOException{
// true表示是否覆蓋原文件
FSDataOutputStream out = fs.create(new Path("/stream.tex"),true);
FileInputStream in = new FileInputStream("c:/test2.txt");
// org.apache.commons.io下的IOUtils
IOUtils.copy(in, out);
}
}
使用hdfs的web工具,查看是否上傳成功
下載文件
注意:
若上面開發環境搭建過程中hadoop報下的bin包和lib包兼容有問題則download()方法會執行失敗(linux下開發不會報錯)。
解決方法1:在自己的windows電腦上編譯hadoop源碼,用編譯后的bin和lib替換。
解決方法2:使用download2()的方法下載。
// 下載文件
@Test
public void download() throws Exception {
fs.copyToLocalFile(new Path("/test2.txt"), new Path("c:/t22.txt"));
fs.close();
}
// 下載文件兼容版
// 以流的方式下載
@Test
public void download2() throws Exception {
FSDataInputStream in = fs.open(new Path("/test2.txt"));
OutputStream out = new FileOutputStream("c:/t23.txt");
// org.apache.commons.io.IOUtils(common中的和hadoop中的IOUtils都可以,有點小差別)
IOUtils.copy(in, out);
}
// 可自定從哪里開始讀以及讀幾個字節,以流的方式
@Test
public void diy() throws IllegalArgumentException, IOException{
FSDataInputStream in = fs.open(new Path("/test2.txt"));
// 指定從哪個字節開始讀
in.seek(5);
FileOutputStream out = new FileOutputStream("c:/t22.txt");
IOUtils.copy(in, out);
// IOUtils.copyLarge(input, output, inputOffset, length)
}
// 指定打印到屏幕,以流的方式
@Test
public void diy2() throws IllegalArgumentException, IOException{
FSDataInputStream in = fs.open(new Path("/test2.txt"));
// 指定從哪個字節開始讀
in.seek(5);
IOUtils.copy(in, System.out);
}
打印配置文件信息
// 打印配置文件
@Test
public void printtConf(){
Iterator<Entry<String, String>> it = conf.iterator();
while(it.hasNext()){
Entry<String, String> ent = it.next();
System.out.println(ent.getKey()+":"+ent.getValue());
}
}
創建目錄
//創建目錄
@Test
public void mkdir() throws IllegalArgumentException, IOException{
// 可遞歸創建目錄,返回值表示是否創建成果
boolean b = fs.mkdirs(new Path("/mkdir"));
System.out.println(b);
}
刪除目錄或文件
// 刪除目錄或文件
@Test
public void delete() throws IllegalArgumentException, IOException{
// true表示遞歸刪除,返回值表示是否刪除成功
boolean b = fs.delete(new Path("/test"), true);
System.out.println(b);
}
打印指定路徑下的文件信息(不含目錄,可遞歸)
// 打印指定路徑下的文件信息
@Test
public void listFile() throws FileNotFoundException, IllegalArgumentException, IOException{
// true表示是否遞歸 返回的是迭代器對象
RemoteIterator<LocatedFileStatus> listFiles = fs.listFiles(new Path("/"), true);
while(listFiles.hasNext()){
LocatedFileStatus file = listFiles.next();
System.out.println("owner:"+file.getOwner());
System.out.println("filename:"+file.getPath().getName());
System.out.println("blocksize:"+file.getBlockSize());
System.out.println("replication:"+file.getReplication());
System.out.println("permission:"+file.getPermission());
BlockLocation[] blockLocations = file.getBlockLocations();
for (BlockLocation b : blockLocations) {
System.out.println("塊的起始偏移量:"+b.getOffset());
System.out.println("塊的長度:"+b.getLength());
String[] hosts = b.getHosts();
for (String host : hosts) {
System.out.println("塊所在的服務器:"+host);
}
}
System.out.println("=========================================");
}
}
打印指定路徑下的目錄或文件信息(不可遞歸)
// 打印指定路徑下的文件或目錄
@Test
public void list() throws FileNotFoundException, IllegalArgumentException, IOException{
// 返回的是數組,不能遞歸目錄中的內容
FileStatus[] listStatus = fs.listStatus(new Path("/"));
for(FileStatus fs: listStatus){
System.out.println((fs.isFile()?"file:":"directory:")+fs.getPath().getName());
}
}