针对Hadoop基本操作的shell命令与Java代码
- 实验目的
- 一、利用Hadoop提供的Shell命令
-
- 1、向HDFS中上传文本文件,如果指定的文件在HDFS中已经存在,则追加到原有文件末尾或者覆盖原有的文件:-appendToFile、-copyFromLocal
- 2、从HDFS中下载指定文件,如果本地文件与要下载的文件名称相同,则自动对下载的文件重命名:if $(); then $(); then $(); fi
- 3、将HDFS中指定文件的内容输出到终端中:-cat
- 4、显示HDFS中指定的文件的读写权限、大小、创建时间、路径等信息:-ls -h
- 5、给定HDFS中某一个目录,输出该目录下的所有文件的读写权限、大小、创建时间、路径等信息,如果该文件是目录,则递归输出该目录下所有文件相关信息:-ls -R -h
- 6、提供一个HDFS内的文件的路径,对该文件进行创建和删除操作。如果文件所在目录不存在,则自动创建目录:-test -d、-touchz、-mkdir -p
- 7、提供一个HDFS的目录的路径,对该目录进行创建和删除操作。创建目录时,如果目录文件所在目录不存在,则自动创建相应目录;删除目录时,由用户指定当该目录不为空时是否还删除该目录。
- 8、向HDFS中指定的文件追加内容,由用户指定内容追加到原有文件的开头或结尾
- 9、删除HDFS中指定的文件:-rm -r
- 10、在HDFS中,将文件从源路径移动到目的路径:-mv
- 二、java编程实现
-
- 1、向HDFS中上传任意文本文件,如果指定的文件在HDFS中已经存在,则由用户来指定是追加到原有文件末尾还是覆盖原有的文件。
- 2、从HDFS中下载指定文件,如果本地文件与要下载的文件名称相同,则自动对下载的文件重命名。
- 3、将HDFS中指定文件的内容输出到终端中。
- 4、显示HDFS中指定的文件的读写权限、大小、创建时间、路径等信息。
- 5、给定HDFS中某一个目录,输出该目录下的所有文件的读写权限、大小、创建时间、路径等信息,如果该文件是目录,则递归输出该目录下所有文件相关信息。
- 6、提供一个HDFS内的文件的路径,对该文件进行创建和删除操作。如果文件所在目录不存在,则自动创建目录;
- 7、提供一个HDFS的目录的路径,对该目录进行创建和删除操作。创建目录时,如果目录文件所在目录不存在,则自动创建相应目录;删除目录时,由用户指定当该目录不为空时是否还删除该目录。
- 8、向HDFS中指定的文件追加内容,由用户指定内容追加到原有文件的开头或结尾
- 9、删除HDFS中指定的文件
- 10、在HDFS中,将文件从源路径移动到目的路径
实验目的
(1)理解HDFS在Hadoop体系结构中的角色;
(2)熟练使用HDFS操作常用的Shell命令;
(3)熟悉HDFS操作常用的Java API。
本地路径:/home/hadoop/
HDFS路径:/user/hadoop/
命令方式 | 区别 |
---|---|
hadoop fs | 使用面最广,可以操作任何文件系统 |
hadoop dfs | 只能操作HDFS文件系统相关(包括与Local FS间的操作),前者已经Deprecated,一般使用后者 |
hdfs dfs | 只能操作HDFS文件系统相关(包括与Local FS间的操作),前者已经Deprecated,一般使用后者 |
(1)对文件和目录的操作:
创建hdfs dfs
创建0字节hdfs空文件hadoop fs -touchz newnullfile
创建hdfs目录hadoop fs -mkdir newnullmulu
浏览文件内容hadoop fs -cat local.txt
递归列出目录内容 hadoop fs -ls -R input
查看目录的使用情况hadoop fs -df input
显示目录中所有文件及目录大小hadoop fs -du input
(2)删除文件和目录:
直接删除文件hadoop fs -rm -skipTrash newnullfile
直接删除目录及目录下的文件hadoop fs -rm -r -skipTrash input
(3)本地文件系统与HDFS 文件系统互相拷贝
从本地移动到hdfs上hadoop fs -moveFromLocal test1.txt /user/hadoop
从hdfs上移动到本地moveToLocal: Option ‘-moveToLocal’ is not implemented yet.不能实现
从本地复制到hdfs上hadoop fs -put local.txt ./
从hdfs复制到本地hadoop fs -get test.txt ./
(4)修改权限或用户组
改变hdfs文件权限 -R表递归 hadoop fs -chmod +r ./local.txt
改变hdfs文件所属用户(修改文件所有者权限)hadoop fs -chown hadoop:hadoop ./test.txt
改变hdfs文件所属组别hadoop fs -chgrp hadoop ./tmp
(5)测试文件目录是否存在
检查文件是否存在-e hadoop fs -test -e tmp/test.txt
检查目录是否存在-d hadoop fs -test -d tmp
一、利用Hadoop提供的Shell命令
1、向HDFS中上传文本文件,如果指定的文件在HDFS中已经存在,则追加到原有文件末尾或者覆盖原有的文件:-appendToFile、-copyFromLocal
- (1)先创建一个文本文件并上传至HDFS
- (2)修改文本文件内容做记号,追加到原有文件末尾:-appendToFile
- (3)修改文本文件内容做记号,覆盖原有的文件:-copyFromLocal
2、从HDFS中下载指定文件,如果本地文件与要下载的文件名称相同,则自动对下载的文件重命名:if $(); then $(); then $(); fi
3、将HDFS中指定文件的内容输出到终端中:-cat
4、显示HDFS中指定的文件的读写权限、大小、创建时间、路径等信息:-ls -h
5、给定HDFS中某一个目录,输出该目录下的所有文件的读写权限、大小、创建时间、路径等信息,如果该文件是目录,则递归输出该目录下所有文件相关信息:-ls -R -h
6、提供一个HDFS内的文件的路径,对该文件进行创建和删除操作。如果文件所在目录不存在,则自动创建目录:-test -d、-touchz、-mkdir -p
7、提供一个HDFS的目录的路径,对该目录进行创建和删除操作。创建目录时,如果目录文件所在目录不存在,则自动创建相应目录;删除目录时,由用户指定当该目录不为空时是否还删除该目录。
8、向HDFS中指定的文件追加内容,由用户指定内容追加到原有文件的开头或结尾
9、删除HDFS中指定的文件:-rm -r
10、在HDFS中,将文件从源路径移动到目的路径:-mv
二、java编程实现
1、向HDFS中上传任意文本文件,如果指定的文件在HDFS中已经存在,则由用户来指定是追加到原有文件末尾还是覆盖原有的文件。
①HDFS上没有test文件,本地test.txt文件如下图所示。
期间我出现了一个报错:/home/hadoop/test.txt does not exist
原因是我以为在/usr/local/hadoop路径就是/home/hadoop,usr/local/hadoop是安装Hadoop的路径,/home/hadoop是~路径。
②运行第一次,把文件上传,在终端查看文件是否存在。
③更改原本test.txt的文件内容以示区分
④再次运行代码,选择覆盖
⑤再次运行代码,选择加尾
如果出错关于node,可以看看:HDFS追加文件出现报错:ailed to replace a bad datanode on the existing pipeline due to no more good datanodes
如果出错可以删掉HDFS上存在的源文件重新上传、重新追加。
package test2_1;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.*;
import java.io.*;
import java.util.Scanner;
import java.io.FileInputStream;
import java.io.IOException;
import org.apache.hadoop.fs.FSDataOutputStream;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
public class HDFSApi {
/**
* 判断路径是否存在
*/
public static boolean test(Configuration conf, String path) throws IOException {
FileSystem fs = FileSystem.get(conf);
return fs.exists(new Path(path));
}
/**
* 复制文件到指定路径
* 若路径已存在,则进行覆盖
*/
public static void copyFromLocalFile(Configuration conf, String localFilePath, String remoteFilePath) throws IOException {
FileSystem fs = FileSystem.get(conf);
Path localPath = new Path(localFilePath);
Path remotePath = new Path(remoteFilePath);
/* fs.copyFromLocalFile 第一个参数表示是否删除源文件,第二个参数表示是否覆盖 */
fs.copyFromLocalFile(false, true, localPath, remotePath);
fs.close();
}
/**
* 追加文件内容
*/
public static void appendToFile(Configuration conf, String localFilePath,String remoteFilePath) {
Path remotePath = new Path(remoteFilePath);
try (FileSystem fs = FileSystem.get(conf);
FileInputStream in = new FileInputStream(localFilePath);) {
FSDataOutputStream out = fs.append(remotePath);
byte[] data = new byte[1024];
int read = -1;
while ((read = in.read(data)) > 0) {
out.write(data, 0, read);
}
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 主函数
*/
public static void main(String[] args) {
Configuration conf = new Configuration();
conf = new Configuration();
conf.set("dfs.client.block.write.replace-datanode-on-failure.policy","NEVER");
conf.set("dfs.client.block.write.replace-datanode-on-failure.enable","true");
conf.set("fs.default.name","hdfs://localhost:9000");
String localFilePath = "/home/hadoop/t.txt"; // 本地路径
String remoteFilePath = "/user/hadoop/t.txt"; // HDFS 路径
//String choice = "append"; // 若文件存在则追加到文件末尾
//String choice = "overwrite"; // 若文件存在则覆盖
try {
/* 判断文件是否存在 */
boolean fileExists = false;
if (HDFSApi.test(conf, remoteFilePath)) {
fileExists = true;
System.out.println(remoteFilePath + " 已存在.");
} else {
System.out.println(remoteFilePath + " 不存在.");
}
/* 进行处理 */
if (!fileExists) {
// 文件不存在,则上传
HDFSApi.copyFromLocalFile(conf, localFilePath, remoteFilePath);
System.out.println(localFilePath + " 已上传至 " + remoteFilePath);
}
else{
Scanner sc = new Scanner(System.in);
System.out.println("1:overwrite 2:append:");
int num1 = sc.nextInt();
if (num1 == 1){
HDFSApi.copyFromLocalFile(conf, localFilePath, remoteFilePath);
System.out.println(localFilePath + " 已覆盖 " + remoteFilePath);
}
else if