目錄
org.apache.hadoop.fs.FileSystem
org.apache.hadoop.fs.FileStatus
org.apache.hadoop.fs.FSDataInputStream
org.apache.hadoop.fs.FSDataOutputStream
準備工作
使用開發工具爲idea
1.需要將hadoop的hdfs-site.xml, core-site.xml這兩個配置文件拷貝到項目的resources目錄下
2.需要在maven中引入
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-client</artifactId>
<version>2.7.3</version>
</dependency>
HDFS API的使用
org.apache.hadoop.fs.FileSystem
抽象類,定義了文件系統訪問的一般步驟。涉及到具體要訪問什麼樣的文件系統,由其子類實現
比方說分佈式文件系統,本地文件系統等等,其子類如下
org.apache.hadoop.fs.Path
用於創建一個路徑,來表示一個文件或目錄。可以是普通的文件路徑,也可以是URI
org.apache.hadoop.fs.FsStatus
表示文件系統的存儲空間使用情況
org.apache.hadoop.fs.FileStatus
表示文件的相關屬性
org.apache.hadoop.fs.FSDataInputStream
讀入HDFS系統的文件接口
org.apache.hadoop.fs.FSDataOutputStream
向HDFS系統寫入文件
示例
@Test
// 讀數據
public void test() throws IOException {
/**
* 加載配置文件
*
* * 底層會加載一堆的配置文件:
* *
* * core-default.xml
* * hdfs-default.xml
* * mapred-default.xml
* * yarn-default.xml
*
* * 當前這個hdfs-site.xml文件就放置在這個項目中的src下。也就是classpath路徑下。
* * 所以 FS在初始化的時候,會把hdfs-site.xml這個文件中的name-value對解析到conf中
* * 但是:
* * 1、如果hdfs-site.xml 不在src下, 看是否能加載??? 不能
* * 2、如果文件名不叫做 hdfs-default.xml 或者 hdsf-site.xml 看是否能自動加載??? 不能
* * 得出的結論:
* * 如果需要項目代碼自動加載配置文件中的信息,那麼就必須把配置文件改成-default.xml或者-site.xml的名稱
* * 而且必須放置在src下
* *
* * 那如果不叫這個名,或者不在src下,也需要加載這些配置文件中的參數:
* * 必須使用conf對象提供的一些方法去手動加載
* conf.set("dfs.replication", "2"); #注意所有的值都是以字符串的形式傳入
*/
Configuration conf = new Configuration();
//代碼入口點,初始化hdfs文件系統
FileSystem fs = FileSystem.get(conf);
//通過fs讀數據
Path p = new Path("/user/centos/user");
FSDataInputStream fis = fs.open(p);
// 讀取文件
int len = 0;
byte[] buff = new byte[1024];
while((len = fis.read(buff)) != -1) {
System.out.println(new String(buff,0,len));
}
}
@Test
//出現 winutil問題
// 寫入文件
// 對hdfs的操作會更改namenode信息時,就會涉及到權限問題
//* 更改操作用戶有兩種方式:
// * 1、直接設置運行的用戶名爲hadoop
// * VM arguments ; -D HADOOP_USER_NAME=admin
// * 2、在代碼中進行聲明
// * System.setProperty("HADOOP_USER_NAME", "admin");
public void test2() throws Exception{
// 設置操作的用戶名,防止出現權限問題
System.setProperty("HADOOP_USER_NAME", "centos");
Configuration conf = new Configuration();
FileSystem fs = FileSystem.get(conf);
Path p = new Path("/user/centos/t4.txt");
FSDataOutputStream out = fs.create(p);
out.write("the people's republic of china".getBytes());
out.flush();
out.close();
}
@Test
// 向已經存在的文件,追加新內容
public void test3() throws Exception{
System.setProperty("HADOOP_USER_NAME", "centos");
Configuration conf = new Configuration();
FileSystem fs = FileSystem.get(conf);
Path p = new Path("/user/centos/t4.txt");
FSDataOutputStream append = fs.append(p);
append.write("\n i love this computer! it's has big power.".getBytes());
append.flush();
append.close();
}
@Test
// 刪除文件
public void test4() throws Exception {
System.setProperty("HADOOP_USER_NAME", "centos");
Configuration conf = new Configuration();
FileSystem fs = FileSystem.get(conf);
Path p = new Path("/user/centos/tt");
// recursive 這個參數設爲爲true, 遞歸的刪除它的子目錄
// 爲false時如果該目錄下有內容會報錯
fs.delete(p, true);
fs.close();
}
@Test
// 把hdfs內的文件複製到本地,或者說是下載文件
public void test5() throws Exception {
Configuration conf = new Configuration();
FileSystem fs = FileSystem.get(conf);
Path p = new Path("/user/centos/t4.txt");
FSDataInputStream in = fs.open(p);
FileOutputStream out = new FileOutputStream("g:/mr/tt.txt");
IOUtils.copyBytes(in, out, 1024);
in.close();
out.close();
fs.close();
}
@Test
/**
* 遞歸列出指定目錄內的內容
*/
public void test6() throws Exception {
System.setProperty("HADOOP_USER_NAME", "centos");
Configuration conf = new Configuration();
FileSystem fs = FileSystem.get(conf);
listDF(fs, new Path("/"));
fs.close();
}
public void listDF(FileSystem fs, Path path) throws IOException {
FileStatus[] statuses = fs.listStatus(path);
for(FileStatus status : statuses) {
if(status.isFile()) {
System.out.println(status.getPath());
} else {
listDF(fs, status.getPath());
}
}
}
@Test
/**
* 測試配置的優先級
* 1)客戶端代碼中設置的值 >(2)classpath下的用戶自定義配置文件 >(3)然後是服務器的默認配置
*/
public void test7() throws IOException {
System.setProperty("HADOOP_USER_NAME", "centos");
Configuration conf = new Configuration();
conf.set("dfs.replication", "2");
FileSystem fs = FileSystem.get(conf);
Path p = new Path("/user/centos/t10.txt");
FSDataOutputStream out = fs.create(p);
out.write("the people's republic of china".getBytes());
out.flush();
out.close();
}
@Test
/**
* 列出指定目錄下的文件及其塊信息
*/
public void test8() throws IOException {
System.setProperty("HADOOP_USER_NAME", "centos");
Configuration conf = new Configuration();
FileSystem fs = FileSystem.get(conf);
Path path = new Path("/user/centos");
RemoteIterator<LocatedFileStatus> fsInfo = fs.listFiles(path, true);
while(fsInfo.hasNext()) {
LocatedFileStatus file = fsInfo.next();
System.out.println("path:" + file.getPath());
System.out.println("name:" + file.getPath().getName());
System.out.println("len: " + file.getLen());
System.out.println("replication:" + file.getReplication());
BlockLocation[] blockLocations = file.getBlockLocations();
for(BlockLocation bl : blockLocations) {
System.out.println("hosts:" + Arrays.toString(bl.getHosts()));
}
System.out.println("============================");
}
Path path2 = new Path("/user/centos/t4.txt");
System.out.println(fs.getFileStatus(path2).getLen());
System.out.println(fs.getFileStatus(path2).getReplication());
System.out.println(fs.getFileStatus(path2).getBlockSize());
}
@Test
/**
* 統計hdfs中文件大小小於blocksize的文件佔比
*/
public void test12() {
// fs.getFileStatus(path2).getLen(); 可以直接使用這個查看文件的大小
// fileStatus.getBlockSize() 這個返回的是這個文件的所設定的塊大小
System.setProperty("HADOOP_USER_NAEM", "centos");
Configuration conf = new Configuration();
try {
FileSystem fs = FileSystem.get(conf);
FileStatus[] fileStatuses = fs.listStatus(new Path("/"));
Queue<FileStatus> queue = new LinkedList<>();
queue.addAll(Arrays.asList(fileStatuses));
// 統計有多少個文件塊
int countBlock1 = 0;
// 統計少於文件塊大小的塊
int countBlock2 = 0;
FileStatus fileStatus = null;
while ((fileStatus = queue.poll()) != null) {
try {
if (fileStatus.isDirectory()) {
queue.addAll(Arrays.asList(fs.listStatus(fileStatus.getPath())));
} else if (fileStatus.isFile()) {
System.out.println("file name: " + fileStatus.getPath() + ", size: " + fileStatus.getLen()/(1024*1024) + " mb");
BlockLocation[] fileBlockLocations = fs.getFileBlockLocations(fileStatus, 0, fileStatus.getLen());
for(BlockLocation bl : fileBlockLocations) {
countBlock1 ++;
if(bl.getLength() < fileStatus.getBlockSize()) {
countBlock2++;
}
}
}
} catch (Exception e) {
}
}
System.out.println("scale: " + (double)countBlock2 / countBlock1);
} catch (Exception e) {
}
}
@Test
/**
* 統計系統中文件的平均副本數
*/
public void test13() {
System.setProperty("HADOOP_USER_NAME", "centos");
Configuration conf = new Configuration();
int totalFile = 0;
int totalReplication = 0;
try {
FileSystem fs = FileSystem.get(conf);
// 剛開始因爲,hadoop的用戶名設置錯誤,導致這裏獲取不到信息
RemoteIterator<LocatedFileStatus> listStatusIter = fs.listFiles(new Path("/"), true);
while(listStatusIter.hasNext()) {
LocatedFileStatus fileStatus = listStatusIter.next();
if(fileStatus.isFile()) {
totalFile++;
totalReplication += fileStatus.getReplication();
}
}
} catch (Exception e) {
} finally {
if(totalFile != 0)
System.out.println("average replication : " + totalReplication / totalFile);
}
}
@Test
/**
* 統計系統中文件的平均block
*/
public void test14() {
System.setProperty("HADOOP_USER_NAME", "centos");
Configuration conf = new Configuration();
int totalFile = 0;
int totalBlock = 0;
try {
FileSystem fs = FileSystem.get(conf);
RemoteIterator<LocatedFileStatus> fileStatusIter = fs.listFiles(new Path("/"), true);
while(fileStatusIter.hasNext()) {
LocatedFileStatus fileStatus = fileStatusIter.next();
if(fileStatus.isFile()) {
totalBlock += fileStatus.getBlockLocations().length;
System.out.println(fileStatus.getBlockLocations().length);
totalFile ++;
}
}
} catch (Exception e) {
} finally {
if(totalFile != 0) {
System.out.println("average block " + (double)totalBlock / totalFile);
}
}
}
/**
* 統計HDFS整個文件系統中的不足指定數據塊大小的數據塊的比例
*
*
*/
@Test
public void test15() {
System.setProperty("HADOOP_USER_NAME", "centos");
Configuration conf = new Configuration();
int totalBlock = 0;
int count = 0;
try {
FileSystem fs = FileSystem.get(conf);
RemoteIterator<LocatedFileStatus> fileStatusIter = fs.listFiles(new Path("/"), true);
while(fileStatusIter.hasNext()) {
LocatedFileStatus fileStatus = fileStatusIter.next();
if(fileStatus.isFile()) {
totalBlock += fileStatus.getBlockLocations().length;
for(BlockLocation bl : fileStatus.getBlockLocations()) {
if(bl.getLength() < fileStatus.getBlockSize()) {
count ++;
}
}
}
}
} catch (Exception e) {
} finally {
System.out.println((double)count / totalBlock);
}
}
常用客戶端命令
0.直接在命令行,輸入hadoop, hadoop fs, hdfs fs
都會給出相應的命令提示
1. hadoop fs 與 hdfs dfs 等價
列出hdfs 文件操作的所有相關命令
2. hadoop fs -help command-name
列出某個命令的幫助信息
3. hadoop fs -ls direct-path
列出某個目錄內下的內容
4. hadoop fs -mkdir /data
在hdfs上創建目錄
5. hadoop fs -moveFromLocal source dest
將本地文件移到hdfs上
hadoop fs -copyFromLocal source dest
將本地文件拷貝到hdfs上
hadoop fs -copyToLocal source dest
拷貝hdfs文件到本地
hadoop fs -cp source dest
在hdfs上拷貝文件到系統的其他目錄
hadoop fs -mv source dest
在hdfs上移動文件到系統的其他目錄
hadoop fs -get source dest
下載hdfs文件到本地
hadoop fs -getmerge source dest
下載多個hdfs文件到本地,且只生成一個文件
hadoop fs -put source dest
上傳本地文件到hdfs
hadoop fs -rm filename
刪除hdfs上的某個文件
hadoop fs -rmdir direct-name
刪除文件夾
6. hadoop fs -cat /centos/hello.txt
查看hdfs上的文件
7. hadoop fs -appendToFile source dest
追加文件到原有的文件
如果目標文件不存在會創建
9. hadoop fs -tail /centos/hello
顯示一個文件末尾
10. hadoop fs -chmode 777 /centos/hello
修改權限
11. hadoop fs -chown root:root /centos/hello
修改文件所有者
12. hadoop fs -df -h path
統計hdfs 文件系統可用空間信息
13. hadoop fs -du -h path
統計文件夾大小信息