在这里总结了一下使用java对HDFS上文件的操作,比如创建目录、上传下载文件、文件改名、删除……
首先对一些类名、变量名做出解释说明:
-
FileSystem
: 文件系统的抽象基类
FileSystem的实现取决于fs.defaultFS的配置!有两种实现!
LocalFileSystem: 本地文件系统 fs.defaultFS=file:///
DistributedFileSystem: 分布式文件系统 fs.defaultFS=hdfs://xxx:9000声明用户身份:
FileSystem fs = FileSystem.get(new URI("hdfs://hadoop101:9000"), conf, "atguigu"); -
Configuration
: 功能是读取配置文件中的参数Configuration在读取配置文件的参数时,根据文件名,从类路径按照顺序读取配置文件!
先读取 xxx-default.xml,再读取xxx-site.xmlConfiguration类一加载,就会默认读取8个配置文件!
将8个配置文件中所有属性,读取到一个Map集合中!也提供了set(name,value),来手动设置用户自定义的参数!
3. `FileStatus`
代表一个文件的状态(文件的属性信息)
-
offset和length
offset是偏移量: 指块在文件中的起始位置
length是长度,指块大小比如:sts.zip 390M length offset blk1: 0-128M 128M 0 blk2: 128M-256M 128M 128M ... blk4: 384M-390M 6M 384M
LocatedFileStatus
LocatedFileStatus是FileStatus的子类,除了文件的属性,还有块的位置信息!
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.*;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.io.IOException;
import java.net.URI;
public class TestHDFS {
private FileSystem fs;
Configuration conf = new Configuration();
@Before
public void init() throws Exception{
//创建一个客户端对象
fs = FileSystem.get(new URI("hdfs://hadoop101:9000"),conf,"sun");//URI不能为null,声明用户
}
//创建目录:hadoop fs -mkdir /xxx
@Test
public void testMkdir() throws Exception {
//System.out.println(fs.getClass().getName());//输出当前使用的类名
fs.mkdirs(new Path("/testHDFS"));//在HDFS的根目录下创建一个testHDFS目录
}
//上传文件:hadoop fs -put 本地文件 hdfs路径
@Test
public void testUpload() throws Exception{
fs.copyFromLocalFile(false, new Path("e:/a.txt"), new Path("/"));
//第一个参数代表上传后是否删除本地文件
}
//下载文件:hadoop fs -get hdfs文件 本地路径
@Test
public void testDownload() throws Exception{
fs.copyToLocalFile(false,new Path("/a.txt"),new Path("e:/"),true);
//最后一个参数代表下载文件的同时是否还下载.crc文件,即校验文件,true代表不下载!
}
//删除文件:hadoop fs -rm hdfs文件
@Test
public void testDelete() throws Exception{
fs.delete(new Path("/a"), true);
//recursive即是否递归删除
}
//重命名:hadoop fs -mv 源文件名 目标文件名
@Test
public void testRename() throws Exception{
fs.rename(new Path("/a.txt"), new Path("/b.txt"));
}
//判断某个文件或目录是否存在
@Test
public void testIfPathExists()throws Exception{
Path path = new Path("/a.txt");
System.out.println(path);//true
}
//判断当前路径是目录还是文件
@Test
public void testIsFileOrDirectory() throws Exception{
Path path = new Path("/a.txt");
/*FileStatus fileStatus = fs.getFileStatus(path);
System.out.println(fileStatus.isDirectory());//false
System.out.println(fileStatus.isFile());//true*/
FileStatus[] fileStatuses = fs.listStatus(path);//获取当前路径的所有文件及目录本身
for (FileStatus status : fileStatuses) {
Path filePath = status.getPath();
//获取的文件名Path是完整的协议(即URI)+文件名,单独获得文件名需要filePath.getName()
System.out.println(filePath.getName()+"是否是目录"+status.isDirectory());
System.out.println(filePath.getName()+"是否是文件"+status.isFile());
}
//不建议使用此方法
/*System.out.println(fs.isDirectory(path));//false
System.out.println(fs.isFile(path));//true*/
}
//获取文件的块信息
@Test
public void testGetBlockInfo() throws Exception{
Path path = new Path("/a.txt");
RemoteIterator<LocatedFileStatus> status = fs.listLocatedStatus(path);
while (status.hasNext()){
LocatedFileStatus locatedFileStatus = status.next();
//获取块的所属用户、所属组
System.out.println(locatedFileStatus.getOwner());
System.out.println(locatedFileStatus.getGroup());
//获取块的位置信息
BlockLocation[] blockLocations = locatedFileStatus.getBlockLocations();
for (BlockLocation blockLocation : blockLocations) {
System.out.println(blockLocation);//输出偏移量、长度、所有主机名
System.out.println("-----------------------");
}
}
}
@After
public void close() throws IOException {
if(fs != null){
fs.close();
}
}
}