经过本章节您能够学习到java
一、将hadoop2.7.2.tar.gz解压到指定目录,例如linux
D:/software/hadoop-2.7.2
hadoop2.7.2.tar.gz就是咱们一开始在linux解压的编译包。shell
二、添加win10所需的组件到bin目录(D:/software/hadoop-2.7.2/bin):将hadoopBin.rar解压,并将里面的7个文件复制到D:/software/hadoop-2.7.2/bin目录。apache
本系列相关的教程都会在章节
【hadoop】1.Hadoop简介
中提供的百度外链下载到。windows
个人是win10环境,因此须要添加以上的组件。maven
若是你的版本不一致,能够从相关网站下载到编译包,至少目前hadoop已经3.x了。ide
一、添加HADOOP_HOME变量,值为D:/software/hadoop-2.7.2/;oop
二、编辑PATH变量,添加新值%HADOOP_HOME%\bin
学习
三、进入windows命令行界面,检测是否成功测试
四、关联集群hosts主机名,修改windows的主机文件
C:\Windows\System32\drivers\etc 添加下面3台主机映射
五、建立目录D:\hadoop
,并在内部建立一个test.txt文件,随便写入一些内容。接下来咱们的测试就是将这个文件上传到HDFS集群。
接下来须要本身建立的测试文件就本身建立测试,这里不做过多说明了。
一、使用idea建立一个maven项目
二、配置pom文件,信息以下
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.zhaoyi</groupId> <artifactId>firsthadoop</artifactId> <version>1.0-SNAPSHOT</version> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <hadoop.version>2.7.3</hadoop.version> </properties> <dependencies> <!-- 引入hadoop相关依赖 --> <dependency> <groupId>org.apache.hadoop</groupId> <artifactId>hadoop-client</artifactId> <version>${hadoop.version}</version> </dependency> <dependency> <groupId>org.apache.hadoop</groupId> <artifactId>hadoop-common</artifactId> <version>${hadoop.version}</version> </dependency> <dependency> <groupId>org.apache.hadoop</groupId> <artifactId>hadoop-hdfs</artifactId> <version>${hadoop.version}</version> </dependency> </dependencies> </project>
三、建立类com.zhaoyi.hdfs.HDFSClient
package com.zhaoyi; import com.google.common.annotations.VisibleForTesting; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.FileSystem; import org.apache.hadoop.fs.Path; import org.junit.Test; import java.net.URI; public class HDFSClient { private final static String HADOOP_USER = "root"; private final static String HDFS_URL = "hdfs://h133:8020"; public static void main(String[] args) throws Exception { // 一、获取配置实体 final Configuration configuration = new Configuration(); // 二、获取文件系统 FileSystem fileSystem = FileSystem.get(new URI(HDFS_URL),configuration,HADOOP_USER); // 三、拷贝本地数据到集群 fileSystem.copyFromLocalFile(new Path("D:/hadoop/test.txt"),new Path("/user/zhaoyi/input")); // 四、关闭文件系统 fileSystem.close(); } }
运行该类,就能够发现咱们建立的文件上传到了/user/zhaoyi/input
下。接下来咱们就在该类的基础上进行其余的测试。
FileSystem.get共有3个重载方法,前两个方法提取的默认认证用户名都为当前用户的帐户名,所以,若是您不指定用户名,会使用你的当前windows帐户去认证,显然是没办法经过的。不过,若是你的HADOOP_USER和WINDOWS_USER一致的话,这里不会有什么问题。推荐使用get的第三个重载方法获取文件系统。
@Test // 获取文件系统 public void getFileSystem() throws Exception{ Configuration configuration = new Configuration(); FileSystem fileSystem = FileSystem.get(new URI(HDFS_URL),configuration,HADOOP_USER); // print fs info System.out.println(fileSystem); }
输出
DFS[DFSClient[clientName=DFSClient_NONMAPREDUCE_-1963602416_1, ugi=root (auth:SIMPLE)]]
编写测试用例
@Test public void putFileToHDFS() throws Exception{ Configuration configuration = new Configuration(); FileSystem fileSystem = FileSystem.get(new URI(HDFS_URL), configuration, HADOOP_USER); // set destination path String destinationPath = "/user/yuanyong"; // uploadFile fileSystem.copyFromLocalFile(true, new Path("D:/hadoop/前尘如梦.txt"),new Path(destinationPath) ); // close fs fileSystem.close(); }
咱们来查看copyFromLocalFile的源码信息,第一个参数的最终执行:
return deleteSource ? srcFS.delete(src, true) : true;
该参数设置为true,则表明上传完成以后会将源文件给删除,是否是以为很像move操做。若是您不想让他删除,能够省略此参数,或者设置为false便可。
@Test public void getFileFromHDFS() throws Exception{ Configuration configuration = new Configuration(); FileSystem fileSystem = FileSystem.get(new URI(HDFS_URL), configuration, HADOOP_USER); // set download path. String downloadPath = "D:/"; // fileSystem.copyToLocalFile(new Path("/user/new.file"),new Path(downloadPath)); fileSystem.copyToLocalFile(false,new Path("/user/new.file"),new Path(downloadPath),false); fileSystem.close(); }
一样,fileSystem.copyToLocalFile也有3个重载方法,其中第三个重载方法的第一个参数指定是否删除源文件,最后一个参数指定是否执行本地的文件系统校检(默认false),false则会在本地生成一个名为.filename.crc的校检文件,设置为true则不生成
关于文件校检:不指定本地校检时,会透明的建立一个.filename.crc的文件。校验文件大小的字节数由io.bytes.per.checksum属性设置,默认是512bytes,即每512字节就生成一个CRC-32校验和。
@Test public void makeDirInHDFS() throws Exception{ Configuration configuration = new Configuration(); FileSystem fileSystem = FileSystem.get(new URI(HDFS_URL), configuration, HADOOP_USER); fileSystem.mkdirs(new Path("/user/areya/my/best/love")); System.out.println("create dir success."); fileSystem.close(); }
建立目录默认就是递归方式。
fileSystem.mkdirs有两个重载方法,另一个
public boolean mkdirs(Path var1, FsPermission var2)
具体用到再说明。
@Test public void deleteInHDFS() throws Exception{ Configuration configuration = new Configuration(); FileSystem fileSystem = FileSystem.get(new URI(HDFS_URL), configuration, HADOOP_USER); fileSystem.delete(new Path("/user/areya"),true); System.out.println("delete dir success."); fileSystem.close(); }
fileSystem.delete也可只指定一个参数,不过该方法会在从此的版本删除,不推荐使用。
@Test public void renameInHDFS() throws Exception{ Configuration configuration = new Configuration(); FileSystem fileSystem = FileSystem.get(new URI(HDFS_URL), configuration, HADOOP_USER); fileSystem.rename(new Path("/user/yuanyong"),new Path("/user/hongqun")); System.out.println("rename dir success."); fileSystem.close(); }
接下来咱们将当前测试在HDFS上的全部文件相关信息都打印一遍。
@Test public void getFileInfoInHDFS() throws Exception{ Configuration configuration = new Configuration(); FileSystem fileSystem = FileSystem.get(new URI(HDFS_URL), configuration, HADOOP_USER); // get all file. RemoteIterator<LocatedFileStatus> listFiles = fileSystem.listFiles(new Path("/"), true); while (listFiles.hasNext()){ System.out.println("------------------"); LocatedFileStatus fileStatus = listFiles.next(); System.out.println("path: " + fileStatus.getPath()); System.out.println("group: " + fileStatus.getGroup()); System.out.println("owner: " + fileStatus.getOwner()); System.out.println("access time: " + fileStatus.getAccessTime()); System.out.println("block size: " + fileStatus.getBlockSize()); System.out.println("length: " + fileStatus.getLen()); System.out.println("modify time: " + fileStatus.getModificationTime()); System.out.println("modify time: " + fileStatus.getModificationTime()); System.out.println("permission: " + fileStatus.getPermission()); System.out.println("replicate: " + fileStatus.getReplication()); // System.out.println("symlink: " + fileStatus.getSymlink()); System.out.println("This file blocks info:"); BlockLocation[] blockLocations = fileStatus.getBlockLocations(); for (BlockLocation blockLocation:blockLocations) { System.out.println("block length:" + blockLocation.getLength()); System.out.println("block offsets:" + blockLocation.getOffset()); System.out.println("block hosts:"); for (String host : blockLocation.getHosts()) { System.out.println(host); } } } System.out.println("-------------"); System.out.println("print end."); }
输出结果:
path: hdfs://h133:8020/user/hongqun/前尘如梦.txt group: supergroup owner: root access time: 1546474991076 block size: 134217728 length: 20 modify time: 1546474991244 modify time: 1546474991244 permission: rw-r--r-- replicate: 3 This file blocks info: block length:20 block offsets:0 block hosts: h133 h135 h134 ------------------ path: hdfs://h133:8020/user/hongqun/test/new.file group: supergroup owner: root access time: 1546465187927 block size: 134217728 length: 21 modify time: 1546465174342 modify time: 1546465174342 permission: rw-r--r-- replicate: 3 This file blocks info: block length:21 block offsets:0 block hosts: h135 h134 h133 ------------------ path: hdfs://h133:8020/user/new.file group: supergroup owner: root access time: 1546477521786 block size: 134217728 length: 21 modify time: 1546465709803 modify time: 1546465709803 permission: rw-r--r-- replicate: 3 This file blocks info: block length:21 block offsets:0 block hosts: h133 h134 h135
从输出结果咱们能够了解到listFiles方法只会列出全部的文件(而非文件夹)信息。
前面咱们经过listFiles获取了文件的信息,接下来咱们获取某个路径下文件的信息,并输出其中的文件和文件夹类型文件。
@Test public void getAllFileInfoInHDFS() throws Exception { Configuration configuration = new Configuration(); FileSystem fileSystem = FileSystem.get(new URI(HDFS_URL), configuration, HADOOP_USER); // get dir "/user"'s file. FileStatus[] listFiles = fileSystem.listStatus(new Path("/user")); for (FileStatus fileStatus:listFiles) { if(fileStatus.isDirectory()){ System.out.println("dir:" + fileStatus.getPath().getName()); }else if(fileStatus.isFile()){ System.out.println("file:" + fileStatus.getPath().getName()); }else if(fileStatus.isEncrypted()){ System.out.println("cry:" + fileStatus.getPath().getName()); }else if(fileStatus.isSymlink()){ System.out.println("symlink:" + fileStatus.getPath().getName()); } } System.out.println("-------------"); System.out.println("print end."); } System.out.println("print end."); }
输出以下:
dir:hongqun file:new.file dir:zhaoyi ------------- print end.
HDFS中可能存在4种类型的文件。
总结一下咱们以上的操做共性:
// 1. 建立配置对象 Configuration configuration = new Configuration(); // 2. 建立文件系统操做对象:设置文件系统URI、配置信息以及HDFS用户名 FileSystem fileSystem = FileSystem.get(new URI(HDFS_URL), configuration, HADOOP_USER); // 3. 执行操做 fileSystem.xxxx(parameter);
接下来咱们经过IO流方式完成文件的一些常规上传下载操做。从新建立一个客户端类。
package com.zhaoyi; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.FSDataInputStream; import org.apache.hadoop.fs.FSDataOutputStream; import org.apache.hadoop.fs.FileSystem; import org.apache.hadoop.fs.Path; import org.apache.hadoop.io.IOUtils; import org.junit.Test; import java.io.FileInputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.net.URI; public class HDFSIOClient { private final static String HADOOP_USER = "root"; private final static String HDFS_URL = "hdfs://h133:8020"; @Test public void uploadFile() throws Exception{ Configuration configuration = new Configuration(); FileSystem fileSystem = FileSystem.get(new URI(HDFS_URL),configuration, HADOOP_USER); // 1. 获取输入流 FileInputStream fis = new FileInputStream(new File("D:/hadoop/天净沙.txt")); // 2. 获取输出流 FSDataOutputStream fos = fileSystem.create(new Path("/user/天净沙.txt")); // 3. 流对接 & 关闭流 try { IOUtils.copyBytes(fis, fos,configuration); System.out.println("upload file success."); } catch (IOException e) { e.printStackTrace(); }finally { fis.close(); fos.close(); fileSystem.close(); } } }
输出与输入的参考系是相对于当前内存系统(也能够理解为咱们的客户端)而言的。本地文件系统属于输入流,上传的目的地HDFS文件系统则属于输出流。
@Test public void downloadFile() throws Exception{ Configuration configuration = new Configuration(); FileSystem fileSystem = FileSystem.get(new URI(HDFS_URL),configuration, HADOOP_USER); // 1. 获取输入流 FSDataInputStream fis = fileSystem.open(new Path("/user/奥丁的子女.txt")); // 2. 获取输出流 FileOutputStream fos = new FileOutputStream(new File("D:/hadoop/奥丁的子女.txt")); // 3. 流对接&关闭流 try { IOUtils.copyBytes(fis, fos,configuration); System.out.println("download file success."); } catch (IOException e) { e.printStackTrace(); }finally { fis.close(); fos.close(); fileSystem.close(); } }
从这里咱们要明白:相对于本地客户端来讲,本地文件系统在下载模式下属于输出的对象,所以使用输出流对应;HDFS文件系统属于输入的对象,所以使用输入流,FileSystem的create建立输出流,open方法建立输入流。
还记得咱们以前的很大的hadoop安装文件夹吗,接下来咱们来定位方式下载该文件。您也能够从新上传一次:
[root@h133 ~]# hadoop fs -put /opt/software/hadoop-2.7.2.tar.gz /user/ [root@h133 ~]# hadoop fs -ls /user/ Found 6 items -rw-r--r-- 3 root supergroup 212046774 2019-01-03 11:06 /user/hadoop-2.7.2.tar.gz drwxr-xr-x - root supergroup 0 2019-01-03 08:23 /user/hongqun -rw-r--r-- 3 root supergroup 21 2019-01-03 05:48 /user/new.file drwxr-xr-x - root supergroup 0 2019-01-03 06:11 /user/zhaoyi -rw-r--r-- 3 root supergroup 28 2019-01-03 10:39 /user/天净沙.txt -rw-r--r-- 3 root supergroup 167 2019-01-03 10:50 /user/奥丁的子女.txt
接下来咱们下载hadoop-2.7.2.tar.gz,分红两部分:第一次下载128M,剩余的放到第二次进行下载。
// 进行第一次下载 @Test public void downloadFileBySeek1() throws Exception{ Configuration configuration = new Configuration(); FileSystem fileSystem = FileSystem.get(new URI(HDFS_URL),configuration, HADOOP_USER); // part 1. 128M // 1. 获取输入流 FSDataInputStream inputStream = fileSystem.open(new Path("/user/hadoop-2.7.2.tar.gz")); // 2. 获取输出流 FileOutputStream outputStream = new FileOutputStream(new File("D:/hadoop/hadoop-2.7.2.tar.gz.part1")); // 3. 流对接(第一部分只需读取128M便可) byte[] buff = new byte[1024]; try { for (int i = 0; i < 1024 * 128; i++) { inputStream.read(buff); outputStream.write(buff); } } finally { IOUtils.closeStream(inputStream); IOUtils.closeStream(outputStream); IOUtils.closeStream(fileSystem); } } // 进行第一次下载 @Test public void downloadFileBySeek1() throws Exception{ Configuration configuration = new Configuration(); FileSystem fileSystem = FileSystem.get(new URI(HDFS_URL),configuration, HADOOP_USER); // part 1. 128M // 1. 获取输入流 FSDataInputStream inputStream = fileSystem.open(new Path("/user/hadoop-2.7.2.tar.gz")); // 2. 获取输出流 FileOutputStream outputStream = new FileOutputStream(new File("D:/hadoop/hadoop-2.7.2.tar.gz.part1")); // 3. 流对接(第一部分只需读取128M便可) byte[] buff = new byte[1024]; try { for (int i = 0; i < 1024 * 128; i++) { inputStream.read(buff); outputStream.write(buff); } } finally { IOUtils.closeStream(inputStream); IOUtils.closeStream(outputStream); IOUtils.closeStream(fileSystem); } } // 第二次寻址下载 @Test public void downloadFileBySeek2() throws Exception{ Configuration configuration = new Configuration(); FileSystem fileSystem = FileSystem.get(new URI(HDFS_URL),configuration, HADOOP_USER); // part 1. 128M // 1. 获取输入流 FSDataInputStream inputStream = fileSystem.open(new Path("/user/hadoop-2.7.2.tar.gz")); // 2. 获取输出流 FileOutputStream outputStream = new FileOutputStream(new File("D:/hadoop/hadoop-2.7.2.tar.gz.part2")); // 3. 指向第二块数据地址 inputStream.seek(1024 * 1024 * 128); try { IOUtils.copyBytes(inputStream,outputStream,configuration); } finally { IOUtils.closeStream(inputStream); IOUtils.closeStream(outputStream); IOUtils.closeStream(fileSystem); } }
分别运行两个测试方法以后,在目录D:/hadoop/下就会生成两个tar.gz.part1和part2的分块文件。接下来运行windows命令行执行追加剧定向操做,将两个文件合并为1个。
type hadoop-2.7.2.tar.gz* > hadoop-2.7.2.tar.gz
便可合并咱们最初的hadoop压缩包文件,能够经过解压缩或者md5计算验证是否一致。
本系列的文章参考资料来源有3个地方: