本篇总结HDFS在windows操作系统Java环境下的API操作。
HDFS的Java_api操作
配置Windows下的 Hadoop环境
在Windows系统需要配置Hadoop运行环境,相当于Windows是一个Hadoop客户端。
不配置而直接运行代码会出现以下问题:
1
| Could not locate executable null\bin\winutils.exe in the hadoop binaries
|
原因: 缺少winutils.exe
1
| Unable to load native-hadoop library for your platform..using builtin-Java classes where applicable
|
原因: 缺少hadoop.dll
解决
1、首先下载Hadoop在Windows上的工具包,下载地址:https://github.com/steveloughran/winutils 。
2、得到后,将其解压到一个无中文无空格的目录下,并配置环境变量。
Path下添加:%HADOOP_HOME%\bin
3、将下载的包内的 hadoop.dll
拷贝一份到 C:\Windows\System32 目录下。
4、 重启电脑,完成。
导入Maven依赖
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
| <dependencies> <dependency> <groupId>org.apache.hadoop</groupId> <artifactId>hadoop-common</artifactId> <version>2.7.7</version> </dependency>
<dependency> <groupId>org.apache.hadoop</groupId> <artifactId>hadoop-client</artifactId> <version>2.7.7</version> </dependency>
<dependency> <groupId>org.apache.hadoop</groupId> <artifactId>hadoop-hdfs</artifactId> <version>2.7.7</version> </dependency>
<dependency> <groupId>org.apache.hadoop</groupId> <artifactId>hadoop-mapreduce-client-core</artifactId> <version>2.7.7</version> </dependency>
<dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>RELEASE</version> </dependency> </dependencies>
<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.2</version> <configuration> <source>1.8</source> <target>1.8</target> <encoding>UTF-8</encoding> </configuration> </plugin>
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <version>2.4.3</version> <executions> <execution> <phase>package</phase> <goals> <goal>shade</goal> </goals> <configuration> <minimizeJar>true</minimizeJar> </configuration> </execution> </executions> </plugin> </plugins> </build>
|
使用URL方式访问数据(了解)
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| @Test public void urlHDFS() throws IOException { URL.setURLStreamHandlerFactory(new FsUrlStreamHandlerFactory()); InputStream inputStream = new URL("hdfs://bigdata1:8020/a.txt").openStream(); FileOutputStream fileOutputStream = new FileOutputStream(new File("D:\\hello.txt")); IOUtils.copy(inputStream, fileOutputStream); IOUtils.closeQuietly(inputStream); IOUtils.closeQuietly(fileOutputStream); }
|
使用文件系统方式访问数据(掌握)
涉及的主要类
在Java中操作HDFS,主要涉及以下Class:
获取FileSystem的四种方式
第一种
1 2 3 4 5 6 7 8 9 10 11
| @Test public void getFileSystem1() throws IOException { Configuration configuration = new Configuration(); configuration.set("fs.defaultFS", "hdfs://bigdata1:8020"); FileSystem fileSystem = FileSystem.get(configuration); System.out.println(fileSystem); }
|
第二种
1 2 3 4 5
| @Test public void getFileSystem2() throws IOException, URISyntaxException { FileSystem fileSystem = FileSystem.get(new URI("hdfs://bigdata1:8020"), new Configuration()); System.out.println(fileSystem); }
|
第三种
1 2 3 4 5 6 7 8 9 10 11
| @Test public void getFileSystem3() throws IOException { Configuration configuration = new Configuration(); configuration.set("fs.defaultFS", "hdfs://bigdata1:8020"); FileSystem fileSystem = FileSystem.newInstance(configuration); System.out.println(fileSystem); }
|
第四种
1 2 3 4 5
| @Test public void getFileSystem4() throws IOException, URISyntaxException { FileSystem fileSystem = FileSystem.newInstance(new URI("hdfs://bigdata1:8020"), new Configuration()); System.out.println(fileSystem); }
|
注意:1、3比较相似,2、4比较相似,主要是get方法和 newInstance方法的使用
这里对Configuration参数对象的加载机制作出解释:
- 首先构造时会加载jar包的默认配置,如:xxx-default.xml
- 再加载用户配置的文件(必须放在resources资源目录下),如自定义的hdfs-site.xml
- 最后可以手动设置,覆盖之前的相同有关配置:configuration.set(“dfs.blocksize”, “64m”);
遍历HDFS所有文件信息
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| @Test public void listFiles() throws URISyntaxException, IOException { FileSystem fileSystem = FileSystem.get(new URI("hdfs://bigdata1:8020"), new Configuration()); RemoteIterator<LocatedFileStatus> iterator = fileSystem.listFiles(new Path("/"), true); while (iterator.hasNext()){ LocatedFileStatus fileStatus = iterator.next(); System.out.println(fileStatus.getPath() + " --- " + fileStatus.getPath().getName());
BlockLocation[] blockLocations = fileStatus.getBlockLocations(); System.out.println("Block数:" + blockLocations.length); } }
|
HDFS创建文件夹
1 2 3 4 5 6 7 8 9 10 11
| @Test public void mkdirs() throws URISyntaxException, IOException { FileSystem fileSystem = FileSystem.get(new URI("hdfs://bigdata1:8020/a.txt"), new Configuration()); boolean bl = fileSystem.mkdirs(new Path("/aaa/bbb/ccc")); fileSystem.create(new Path("/aaa/aaa.txt")); System.out.println(bl); fileSystem.close(); }
|
文件的下载
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| @Test public void downloadFile() throws URISyntaxException, IOException { FileSystem fileSystem = FileSystem.get(new URI("hdfs://bigdata1:8020/a.txt"), new Configuration());
FSDataInputStream inputStream = fileSystem.open(new Path("/a.txt")); FileOutputStream outputStream = new FileOutputStream("D://a.txt"); IOUtils.copy(inputStream, outputStream); IOUtils.closeQuietly(inputStream); IOUtils.closeQuietly(outputStream); fileSystem.close(); }
@Test public void downloadFile2() throws URISyntaxException, IOException { FileSystem fileSystem = FileSystem.get(new URI("hdfs://bigdata1:8020/a.txt"), new Configuration()); fileSystem.copyToLocalFile(new Path("/a.txt"), new Path("D://a.txt")); fileSystem.close(); }
|
文件的上传
1 2 3 4 5 6
| @Test public void uploadFile() throws URISyntaxException, IOException { FileSystem fileSystem = FileSystem.get(new URI("hdfs://bigdata1:8020/a.txt"), new Configuration()); fileSystem.copyFromLocalFile(new Path("D://b.txt"),new Path("/")); fileSystem.close(); }
|
HDFS的权限访问控制
首先进入Hadoop的安装目录下的/etc/hadoop/hdfs-site.xml,修改permission为true,代表启动权限。启动后通过命令行的权限修改才能生效,修改配置文件需要重启才能生效。
1
| hdfs dfs -chmod 000 /a.txt
|
数字代表权限等级,当开启权限控制时,文件会有其对应的Owner,不是相应的Owner仍然无法访问资源。这时我们可以在get方法内指定伪装用户对资源进行访问:
1
| FileSystem fileSystem = FileSystem.get(new URI("hdfs://bigdata1:8020/a.txt"), new Configuration(), "root");
|
小文件合并
由于Hadoop擅长存储大文件,因为大文件的元数据信息比较少。如果集群中有大量的小文件,则需要维护大量的元数据,增大内存压力。所以有必要将小文件合并成大文件一起处理。
在HDFS的Shell命令下,可以用如下命令讲很多HDFS文件合并成一个大文件下载到本地
1 2
| cd /export/servers hdfs dfs -getmerge /config/*.xml ./hello.xml # 表示合并文件,下载到当前目录下的hello.xml
|
同样也可以在上传时将小文件合并到一个大文件里面去
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| @Test public void mergeFile() throws URISyntaxException, IOException, InterruptedException { FileSystem fileSystem = FileSystem.get(new URI("hdfs://bigdata1:8020/a.txt"), new Configuration(), "root"); FSDataOutputStream outputStream = fileSystem.create(new Path("/big.txt")); LocalFileSystem localFileSystem = FileSystem.getLocal(new Configuration()); FileStatus[] fileStatuses = localFileSystem.listStatus(new Path("D:\\input")); for (FileStatus fileStatus : fileStatuses) { FSDataInputStream inputStream = localFileSystem.open(fileStatus.getPath()); IOUtils.copy(inputStream, outputStream); IOUtils.closeQuietly(inputStream); } IOUtils.closeQuietly(outputStream); localFileSystem.close(); fileSystem.close(); }
|
HDFS的高可用机制
在Hadoop2.X之前,Namenode是HDFS集群中可能发生单点故障的节点,每个HDFS集群只有一个namenode,一旦这个节点不可用,则整个HDFS集群将处于不可用状态。
HDFS高可用(HA)方案就是为了解决上述问题而产生的,在HA HDFS集群中会同时运行两个Namenode,一个作为活动的Namenode(Active),一个作为备份的Namenode(Standby)。备份的Namenode的命名空间与活动的Namenode是实时同步的,所以当活动的Namenode发生故障而停止服务时,备份Namenode可以立即切换为活动状态,而不影响HDFS集群服务。
详情:https://blog.csdn.net/u012736748/article/details/79534019
Hadoop联邦机制