开发者学堂课程【高校精品课-上海交通大学-企业级应用体系架构: HDFS】学习笔记,与课程紧密联系,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/75/detail/15845
HDFS(二)
内容介绍
一、HDFS
二、测试
二、测试
1.代码
import org.apache.hadoop.confConfiguration import org.apache.hadoop.fs.FileSystem; import org.apache.hadoop.fs.Path;
public class TestHDFS {
public static void main(String[]args) throws Exception { Configuration conf=new Configuration();
confset("dfs.defaultFS","hdfs://hadoop:9000"); FileSystem fs=FileSystemget(conf);
fs.create(new Path("./test/helloByJava")) fs.close();
)
创建 Hadoop 的配置对象,以及分布式文件系统的位置在哪里,用配置对象去获取 file system 对象,拿到对象以后就拿到了 Distributed file system,然后就可以进行操作了,使用 create 创建对象,对象在/test/helloByJava这个位置,创建好以后关掉,这就是一个写操作
2.专门演示应用方法
还有一个例子是 HDFS 专门演示的应用方法
public class HDFSApp {
public static final string HOFS_PATH ="hdfs://hadoop:9000";//文件系统
FileSystem fileSystem =null;//配置类
Configuration configuration = null;
//Before 适用于类加载之前@Test/**
* 创建 HDES 系统*/
public void mkdir() throws Exception {
fileSystem.mkdirs(new Path(pathString: "./output"));}
@Test
public void create() throws Exception {
FSDataOutputStream output =fileSystem.create(new Path(pathString output.write("hello hadoop".getBytes()); output.flush(); output.close();
@Test
public void create() throws Exception {
FSDataOutputstream output=fileSystem.create(new Path(pathStrir output Iwrite("hello hadoop".getBytes()); output.flush(); autput.close();}
@Test/**
* 查看 HDFS 文件上的内容*/
public void cat() throws Exception {
FSDataInputStream in =fileSystem.open(new Path(pathString:"./ou IOUtils.copyBytes(in,System.out, buffSize: 1024); in.close();}
@Before
public void setup() throws Exception {
System.out.printf("HDFSapp.setup");
包括有创建目录,创建单个文件向里面写入信息,又将两个文件合并起来,等等等等这些功能,大家下载之后可以跑一下,Test 只是其中一个,创建了一个空文件,可以认为这是对 HDFS 标准的写入动作,所有的动作都在里面,未来可以用这些封装接口执行逻辑。
上面讲的是 HDFS 代码,下面看一下 H DFS 封装起来的东西
public class HDFSApp{
public static final StringHDFS_PATH="hdfs://hadoop:9000";//文件系统
FileSystem fileSystem=null;//配置类
Configuration configuration=null;
//Before 适用于类加载之前@Test/**
*创建 HDFS 系统*/
public void mkdir() throws Exception {
fileSystem.mkdirs(new Path("./output"));
}
@Test
public void create()throws Exception {
FSDataOutputStreamoutput=fileSystemcreate(new
Path("./output/a.txt")) outputwrite("hello hadoop".getBytes());
output.flush(); output.close();
@Test/**
*查看 HDFS 文件上的内容*/
public void cat() throws Exception {
FSDatalnputStream in=fileSystem.open(new
Path("./output/b.txt")); IOUtils.copyBytes(in,System.out,1024); in.close();
有创建目录的,也有创建一个文件的,创建文件具体的是 a.txt,这个文件创建好以后,得到文件的输出流,向里面写入东西相当于将里面的内容写到文件中去,flush才真正写入数据,然后再 close,之所以 flush 是因为与Hibernate很类似,flush 是将内存中的东西刷到真正的硬盘上去,刚刚看到的一个文件块是64M,这里只写入几个字符远远小于64M,所以会在输出缓冲区中缓冲,当文件数量大于64M时才会像硬盘中写出一个 block,当继续写时还在缓存,每满足64M 向外写,这时对 a.TXT 进行操作时,可能写进去了1 gb 的内容,可能会出来很多很多的 block,这个东西从test这段代码来讲是用户是分布式文件系统,从这段代码讲是屏蔽的,只知道创建了文件向里面不断的写入数据,至于其中到底有哪些 block 不用关心,因为不用关心 block 在哪里里面的内容如何拿到,就像在硬盘上写入一个文件从来不用关心在硬盘上哪一个扇区哪个词道上,这些东西应该透明,只知道有文件不断的向里写入,能从里面读取出来。下面的码是查看文件系统里的内容,openb.txt 这个文件,这是文件输入流,读取出这个文件输入流在屏幕上进行输出,Copy bytes 是将 system 的流 copy 到这里,一次读取1024个字节不断的进行读取,现在可以考前面1024个字节出来查看里面的内容,实际上对应的部分是打开文件
@Before
public void setUp() throws Exception{
System.outprintf("HDFSapp.setup"); configuration=newConfiguration();
configuration.set("dfs.defaultFS",
"hdfs://hadoop:9000") fileSystem=FileSystemget(configuration);
//关闭资源用的这个@After
public void tearDown() throws Exception {//释放资源
configuration =null; fileSystem=null;
System.outprintf("HDFSAPP.tearDown")
这里讲的是如何获取 file system 对象,首先要创建 configuration 在里面设置一些键值对,最主要的是引用的分布式文件系统位置在哪里,用静态方法去 get 得到了 file system,以上的操作都是通过 file system 实现的。tear down指的是释放资源,释放资源,设置文件系统操作完成以后持有的 configuration 和 file system 这两个应该可以被回收掉,要想被垃圾回收掉就不会再被引用,所以要将他们的引用指向空,在内存中这两个对象就没有了任何引用,就被释放掉了
/**
*重命名文件/*
@Test
public void rename() throws Exception {
Path oldPath=new Path("./output/a.txt");
Path newPath=new Path("./output/b.txt);
fileSystem.rename(oldPath,newPath);
这是在改名字,改名字调用的也是 file system rename 方法,将旧的名字改成新的名字
/**
*上传一个文件
*
* @throws Exception
*
@Test
public void copyFromLocalFile() throws Exception {
Path localPath=new Path("./test/helloByJava");
Path hdfsPath=new
Path("./output/helloByJava")
fileSystem.copyFromLocalFile(localPathhdfsPath)
这是复制,将一个文件通过 copy from local file 复制到另外一个目录中去,把 local path 件复制到 HDFS path文件指向的位置
/**
*上传一个大文件* @throws Exception*/
@Test
public void copyFromLocalBigFile() throws Exception {
InputStream in=new BufferedIputStream
new FilelnputStream(
new File("./resources/hadoop-hdfs-3.2.1.jar")))
FSDataOutputStreamoutput=fileSystemcreate(
new Path("./output/hadoop-hdfs-3.2.1.jar") new Progressable(){
public void progress() {
System.out.print(".");//带进度提醒信息
});
lOUtilscopyBytes(in,output,4096);
这是用 path 表示的,真正的使用文件输入输出流进行操作,把本地的文件 resources/hadoop-hdfs-3.2.1.jar上传到./output/hadoop-hdfs-3.2.1.jar 这个文件上去,同样是要有文件的输入流和输出流,因为在线上传时相当于在HDFS里创建了新文件,所以要将上面的文件写入到这里,拷贝到 Output 里,拷贝前4K 的内容,这样就完成了
/**
*下载 HDFS 文件/*
@Test
public void copyTOLocalFile() throws Exception{
Path localPath=new Path("./test/b.txt");
Path hdfsPath=new Path("./output/b.txt");
fileSystem.copyToLocalFile(false,hdfsPathlocalPathtrue)
这个是将分布式文件系统的文件下载到本地,使用的是 copy to local file 方法,使用的是先创建一个文件然后使用复制,所以大体上看到的对文件大部分操作都有了,可以去进行测
3.测试代码
@Test
public void listFiles() throws Exception {
FileStatus[] fileStatuses=fileSystem.listStatus(new Path("./output"))
for (FileStatus fileStatus:fileStatuses){
String isDir=fileStatus.isDirectory文件夹":"文件"//副本
short replication=fileStatus.getReplication();//大小
long len=fileStatusgetLen();//路径
String path=fileStatusgetPath().toString();
System.outprintIn(isDir+"\t"+replication +"\t"+ len +"\t" + path)
}
可以测试一下文件系统中到底都包含什么,例如指向一个目录去遍历,查看目录里面的内容是目录还是一个具体文件,如果是目录就输出文件夹如果不是就输出文件是字符串,下面是查看文件有多少个副本,长度等等,拿到信息以后输出一下,便利完成以后就会将当前 HDFS 系统里所有的文件一个目录树打印出来,并且给了相应文件的副本数长度这样的信息,dir 表示是文件还是目录?path 是具体的文件,相当于叫 name Note 里面的原数据文件打印了出来。
@Test
public void delete() throws Exception{
fileSystem.delete(new Path("./test/"),true);
删除比较简单,直接 delete 就可以
4.pom 文件
<dependency>
<dependency>
<groupld>org.apache.hadoop</groupld><groupld>junit</groupld>
<artifactld>hadoop-common</artifactld><artifactld>iunit</artifactld>
<version>3.2.1</version>
<version>4.13</version>
</dependency>
<scope>test</scope>
<dependency>
</dependency>
<groupld>org.apache.hadoop</groupld>
<dependency>
<artifactld>hadoop-hdfs</artifactld>
<groupld>junit</groupld>
<version>3.2.1</version>
<artifactld>iunit</artifactld>
</dependency>
<version>4.13</version>
<dependency>
<scope>compile</scope>
<groupld>org.apache.hadoop</groupld>
</dependency>
<artifactld>hadoop-hdfs-client</artifactld><version>3.2.1</version><scope>provided</scope></dependency>
为了使刚才的代码跑起来,首先要用到 Hadoop commonHadoop 盒要拿到,其次是 HDFS,还需要 HDFS 的客户端,这是要得到的东西,刚才在跑的时候使用了 annotation test,所以这边实际上是 junit 的东西,使用此一个目的是测试一个是在编译的时候用的,这就是 pom 文件中要包含的内容。
真正在跑例子时,将 HDFS 跑起来
这就就是跑完的例子,因为刚才创建了一个文件,上传了文件,将文件进行了输出与下载等等所以看到文件的输出,这就是所讲述的例子,也就是上面讲的代码后面再写的时候加了一个 main,如果不用刚才的 test 来跑直接将所有的东西跑一遍,会出现刚刚看到的例子
也就是这样的输出,可以看到里面的内容,Test 有控制台
控制台是这样的 Local host 9870.在启动了 HadoopHDFS 之后是它的控制台,在这里面可以看到信息,其实刚才写进去的内容很少总共只有4K 的空间,总共也只有一个节点,就是 local host 9866节点
节点会展示跑了多长时间,里面的文件在哪里等等,这就是与 HDFS 有关的东西,要强调的是 HDFS 要有一个概念,底层是构建在 Linux fs 之上的,作用是将一个大的文件存储下来,构建 Linux 上以后将一个大文件切成许多小块,每个小块就是一个 Linux 文件,要做的就是大文件到小文件的映射,然后这些小文件本身在 Linux 系统之上去看就是一个标准的小文件,每个文件都是指定尺寸的,例如64M,在处理大文件到小文件的映射以及分布式的存储和多个副本之间的管理这就是复杂性,不是在裸机上面直接装了一个 HDFS,可以直接跑,就是在机器上面跑起来了 HDFS系统,这是 HDFS 最重要的一块,其他是 API 的使用问题。