大数据学习栈记——HDFS命令行操作与Java API操作

HDFS是hadoop框架中的存储技术,由他来决定文件应该怎么存储在分布式集群当中,下面文章将讲述常见的HDFS操作

HDFS操作常用Shell命令

1、启动hadoop (在master上执行)

start-all.sh

mr-jobhistory-daemon.sh start historyserver

使用帮助

可以在终端输入如下命令,查看hdfs dfs总共支持哪些操作:

hdfs dfs

可以查看某个命令的作用,比如,当需要查询put命令的具体用法时,可以采用如下命令:

hdfs dfs -help put

2、目录操作

需要注意的是,Hadoop系统安装好以后,第一次使用HDFS时,需要首先在HDFS中创建用户目录。本教程全部采用hadoop用户登录Linux系统,因此,需要在HDFS中为hadoop用户创建一个用户目录,命令如下:

hdfs dfs -mkdir -p /user/hadoop

“/user/hadoop”目录就成为用户对应的用户目录,可以使用如下命令显示HDFS中与当前用户对应的用户目录下的内容:

hdfs dfs -ls .

hdfs dfs -ls /user/hadoop

如果要列出HDFS上的所有目录,可以使用如下命令:

hdfs dfs -ls

如果要列出HDFS根目录下的所有目录,可以使用如下命令:

hdfs dfs -ls /

下面,可以使用如下命令创建一个input目录(这个input目录是创建在用户目录下):

hdfs dfs -mkdir input

如果要在HDFS的根目录下创建一个名称为input的目录,则需要使用如下命令:

hdfs dfs -mkdir /input

可以使用rm命令删除一个目录,比如,可以使用如下命令删除刚才在HDFS中创建的“/input”目录(不是“/user/hadoop/input”目录):

hdfs dfs -rm -r /input

3、文件操作

首先,使用vim编辑器,在本地Linux文件系统的“/home/youka/”目录下创建一个文件myLocalFile.txt,

vim myLocalFile.txt

里面可以随意输入一些单词,比如,输入如下三行:

Hadoop
Spark
XMU DBLAB

然后,可以使用如下命令把本地文件系统的“/home/youka/myLocalFile.txt”上传到HDFS中的当前用户目录的input目录下,也就是上传到HDFS的“/user/youka/input/”目录下:

本地文件传到HDFS:

./bin/hdfs dfs -put /home/youka/myLocalFile.txt  input

可以使用ls命令查看一下文件是否成功上传到HDFS中,具体如下:

hdfs dfs -ls input

下面使用如下命令查看HDFS中的myLocalFile.txt这个文件的内容:

hdfs dfs -cat input/myLocalFile.txt

下面把HDFS中的myLocalFile.txt文件下载到本地文件系统中的“/home/youka/下载”这个目录下(注意大小写!!!),命令如下:

hdfs dfs -get input/myLocalFile.txt /home/youka/下载

可以使用如下命令,到本地文件系统查看下载下来的文件myLocalFile.txt:

cd /home/youka/下载

ls

cat myLocalFile.txt

最后,了解一下如何把文件从HDFS中的一个目录拷贝到HDFS中的另外一个目录。比如,如果要把HDFS的“/user/hadoop/input/myLocalFile.txt”文件,拷贝到HDFS的另外一个目录“/input”中(注意,这个input目录位于HDFS根目录下),可以使用如下命令:

hdfs dfs -cp input/myLocalFile.txt /input

中文的目录名,如果在Ubuntu里需要安装中文输入法,参照:

Ubuntu如何开启中文输入法?(多图教学)_ubuntu中文输入法-CSDN博客

4、利用HDFS的Web管理界面

打开浏览器,输入 http://主节点ip地址:9870/,例如我输入了http://hadoop101:9870/,可以在浏览器中查看hadoop集群的状态

里面有各种工具可以使用,例如,选择Utinities下的Browser the file system,可以看到文件系统的状态

Java操作HDFS

我们首先展现一个例题,以此为例讲述Java API操作HDFS

题目

现在要执行的任务是:假设在目录“hdfs://hadoop101:9000/user/hadoop”下面有几个文件,分别是file1.txt、file2.txt、file3.txt、file4.abc和file5.abc,这里需要从该目录中过滤出所有后缀名不为“.abc”的文件,对过滤之后的文件进行读取,并将这些文件的内容合并到文件“hdfs://hadoop101: 8020/user/hadoop/merge.txt”中。文件内容为:

备注:ip地址使用你自己的hadoop hdfs名称节点的虚拟机地址,我的名称节点是hadoop101,9000是hdfs的服务端口号。在这里可以看到hadoop的服务端口号默认是9000(我的是8020):

在IDEA中创建项目:

使用Maven的好处是不需要到处去找相关的jar文件,只需要配置好pom.xml就可以自动从中央仓库下载需要的依赖包(jar文件)。

配置pom.xml

通过使用Java API操作HDFS_使用java api读取hdfs的数据-CSDN博客 发现需要配置三个依赖Apache Hadoop Common、Apache Hadoop HDFS、Apache Hadoop Client(还有一个Junit是做单元测试用的,暂时可以不用),先去下面这个网站看看有哪些可用的版本,以及配置文件应该怎么写

https://mvnrepository.com/

搜索Apache Hadoop Common

打开找到的第一个Apache Haddoop Common,查看版本号,最新版是3.3.6

点击3.3.6,查看详情

里面有Maven的配置语句,等会儿我们要用

<!-- https://mvnrepository.com/artifact/org.apache.hadoop/hadoop-common -->
<dependency>
    <groupId>org.apache.hadoop</groupId>
    <artifactId>hadoop-common</artifactId>
    <version>3.3.6</version>
</dependency>

再搜索Apache Hadoop HDFS,

最新版本也是3.3.6,同样方法查看详情

配置代码如下:

<!-- https://mvnrepository.com/artifact/org.apache.hadoop/hadoop-hdfs -->
<dependency>
    <groupId>org.apache.hadoop</groupId>
    <artifactId>hadoop-hdfs</artifactId>
    <version>3.3.6</version>
    <scope>test</scope>
</dependency>

再找到Apache Hadoop Client

配置代码如下:

<!-- https://mvnrepository.com/artifact/org.apache.hadoop/hadoop-client -->
<dependency>
    <groupId>org.apache.hadoop</groupId>
    <artifactId>hadoop-client</artifactId>
    <version>3.3.6</version>
</dependency>

在IDEA中,打开pom.xml(在左边的树形菜单中),这个文件是Maven的核心配置文件

配置dependency,添加内容

相关的包没有下载,所以Maven还认不出来。

刷新一下Maven,让Maven从中央仓库把相关的jar包下载下来,刷新按钮在右上角。

一般来说,你的maven会卡住,这是因为国内访问maven速度很慢,可以配置阿里云镜像,由于我已经配置了,这里就不再多说,可以参考网上的做法

点击右侧的Maven,展开Dependencies,可以看到三个依赖包已经导入进来了:

使用HDFS的Java API 实现文件操作

Hadoop中常用的Java API

先写一个测试类,看看能不能正确操作HDFS,这个测试类主要模仿

https://blog.csdn.net/HMLieder/article/details/128041615

输入下列代码:

package HDFS_API;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;

import java.net.URI;

public class CreateFileOnHDFS {
    public static void main(String[] args) throws Exception {
        // 创建Configuration类的对象,用于HDFS配置
        Configuration conf = new Configuration();
        // 定义uri字符串
        String uri = "hdfs://hadoop101:8020";
        // 创建文件系统
        FileSystem fs = FileSystem.get(new URI(uri), conf);
        // 创建路径对象(文件或者目录)
        Path path = new Path(uri + "/input/hadoop.txt");
        // 创建文件
        boolean result = fs.createNewFile(path);
        if (result) {
            System.out.println("文件[" + path + "创建成功!");
        } else {
            System.out.println("文件[" + path + "创建失败!");
        }

    }
}

检查异常的堆栈,第一条是这样的问题,看来是权限的问题,这里需要有用户名的变量定义,才能正确连接

package HDFS_API;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;

import java.net.URI;

public class CreateFileOnHDFS {
    public static void main(String[] args) throws Exception {
        Configuration conf = new Configuration();
        String uri = "hdfs://hadoop101:8020";
        String user = "root";
        FileSystem fs = FileSystem.get(new URI(uri), conf, user);

        // 先创建父目录
        Path inputDir = new Path("/input");
        if (!fs.exists(inputDir)) {
            fs.mkdirs(inputDir);
        }

        // 然后创建文件
        Path path = new Path("/input/hadoop.txt");
        boolean result = fs.createNewFile(path);
        if (result) {
            System.out.println("文件[" + path + "]创建成功!");
        } else {
            System.out.println("文件[" + path + "]创建失败!");
        }
    }
}

运行成功

利用HDFS集群WebUI查看成功创建文件

再写一个Java程序,把本地文件上传到hadoop集群中:

package HDFS_API;

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 org.apache.hadoop.io.IOUtils;

import java.io.FileInputStream;
import java.net.URI;

public class WriteFileOnHDFS {
    public static void main(String[] args) throws Exception {
        // 创建Configuration类的对象,用于HDFS配置
        Configuration conf = new Configuration();
        // 定义uri字符串
        String uri = "hdfs://hadoop101:8020";
        // 创建文件系统
        String user = "root";
        FileSystem fs = FileSystem.get(new URI(uri), conf, user);
        // 创建路径对象(文件或者目录)
        Path path = new Path(uri + "/input/word.txt");
        // 创建文件输出流
        FSDataOutputStream out = fs.create(path);
        // 创建文件输入流
        FileInputStream in = new FileInputStream("D:\\BaiduNetdiskDownload\\Spark\\spark-3.4.1-bin-hadoop3\\bin\\input\\word.txt");
        // 使用工具类IOUtils来完成文件的相关操作
        IOUtils.copyBytes(in, out, conf);
        System.out.println("word.txt写入[" + path + "]!");
        // 关闭相关对象,节约系统资源
        in.close();
        out.close();
        fs.close();
    }
}

可能会遇到的问题(我都没有遇到过):(1)权限问题;(2)域名解析问题

在C:\Windows\System32\drivers\etc目录下找到hosts文件进行修改

使用Web UI时,hadoop不知道我们是哪个用户,用这里的方法解决一下

https://blog.csdn.net/weixin_51967583/article/details/121214812

Unbuntu shell命令

cd /usr/local/hadoop-3.3.6/etc/hadoop

vim core-site.xml

core-site.xml配置代码:

<property>
  <name>hadoop.http.staticuser.user</name>
  <value>root</value>
</property>
<property>
  <name>dfs.permissions.enabled</name>
  <value>false</value>
</property>

如果没有问题,在web端查看,成功上传

继续完成程序要求:

先在客户端创建file1 file2 file3,先利用Web UI上传这几个文件到指定的目录。这里我一开始上传失败了

与教程相同,这里是由于/user/hadoop权限不够导致,在Linux中执行:

dfs dfs -chmod 777 /user/hadoop

随后上传成功

编写代码

package HDFS_API;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.*;
// import org.apache.hadoop.io.IOUtils;

// import java.io.FileInputStream;
import java.io.PrintStream;
import java.net.URI;

/**
 * 过滤掉文件名满足特定条件的文件
 */
class MyPathFilter implements PathFilter {
    String reg;

    MyPathFilter(String reg) {
        this.reg = reg;
    }

    public boolean accept(Path path) {
        return !(path.toString().matches(reg));
    }
}

public class MergeFile {
    public static void main(String[] args) throws Exception {
        // 创建Configuration类的对象,用于HDFS配置
        Configuration conf = new Configuration();
        // 定义uri字符串
        String uri = "hdfs://hadoop101:8020";
        // 创建文件系统
        String user = "root";
        FileSystem fs = FileSystem.get(new URI(uri), conf, user);
        // 创建路径对象(文件或者目录),inputPath为输入路径,outputPath为输出路径
        Path inputPath = new Path(uri + "/user/hadoop");
        Path outputPath = new Path(uri + "/user/hadoop/merge.txt");

        // 列出输入路径下的所有文件,并用MyPathFilter进行过滤,".*\\.abc"为过滤用的正则表达式
        FileStatus[] sourceStatus = fs.listStatus(inputPath, new MyPathFilter(".*\\.abc"));

        // 为“hdfs://192.168.70.100:9000/user/hadoop/merge.txt”创建一个输出流
        FSDataOutputStream fsdos = fs.create(outputPath);

        PrintStream ps = new PrintStream(System.out);

        // 遍历输入目录下每一个符合要求的文件
        for (FileStatus sta : sourceStatus) {
            System.out.print("\n路径:" + sta.getPath() + " 文件大小:" + sta.getLen() + " 权限:" + sta.getPermission() + " 内容:");
            // 为每一个符合要求的文件创建一个输入流
            FSDataInputStream fsdis = fs.open(sta.getPath());
            // 创建字符缓冲区
            byte[] data = new byte[1024];
            int read;
            // 如果输入流读取的字符长度>0,就用输出流写到merge.txt中去,同时在本地控制台中输出结果
            while ((read = fsdis.read(data)) > 0) {
                ps.write(data, 0, read);
                fsdos.write(data, 0, read);
            }
            fsdis.close();
        }
        ps.close();
        fsdos.close();
    }
}

运行成功

WebUI发现已经创建了“merge.txt”文件

在命令行显示正确

### HDFS 文件操作的技术原理应用 #### 1. HDFS 的基本概念 Hadoop分布式文件系统(HDFS, Hadoop Distributed File System)是一种高容错性的分布式存储系统,设计用于运行在廉价硬件上。它提供了高吞吐量的数据访问机制,非常适合大规模数据分析场景[^1]。 #### 2. 移动文件的操作原理 当执行 `hdfs dfs -mv` 命令时,实际上是通过修改元数据的方式完成文件的移动操作。具体来说,在 HDFS 中,文件的实际数据块不会被物理复制或重新分配,而是更新 NameNode 上关于该文件的位置信息。这种操作非常高效,因为它仅涉及少量的元数据更改而非实际数据传输。 以下是实现此功能的一个 Java API 示例代码片段: ```java import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.FileSystem; import org.apache.hadoop.fs.Path; public class HDFSMoveFile { public static void main(String[] args) throws Exception { Configuration conf = new Configuration(); FileSystem fs = FileSystem.get(conf); Path sourcePath = new Path("/source/path/to/text.txt"); Path destPath = new Path("/destination/path/to/text2.txt"); boolean isMoved = fs.rename(sourcePath, destPath); if (isMoved) { System.out.println("File moved successfully."); } else { System.out.println("Failed to move the file."); } fs.close(); } } ``` 上述代码展示了如何利用 Hadoop 提供的 Java API 来完成文件从源路径到目标路径的移动操作[^2]。 #### 3. 文件冲突处理策略 对于上传文件时可能存在的同名文件问题,可以通过配置参数决定是否覆盖已有文件或者将其追加至现有文件末尾。例如,在命令行工具中可以使用 `-f` 参数强制覆盖已有的文件;而在程序开发过程中则需显式调用相应方法来控制行为逻辑。 #### 4. 下载文件并解决命名冲突 当尝试将远程 HDFS 上的某个文件下载到本地磁盘时,如果发现两者具有相同的名称,默认情况下会引发错误提示。为了避免这种情况发生,开发者可以在编写应用程序时加入额外判断条件——一旦检测到潜在冲突即动态调整最终保存下来的副本名字。 #### 5. 输出文件详情及目录遍历 为了获取单个文件的具体属性比如大小、最后修改日期等基本信息以及整个子树结构中的所有条目列表连带它们各自的描述性字段集合,可借助FileSystem类里的listStatus()函数达成目的。 下面给出一段简单的伪代码表示这一过程: ```java // 获取当前工作区下的全部项... RemoteIterator<LocatedFileStatus> ite = fs.listFiles(new Path("."), true); while(ite.hasNext()) { LocatedFileStatus status = ite.next(); // 打印每一个对象的相关特性值. System.out.printf("%s %d bytes\n",status.getPath(),status.getLen()); } ``` 以上列举了几种常见的针对HDFS所支持的基础级交互动作及其背后蕴含的工作机理概述. ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值