目录
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
统计文件夹大小信息