【大数据技术】HDFS的一些编程(java)
目录
// 导入 Hadoop 的 Configuration 类,用于加载配置(用来告诉程序如何连接 HDFS)
import org.apache.hadoop.conf.Configuration;
// 导入 Hadoop 的 FileSystem 类,提供对文件系统的操作
import org.apache.hadoop.fs.FileSystem;
// 定义一个公共类 FileExist,程序入口类
public class FileExist {
// 主函数,Java 程序执行的入口
public static void main(String[] args) {
try {
// 创建 Configuration 对象,会自动读取 Hadoop 的配置文件
// 默认读取位置是 $HADOOP_HOME/etc/hadoop 目录下的 core-site.xml 等配置文件
Configuration conf = new Configuration();
// 通过配置对象获取 FileSystem 实例
// 如果配置文件中指定的是 HDFS 地址(如 hdfs://namenode:9000),则返回的是 HDFS 实例
FileSystem fs = FileSystem.get(conf);
} catch (Exception e) {
// 如果在配置、连接文件系统等过程中出现异常,会被捕获到这里
// 打印异常的堆栈信息,方便调试错误
e.printStackTrace();
}
}
}
连接 Hadoop 的文件系统(HDFS)
FileSystem 类,是 Hadoop 提供的统一的文件系统抽象类,支持 HDFS、本地文件系统等。通过它可以进行文件的读取、写入、删除、检查是否存在等操作。
启动Hadoop 集群环境
(master) > bash /scripts/hadoop/start-hadoop.sh
(master) >是终端或命令行的提示符(prompt)
意思是你当前所在的是 主节点master
本身不是命令,只是提示符的一部分
bash /scripts/hadoop/start-hadoop.sh
用 bash 执行一个叫 start-hadoop.sh 的 shell 脚本,路径是 /scripts/hadoop/start-hadoop.sh。
Shell 脚本 就是一种写在文件里的“命令集合”,让你可以批量自动执行一堆命令,相当于给电脑写的“任务清单”
Shell命令行解释器
bash---Bourne Again Shell,是 Linux 和 macOS 等操作系统中默认的 命令行解释器Shell 是一个统称,bash 是最常用的一种 Shell
使用 IntelliJ IDEA 创建一个用于开发 Hadoop HDFS 程序的 Java 工程

创建 HDFS 目录
CreateDir 类的功能是:
根据用户输入的目录路径,在 HDFS 上创建对应目录
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import java.util.Scanner;
import java.net.URI;
public class CreateDir {
public static void main(String[] args) {
try {
Scanner sc = new Scanner(System.in);
String dirPath = '/'+sc.next();
FileSystem fs = FileSystem.get(new URI("hdfs://master:9000"), new Configuration());
Path hdfsPath = new Path(dirPath);
if(fs.mkdirs(hdfsPath)){
System.out.println("Directory "+ dirPath +" has been created successfully!");
}
}catch(Exception e) {
e.printStackTrace();
}
}
}
程序所需的库:
-
Configuration:Hadoop 的配置类------用来加载 Hadoop 的配置信息,不写这个,后面就无法配置和连接 HDFS -
FileSystem:HDFS 的客户端接口,操作文件系统----Java 和 HDFS 之间的“桥梁” -
Path:代表 HDFS 路径的对象-----HDFS 路径必须用这个Path类来表示,不能用普通的字符串 -
Scanner:获取用户输入--Java 自带的输入类 -
URI:统一资源标识符,用来描述 Hadoop 的主节点地址
main 方法中 try-catch,用于捕获异常
public static void main(String[] args)-----Java 程序的主入口,程序从这里开始执行
Scanner sc = new Scanner(System.in);
创建一个扫描器,从控制台读取用户输入
String dirPath = "/" + sc.next(); // 字符串拼接
一个标准的 HDFS 路径
FileSystem fs = FileSystem.get(new URI("hdfs://master:9000"), new Configuration());
获取一个 HDFS 文件系统对象 fs,并且使它能够与 Hadoop 集群中的 HDFS 进行交互
FileSystem 是一个 Hadoop API 中的类,代表了一个文件系统。它定义了和文件系统交互的各种方法,例如上传、下载文件、创建目录、删除文件等操作。
-
"hdfs://master:9000":HDFS 的主节点地址(master 是主机名)。 Hadoop 启动后暴露给客户端的访问地址。new URI(...)是用来创建一个 URI 对象,URI 是统一资源标识符(Uniform Resource Identifier)的缩写,用来标识一个资源的位置。在这里,URI 用来标识 Hadoop 集群中的 HDFS 地址 -
new Configuration():创建 Hadoop 的配置对象,加载默认配置
FileSystem.get() 是 静态方法,用来获取一个 FileSystem 实例(对象)。这个方法的作用是:通过指定 URI 和 Hadoop 配置来建立与 HDFS 的连接
Path hdfsPath = new Path(dirPath);
将路径封装为 Path 对象--------HDFS 的 API 都需要传 Path 对象,而不是字符串
public boolean mkdirs(Path f) throws IOException
public:这是一个公开的方法,外部代码可以调用。
boolean:返回值是布尔类型 ——true表示创建成功,false表示失败。
mkdirs:方法名,意思是“创建目录”(make directories)。
Path f:传入的参数是一个 Hadoop 的Path对象,表示要创建的目录路径。
throws IOException:可能会抛出 IO 异常,比如 HDFS 无法连接、路径非法等
if(fs.mkdirs(hdfsPath)){
System.out.println("Directory "+ dirPath +" has been created successfully!");
}
-
fs.mkdirs()方法创建目录。 -
mkdirs()不仅可以创建目录,还可以自动创建不存在的父目录(递归创建)
目录存在性判断
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import java.util.Scanner;
import java.net.URI;
public class DirExist {
public static void main(String[] args) {
try {
Scanner sc = new Scanner(System.in);
String dirName = '/'+sc.next();
FileSystem fs = FileSystem.get(new URI("hdfs://master:9000"), new Configuration());
if(fs.exists(new Path(dirName ))) {
System.out.println("Directory Exists!");
} else {
System.out.println("Directory not Exists!");
}
}catch(Exception e) {
e.printStackTrace();
}
}
}
exists 方法用于检查指定的路径是否存在
-
new Path(dirName)将用户输入的目录路径转换成 Hadoop 的Path对象。 -
fs.exists(new Path(dirName))检查该路径在 HDFS 上是否存在。
列出目录中的内容
listStatus 方法---该方法用于列出指定目录下的所有文件和子目录的详细信息
Path f:参数 f 是一个 Path 对象,表示你要查看的目录路径
返回值 FileStatus[]:方法返回一个 FileStatus 数组,FileStatus 对象封装了目录下每个文件或子目录的详细信息
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileStatus;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.FileUtil;
import org.apache.hadoop.fs.Path;
import java.net.URI;
import java.util.Scanner;
public class ListFiles {
public static void main(String[] args) {
try {
Scanner sc = new Scanner(System.in);
String filePath = sc.next(); // 读取用户输入的目录路径
FileSystem fs = FileSystem.get(new URI("hdfs://master:9000"), new Configuration()); // 获取 FileSystem 对象
Path srcPath = new Path(filePath); // 创建指定路径的 Path 对象
FileStatus[] stats = fs.listStatus(srcPath); // 列出该目录下所有文件/子目录的 FileStatus 数组
Path[] paths = FileUtil.stat2Paths(stats); // 将 FileStatus 转换为 Path 数组
for (Path p : paths) // 遍历并输出每个文件或子目录的名称
System.out.println(p.getName()); // 输出文件/子目录的名称
} catch (Exception e) {
e.printStackTrace(); // 异常处理
}
}
}
相关类:
FileStatus:表示文件或目录的详细信息
FileUtil:工具类,包含一些有用的静态方法
用户输入的路径会存储在 filePath 变量中
sc.next() 是使用 Scanner 类来读取用户输入的一种方式。具体来说,next() 方法用于获取用户输入的下一个完整的单词(以空格、换行等为分隔符)。
sc.next() 会读取第一个“词”
调用 fs.listStatus() 方法获取指定路径下的所有文件和子目录的 FileStatus 数组
FileUtil.stat2Paths() 方法将 FileStatus 数组转换为 Path 数组。这样,我们就可以通过 Path 数组来进一步操作和输出文件/目录的路径
for (Path p : paths)
System.out.println(p.getName());
使用 for 循环遍历 Path[] 数组,调用 getName() 方法输出每个文件或子目录的名称
删除目录
delete(Path f, boolean recursive):该方法用于删除 HDFS 上的文件或目录
-
f:表示要删除的文件或目录的路径,类型为Path对象。 -
recursive:这是一个布尔值。true表示如果要删除的是一个目录,并且该目录中有子文件或子目录,则递归删除所有内容。false表示仅删除目录本身(前提是目录为空),如果目录非空,删除操作将失败
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import java.net.URI;
import java.util.Scanner;
public class DeleteDir {
public static void main(String[] args) {
try {
Scanner sc = new Scanner(System.in);
String dirPath = '/' + sc.next(); // 读取用户输入的目录路径
FileSystem fs = FileSystem.get(new URI("hdfs://master:9000"), new Configuration()); // 获取 HDFS 文件系统实例
Path hdfsPath = new Path(dirPath); // 创建 Path 对象,表示目录路径
if (fs.delete(hdfsPath, true)) { // 删除目录,递归删除目录中的内容
System.out.println("Directory " + dirPath + " has been deleted successfully!");
}
} catch (Exception e) {
e.printStackTrace(); // 异常处理
}
}
}
创建文件
create 方法主要用于在 HDFS 上创建文件。不同的重载方法具有不同的参数,可以控制文件创建时的行为,比如是否覆盖、使用的缓冲区大小、块大小、是否报告进度、设置副本数量等
各种重载方法及其参数说明:
public FSDataOutputStream create(Path f) throws IOException根据给定路径
f创建一个文件。如果文件已存在,会抛出异常
f:文件的路径。返回值:返回一个
FSDataOutputStream对象,可以用来写入数据。
public FSDataOutputStream create(Path f, boolean overwrite) throws IOException根据路径
f创建文件,overwrite参数指定如果文件已存在,是否覆盖。
overwrite:如果true,文件已存在则覆盖;如果false,则不覆盖,抛出异常。
public FSDataOutputStream create(Path f, Progressable progress) throws IOException创建文件并在创建过程中报告进度。
progress:一个Progressable对象,用于报告文件创建进度。返回值:返回一个
FSDataOutputStream对象。
public FSDataOutputStream create(Path f, short replication) throws IOException创建文件,并设置文件的副本数量。
replication:文件块的副本数量
public FSDataOutputStream create(Path f, short replication, Progressable progress) throws IOException创建文件,设置副本数量,并报告文件创建进度。
replication:文件副本数量。
progress:用于报告进度的Progressable对象。
public FSDataOutputStream create(Path f, boolean overwrite, int bufferSize) throws IOException创建文件,设置是否覆盖,以及缓冲区大小。
overwrite:是否覆盖已存在的文件。
bufferSize:缓冲区的大小。
public FSDataOutputStream create(Path f, boolean overwrite, int bufferSize, Progressable progress) throws IOException创建文件,设置是否覆盖、缓冲区大小,并报告进度。
overwrite:是否覆盖已存在的文件。
bufferSize:缓冲区大小。
progress:报告进度的Progressable对象。
public FSDataOutputStream create(Path f, boolean overwrite, int bufferSize, short replication, long blockSize) throws IOException创建文件,设置是否覆盖、缓冲区大小、副本数量和块大小。
overwrite:是否覆盖已存在的文件。
bufferSize:缓冲区大小。
replication:文件副本数量。
blockSize:文件的块大小。
public FSDataOutputStream create(Path f, boolean overwrite, int bufferSize, short replication, long blockSize, Progressable progress) throws IOException创建文件,设置是否覆盖、缓冲区大小、副本数量、块大小,并报告进度。
overwrite:是否覆盖已存在的文件。
bufferSize:缓冲区大小。
replication:文件副本数量。
blockSize:文件块大小。
progress:报告进度的Progressable对象
public abstract FSDataOutputStream create(Path f, FsPermission permission, boolean overwrite, int bufferSize, short replication, long blockSize, Progressable progress) throws IOException创建文件,并设置文件权限、是否覆盖、缓冲区大小、副本数量、块大小、以及进度报告。
permission:文件的权限设置。
overwrite:是否覆盖已存在的文件。
bufferSize:缓冲区大小。
replication:副本数量。
blockSize:块大小。
progress:报告进度的Progressable对象。
public FSDataOutputStream create(Path f, FsPermission permission, EnumSet<CreateFlag> flags, int bufferSize, short replication, long blockSize, Progressable progress) throws IOException创建文件,设置权限、文件创建标志、缓冲区大小、副本数量、块大小和进度报告。
permission:文件权限。
flags:文件创建标志。
bufferSize:缓冲区大小。
replication:副本数量。
blockSize:块大小。
progress:报告进度的Progressable对象。
public FSDataOutputStream create(Path f, FsPermission permission, EnumSet<CreateFlag> flags, int bufferSize, short replication, long blockSize, Progressable progress, Options.ChecksumOpt checksumOpt) throws IOException创建文件,设置权限、文件创建标志、缓冲区大小、副本数量、块大小、进度报告以及校验和选项。
permission:文件权限。
flags:文件创建标志。
bufferSize:缓冲区大小。
replication:副本数量。
blockSize:块大小。
progress:报告进度的Progressable对象。
checksumOpt:校验和选项
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import java.net.URI;
import java.util.Scanner;
public class CreateFile {
public static void main(String[] args) {
try {
Scanner sc = new Scanner(System.in); // 1. 创建Scanner对象,用于读取用户输入
String filePath = '/'+sc.next(); // 2. 获取用户输入的文件路径,并加上前缀‘/’构成完整路径
FileSystem fs = FileSystem.get(new URI("hdfs://master:9000"), new Configuration()); // 3. 获取HDFS文件系统实例
Path hdfsPath = new Path(filePath); // 4. 创建Path对象,表示文件的路径
fs.create(hdfsPath); // 5. 使用FileSystem实例在HDFS上创建文件
} catch (Exception e) { // 6. 异常处理
e.printStackTrace(); // 输出异常信息
}
}
}
文件存在性判断
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import java.net.URI;
import java.util.Scanner;
public class FileExist {
public static void main(String[] args) {
try {
Scanner sc = new Scanner(System.in); // 1. 创建Scanner对象,用于读取用户输入
String fileName = '/'+sc.next(); // 2. 获取用户输入的文件路径,并加上前缀‘/’构成完整路径
FileSystem fs = FileSystem.get(new URI("hdfs://master:9000"), new Configuration()); // 3. 获取HDFS文件系统实例
if (fs.exists(new Path(fileName))) { // 4. 判断文件是否存在
System.out.println("File Exists!"); // 5. 如果文件存在,输出提示信息
} else {
System.out.println("File not Exists!"); // 6. 如果文件不存在,输出提示信息
}
} catch (Exception e) { // 7. 异常处理
e.printStackTrace(); // 输出异常信息
}
}
}
FileSystem.exists(Path f) 方法,判断文件路径所指向的文件是否存在
exists() 方法会返回一个布尔值。如果路径所指向的文件存在,返回 true;否则返回 false
文件写
HDFS 不支持文件的随机写操作,只能顺序写入数据
-
创建文件并写入数据:使用
create()方法创建文件并将数据写入文件。如果文件已存在,可以选择覆盖或追加。 -
文件已存在,追加数据:使用
append()方法将数据追加到文件的尾部
FileSystem.create()方法
public FSDataOutputStream create(Path f, boolean overwrite, int bufferSize, short replication, long blockSize)如果文件不存在,则创建文件并返回一个输出流
FSDataOutputStream。如果文件已经存在,可以选择是否覆盖。overwrite: 是否覆盖已存在的文件(true表示覆盖)。
bufferSize: 缓冲区大小,单位是字节。
replication: 文件的副本数量,通常设为1。
blockSize: 文件块的大小,这里用1 << 26(即64MB)来设置块大小。
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FSDataOutputStream;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import java.net.URI;
import java.util.Scanner;
public class WriteFile {
public static void main(String[] args) {
try {
// 创建Scanner对象,用于从控制台读取输入
Scanner sc = new Scanner(System.in);
// 获取用户输入的文件路径,并为其加上前缀'/',使其成为绝对路径
String filePath = '/'+sc.next();
// 获取HDFS文件系统的实例
FileSystem fs = FileSystem.get(new URI("hdfs://master:9000"), new Configuration());
// 创建Path对象,表示文件的路径
Path srcPath = new Path(filePath);
// 第一部分:使用create方法创建文件并写入数据
FSDataOutputStream os = fs.create(srcPath, true, 1024, (short) 1, (long)(1 << 26)); // 创建文件,返回输出流
String str = "Hello, this is a sentence that should be written into the file.\n"; // 待写入文件的字符串
os.write(str.getBytes()); // 将字符串写入文件
os.flush(); // 将内存中的数据刷新到文件
os.close(); // 关闭流,完成文件的写入
// 第二部分:使用append方法向已有文件中追加数据
os = fs.append(srcPath); // 打开文件,并定位到文件尾部
str = "Hello, this is another sentence that should be written into the file.\n"; // 待追加的字符串
os.write(str.getBytes()); // 将字符串写入文件
os.flush(); // 将内存中的数据刷新到文件
os.close(); // 关闭流,完成数据的追加
} catch (Exception e) {
e.printStackTrace(); // 捕获并打印异常
}
}
}
FSDataOutputStream.write() 方法
将字节数组写入文件。os.write(str.getBytes()) 会将字符串 str 转换为字节数组,并将其写入文件。
FSDataOutputStream.flush() 方法
将内存中缓冲的数据刷新到磁盘上。通常在写入数据后调用此方法,以确保数据写入文件系统。
FSDataOutputStream.close() 方法
关闭流,释放资源。每次完成写操作后,应该调用 close() 来确保文件写操作的完成。
文件读
FileSystem.open() 方法
public FSDataInputStream open(Path f) throws IOException
打开指定路径的文件,返回一个 FSDataInputStream 对象,可以利用该对象读取文件的内容。
FSDataInputStream.readLine() 方法
逐行读取文件内容。每次调用 readLine(),返回的是文件的一行内容。若没有更多内容,返回 null。
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FSDataInputStream;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import java.net.URI;
import java.util.Scanner;
public class ReadFile {
public static void main(String[] args) {
try {
// 创建Scanner对象,读取用户输入的文件路径
Scanner sc = new Scanner(System.in);
String filePath = '/'+sc.next(); // 获取用户输入的文件路径,路径前加上'/'
// 获取HDFS文件系统的实例
FileSystem fs = FileSystem.get(new URI("hdfs://master:9000"), new Configuration());
// 创建Path对象,表示HDFS中文件的路径
Path srcPath = new Path(filePath);
// 使用open方法打开文件,返回一个FSDataInputStream对象
FSDataInputStream is = fs.open(srcPath);
// 循环读取文件内容,直到文件末尾
while (true) {
String line = is.readLine(); // 逐行读取
if (line == null) { // 如果读取到文件末尾,则退出循环
break;
}
System.out.println(line); // 打印每一行
}
// 关闭输入流
is.close();
} catch (Exception e) {
e.printStackTrace(); // 捕获异常并打印堆栈信息
}
}
}
文件重命名
public abstract boolean rename(Path src, Path dst) throws IOException
rename将路径 src (原始路径)重命名为路径 dst(目标路径)
import org.apache.hadoop.conf.Configuration; // 导入Hadoop的配置类
import org.apache.hadoop.fs.FileSystem; // 导入HDFS文件系统类
import org.apache.hadoop.fs.Path; // 导入Path类,用于表示HDFS路径
import java.net.URI; // 导入URI类,用于定位HDFS路径
import java.util.Scanner; // 导入Scanner类,用于接收用户输入
public class Rename {
public static void main(String[] args) {
try {
// 创建Scanner对象,从控制台读取用户输入
Scanner sc = new Scanner(System.in);
// 从控制台读取源文件名,并加上'/'构造成HDFS中的绝对路径
String srcStrPath = '/' + sc.next(); // 例如输入 oldfile.txt,结果为 /oldfile.txt
// 从控制台读取目标文件名,并加上'/'构造成HDFS中的绝对路径
String dstStrPath = '/' + sc.next(); // 例如输入 newfile.txt,结果为 /newfile.txt
// 创建FileSystem对象,连接到HDFS(这里使用的是主机名为master,端口为9000)
FileSystem fs = FileSystem.get(new URI("hdfs://master:9000"), new Configuration());
// 构造源路径和目标路径的Path对象
Path srcPath = new Path(srcStrPath);
Path dstPath = new Path(dstStrPath);
// 使用rename方法进行文件重命名操作
if (fs.rename(srcPath, dstPath)) {
// 如果重命名成功,输出提示信息
System.out.println("rename from " + srcStrPath + " to " + dstStrPath + " successfully!");
} else {
// 如果重命名失败,输出失败提示
System.out.println("Failed to rename " + srcStrPath + " to " + dstStrPath);
}
} catch (Exception e) {
// 捕获并打印所有异常信息,避免程序崩溃
e.printStackTrace();
}
}
}
文件删除
public abstract boolean delete(Path f, boolean recursive) throws IOException
删除 HDFS 中的文件或目录
recursive:是否递归删除(若是目录且非空,必须为 true)
import org.apache.hadoop.conf.Configuration; // 导入Hadoop配置类
import org.apache.hadoop.fs.FileSystem; // 导入HDFS文件系统类
import org.apache.hadoop.fs.Path; // 导入路径类
import java.net.URI; // 导入URI类,用于表示HDFS地址
import java.util.Scanner; // 导入Scanner类,用于接收用户输入
public class DeleteFile {
public static void main(String[] args) {
try {
// 创建Scanner对象,用于从控制台读取用户输入的文件路径
Scanner sc = new Scanner(System.in);
// 从控制台读取要删除的文件路径,并加上前缀'/'构成HDFS根目录下路径
String filePath = '/' + sc.next();
// 创建FileSystem对象,连接HDFS(master为主节点,端口9000)
FileSystem fs = FileSystem.get(new URI("hdfs://master:9000"), new Configuration());
// 创建Path对象,表示要删除的HDFS路径
Path hdfsPath = new Path(filePath);
// 调用delete方法删除文件
// 第二个参数false表示非递归删除(即不能删除非空目录)
if (fs.delete(hdfsPath, false)) {
System.out.println("File " + filePath + " has been deleted successfully!");
} else {
System.out.println("Failed to delete file " + filePath + ". It may not exist.");
}
} catch (Exception e) {
// 捕获并打印异常信息
e.printStackTrace();
}
}
}
删除目录且目录非空,第二个参数必须设为 true
作业

-
Configuration:配置文件(连接 HDFS 用) -
FileSystem:代表 HDFS 文件系统对象 -
Path:代表 HDFS 或本地文件路径 -
FileStatus:描述文件或目录的状态信息
连接到 HDFS 文件系统![]()
创建 Scanner 对象,从控制台接收用户输入
![]()
进入一个无限循环,不停接收用户输入
![]()
读取用户输入的第一个单词(比如 HShell)
![]()
判断用户是不是输入了 HShell,如果是,继续解析后面的命令
读取第二个单词,比如 -cp、-rm 等操作
如果输入 -r,表示要复制目录,使用 copyFromLocalFile 拷贝整个目录到HDFS
否则就是普通的拷贝文件操作

-rm 删除文件或目录,如果是 -r,说明是要递归删除目录,
fs.delete(path, true),true代表递归删除。则删除的是单个文件,不递归
-list 查看路径信息。显示某个路径(文件或目录)的详细信息

fs.exists(Path) 方法:检查 HDFS 上是否真的存在这个路径:存在,继续查询
。如果不存在,提示路径不存在
FileStatus status = fs.getFileStatus(new Path(path));
调用
fs.getFileStatus(Path)方法,获取指定文件或目录的详细信息。返回的是一个
FileStatus对象,里面包含了很多属性:
是文件还是目录
文件大小
权限(rwx)
所有者。。。。。。。
FileStatus就像一个文件的身份证,记录了所有关键信息。
FileStatus 对象的 toString() 方法,打印出文件/目录的所有信息
-mv 移动或重命名
将源路径 src 移动或重命名到目标路径 dst。使用 fs.rename() 方法
-find 递归查找文件
递归搜索HDFS目录下,是否存在目标文件名。
调用下面定义的 findFile() 方法

如果当前是目录,递归进入子目录继续找。如果是文件,检查名字是否匹配。找到目标文件时,输出路径
私有静态方法(
private static),只能在本类中调用
FileSystem fs:已经连接好的 HDFS 文件系统对象
Path dir:当前需要搜索的目录路径
String filename:要查找的文件名
调用fs.exists(dir),检查指定目录是否存在。调用
fs.listStatus(dir)获取当前目录下的所有子文件和子目录的状态列表遍历每一个子文件/子目录
如果遇到子目录,递归查找
如果是文件,判断名字是否匹配

关闭Scanner(释放输入流)
关闭FileSystem连接(释放资源)
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.*;
import java.net.URI;
import java.util.Scanner;
public class HShell {
public static void main(String[] args) {
try {
// 连接HDFS(根据自己环境修改URI)
FileSystem fs = FileSystem.get(new URI("hdfs://master:9000"), new Configuration(), "hadoop");
Scanner sc = new Scanner(System.in);
System.out.println("欢迎使用HShell,输入命令开始操作:");
while (true) {
System.out.print("> "); // 提示符
String cmd = sc.next();
if (cmd.equals("HShell")) {
String option = sc.next();
if (option.equals("-cp")) {
String src = sc.next();
String dst = sc.next();
if (src.equals("-r")) {
// 拷贝目录
String localDir = dst;
String hdfsDst = sc.next();
fs.copyFromLocalFile(false, true, new Path(localDir), new Path(hdfsDst));
System.out.println("目录拷贝成功: " + localDir + " -> " + hdfsDst);
} else {
// 拷贝文件
fs.copyFromLocalFile(new Path(src), new Path(dst));
System.out.println("文件拷贝成功: " + src + " -> " + dst);
}
} else if (option.equals("-rm")) {
String path = sc.next();
if (path.equals("-r")) {
// 删除目录
String dir = sc.next();
if (fs.delete(new Path(dir), true)) {
System.out.println("目录删除成功: " + dir);
} else {
System.out.println("目录删除失败: " + dir);
}
} else {
// 删除文件
if (fs.delete(new Path(path), false)) {
System.out.println("文件删除成功: " + path);
} else {
System.out.println("文件删除失败: " + path);
}
}
} else if (option.equals("-list")) {
String path = sc.next();
FileStatus status = fs.getFileStatus(new Path(path));
System.out.println("路径信息:");
System.out.println(status.toString());
} else if (option.equals("-mv")) {
String src = sc.next();
String dst = sc.next();
if (fs.rename(new Path(src), new Path(dst))) {
System.out.println("移动/重命名成功: " + src + " -> " + dst);
} else {
System.out.println("移动/重命名失败: " + src);
}
} else if (option.equals("-find")) {
String fileName = sc.next();
String dirPath = sc.next();
findFile(fs, new Path(dirPath), fileName);
} else {
System.out.println("无效的操作,请重新输入!");
}
} else if (cmd.equals("exit")) {
System.out.println("退出HShell,再见!");
break;
} else {
System.out.println("命令应以 HShell 开头!");
}
}
sc.close();
fs.close();
} catch (Exception e) {
e.printStackTrace();
}
}
// 辅助方法:递归查找文件
private static void findFile(FileSystem fs, Path path, String targetName) throws Exception {
FileStatus[] statuses = fs.listStatus(path);
for (FileStatus status : statuses) {
if (status.isDirectory()) {
// 递归子目录
findFile(fs, status.getPath(), targetName);
} else {
if (status.getPath().getName().equals(targetName)) {
System.out.println("找到文件: " + status.getPath().toString());
}
}
}
}
}
可以改成switch更好
更多推荐

所有评论(0)