百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 热门文章 > 正文

这个很实用,JAVA操作HDFS工具类

bigegpt 2024-09-24 07:21 3 浏览

一、HDFSUtil工具类补充

删除文件
 /**
 * 删除某一路径
 * @param path 需要删除的路径
 * @param recursive 指定为true删除目录中全部文件,false时可以删除空目录和单个文件
 * @return
 */
 public boolean delete(String path, boolean recursive) {
 boolean result = false;
 if(recursive) {
 try {
 result = fs.delete(new Path(path), true);
 } catch (Exception e) {
 e.printStackTrace();
 result = false;
 }
 return result;
 }else{
 try {
 result = fs.delete(new Path(path), false);
 } catch (Exception e) {
 e.printStackTrace();
 result = false;
 } 
 return result;
 }
 }

获取某一路径下的文件信息
/**
 * 获得某一路径下的文件信息
 * @param path 待查看路径
 * @return 文件信息列表-包含文件类型,文件大小,所有者,所在组,文件名称
 */
 public List<String> getFileInfo(String path){
 List<String> infos = new ArrayList<>();
 try {
 // 通过FileSystem获得某一路径下的文件状态列表
 FileStatus[] fileStatus = fs.listStatus(new Path(path));
 for (FileStatus temp : fileStatus) {
 String info = "";
 // 判断文件类型
 if (temp.isDirectory()) {
 info += "目录\t" + "0" + "\t";
 }else {
 info += "文件\t" + sizeFormat(temp.getLen()) + "\t";
 }
 // 拼接文件信息
 info += temp.getOwner() + "\t" + temp.getGroup() + "\t" + temp.getPath().getName();
 infos.add(info);
 }
 } catch (Exception e) {
 e.printStackTrace();
 }
 return infos;
 }

文件大小单位换算
/**
 * 文件大小单位换算
 * @param length 默认获得的文件大小单位为Byte-字节
 * @return 使用1024进行换算
 */
 private String sizeFormat(long length) {
 long result = length;
 // 不足1024则单位为Byte
 if (result / 1024 == 0) {
 return result + "B";
 }else {
 result /= 1024;
 // 不足1024*1024则单位为KB,否则为MB
 if (result / 1024 == 0) {
 return result + "KB";
 }else {
 return result / 1024 + "MB";
 }
 }
 }

将本地文件内容写入HDFS文件中
  • create():覆盖原文件
  • append():直接在原文件基础上进行追加
/**
 * 将本地磁盘文件内容写入HDFS文件中
 * @param src 源文件路径
 * @param parentDir 目标文件父级目录
 * @param fileName 目标文件名称
 * @param overwrite 是否覆盖写入
 * @return
 */
 public boolean write(String src,String parentDir,String fileName,boolean overwrite) {
 // 判断源文件是否存在,如不存在则直接返回
 if (!new File(src).exists()) {
 System.out.println("源文件不存在");
 return false;
 }
 FSDataOutputStream fsDataOutputStream = null;
 boolean isDir = false;
 try {
 // 由于HDFS的特殊性,必须保证父级路径是一个目录,而不能只判断是否存在
 isDir = fs.isDirectory(new Path(parentDir));
 } catch (Exception e) {
 e.printStackTrace();
 }
 if (!isDir) {// false -> 可能为文件也可能不存在
 try {
 // 尝试创建父级目录
 fs.mkdirs(new Path(parentDir));
 } catch (Exception e) {
 // 出现异常说明该路径下已经存在了文件 - 与目标文件夹文件相同
 e.printStackTrace();
 System.out.println("该路径不可用");
 return false;
 }
 }
 Path destPath = new Path(parentDir + File.separator + fileName);
 if (overwrite) {
 try {
 // 覆盖写入时使用create方法进行创建,指定覆盖参数为true
 fsDataOutputStream = fs.create(destPath,true);
 } catch (Exception e) {
 e.printStackTrace();
 }
 }else {
 try {
 // 保证文件一定存在,如果已经存在返回false,不会重新创建
 fs.createNewFile(destPath);
 // 追加写入时使用append方法进行创建
 fsDataOutputStream = fs.append(destPath);
 } catch (Exception e) {
 e.printStackTrace();
 }
 }
 // 初始化输入流,指定编码
 BufferedReader bufferedReader = null;
 Writer writer = null;
 try {
 bufferedReader = new BufferedReader(new InputStreamReader(new FileInputStream(new File(src)), "UTF-8"));
 writer = new OutputStreamWriter(fsDataOutputStream, "UTF-8");
 } catch (Exception e) {
 e.printStackTrace();
 }
 BufferedWriter bufferedWriter = new BufferedWriter(writer);
 String temp = "";
 int line = 0;
 try {
 while((temp = bufferedReader.readLine()) != null) {
 bufferedWriter.write(temp);
 bufferedWriter.newLine();
 line ++;
 // 每一千行写入一次数据
 if (line % 1000 == 0) {
 bufferedWriter.flush();
 }
 }
 } catch (IOException e) {
 e.printStackTrace();
 return false;
 }
 try {
 bufferedWriter.flush();
 bufferedWriter.close();
 writer.close();
 bufferedReader.close();
 fsDataOutputStream.close();
 } catch (IOException e) {
 e.printStackTrace();
 return false;
 }
 return true;
 }

读取HDFS中的文件内容
/**
 * 从指定文件中读取数据
 * @param path HDFS路径
 */
 public void read(String path) {
 try {
 // 使用open方法获得一个输入流
 FSDataInputStream fsDataInputStream = fs.open(new Path(path));
 // 使用缓冲流读取文件内容
 BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(fsDataInputStream, "UTF-8"));
 String temp = "";
 while ((temp = bufferedReader.readLine()) != null) {
 System.out.println(temp);
 }
 bufferedReader.close();
 fsDataInputStream.close();
 } catch (Exception e) {
 e.printStackTrace();
 }
 }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

二、PropertiesUtil工具类

此工具类作用是获取properties中的配置

import java.io.IOException;
import java.util.Properties;
public class PropertiesUtil {
 private String fileName;
 private Properties properties = new Properties();
 public PropertiesUtil(String fileName) {
 this.fileName = fileName;
 open();
 }
 private void open() {
 try {
 properties.load(Thread.currentThread().getContextClassLoader().getResourceAsStream(fileName));
 } catch (IOException e) {
 e.printStackTrace();
 }
 }
 public String readPropertyByKey(String key) {
 return properties.getProperty(key);
 }
}

三、RemoteUtil工具类

此工具类的作用是直接通过传入hdfs语句对hdfs进行操作

注意事项:

  1. 通过SSH的工具类实现命令执行时需要将命令的全路径写出
  2. 远程登录需要导入ganymed-ssh2.jar包
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import org.apache.commons.lang.StringUtils;
import ch.ethz.ssh2.Connection;
import ch.ethz.ssh2.Session;
import ch.ethz.ssh2.StreamGobbler;
public class RemoteUtil {
 private static String DEFAULTCHART = "UTF-8";
 private Connection conn;
 private String host;
 private String userName;
 private String userPwd;
 public RemoteUtil(String host, String userName, String userPwd) {
 this.host = host;
 this.userName = userName;
 this.userPwd = userPwd;
 }
 // 登录
 public Boolean login() {
 boolean flg = false;
 try {
 conn = new Connection(host);
 conn.connect();// 连接
 flg = conn.authenticateWithPassword(userName, userPwd);// 认证
 } catch (IOException e) {
 e.printStackTrace();
 }
 return flg;
 }
 // 执行操作
 public String execute(String cmd) {
 String result = "";
 try {
 if (login()) {
 System.out.println("登录成功");
 Session session = conn.openSession();// 打开一个会话
 session.execCommand(cmd);// 执行命令
 // session.getStdout():获得session标准输出
 result = processStdout(session.getStdout(), DEFAULTCHART);
 // 如果未得到标准输出为空,说明脚本执行出错了
 if (StringUtils.isBlank(result)) {
 result = processStdout(session.getStderr(), DEFAULTCHART);
 }
 conn.close();
 session.close();
 }
 } catch (IOException e) {
 e.printStackTrace();
 }
 return result;
 }
 // 将从服务器得到的数据包装成String返回
 private String processStdout(InputStream in, String charset) {
 // 接收目标服务器上的控制台返回结果
 InputStream stdout = new StreamGobbler(in);
 StringBuffer buffer = new StringBuffer();
 try {
 // 将控制台的返回结果包装成BufferedReader
 BufferedReader br = new BufferedReader(new InputStreamReader(stdout, charset));
 String line = null;
 while ((line = br.readLine()) != null) {
 buffer.append(line + "\n");
 }
 br.close();
 } catch (Exception e) {
 e.printStackTrace();
 }
 return buffer.toString();
 }
 public static void setCharset(String charset) {
 DEFAULTCHART = charset;
 }
}

四、对工具类的测试

  • 配置文件system.properties
hostName=SZ01
hdfsPort=8020
hadoopUser=bigdata
hadoopPwd=bigdata
hadoopBinHome=/home/bigdata/hadoop-2.7.2/bin
userDataDir=/input/user
1
2
3
4
5
6
  • 测试类UtilTest.java
import java.util.List;
import com.sand.util.HDFSUtil;
import com.sand.util.PropertiesUtil;
import com.sand.util.RemoteUtil;
public class UtilTest {
public static void main(String[] args) {
 // TODO 工具类测试类
 PropertiesUtil propertiesUtil = new PropertiesUtil("system.properties");
 String host = propertiesUtil.readPropertyByKey("hostName");
 String userName = propertiesUtil.readPropertyByKey("hadoopUser");
 String userPwd = propertiesUtil.readPropertyByKey("hadoopPwd");
 // 使用Java API的方式获取文件信息
 HDFSUtil hdfsUtil = new HDFSUtil(host);
 // 输出根目录下的内容信息
 List<String> list = hdfsUtil.getFileInfo("/");
 for (String string : list) {
 System.out.println(string);
 }
 // 远程登录至Hadoop集群环境,通过命令执行取回信息
 RemoteUtil remoteUtil = new RemoteUtil(host, userName, userPwd);
 String bin = propertiesUtil.readPropertyByKey("hadoopBinHome");
 // 执行时可以使用命令全路径
 String result = remoteUtil.execute(bin + "/hdfs dfs -ls /");
 System.out.println(result);
 // 如果相关命令所在路径已经在PATH中声明,则可以先source再执行
 // 通过&&可以组合执行多条命令
 result = remoteUtil.execute("source .bash_profile && hdfs dfs -ls /");
 System.out.println(result);
 // System.out.println(result.split("\n")[0]);
}
}

  • 运行结果:

五、通过Web操作HDFS

上传本地文件至HDFS

upload.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
 pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
 <form action="UploadServlet" method="post" enctype="multipart/form-data">
 <input type="file" name="data" />
 <input type="submit" value="上传" />
 </form>
</body>
</html>

UploadServlet.java

import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;
import java.util.UUID;
import javax.servlet.ServletException;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;
import com.sand.util.HDFSUtil;
import com.sand.util.PropertiesUtil;
/**
 * Servlet implementation class UploadServlet
 */
@WebServlet("/UploadServlet")
@MultipartConfig
public class UploadServlet extends HttpServlet {
 private static final long serialVersionUID = 1L;
 /**
 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
 * response)
 */
 protected void doGet(HttpServletRequest request, HttpServletResponse response)
 throws ServletException, IOException {
 // 设置编码
 response.setCharacterEncoding("UTF-8");
 response.setContentType("text/plain; charset=UTF-8");
 // 使用Part对象接收文件
 Part part = request.getPart("data");
 // 取出文件名(如果需要)
 String path = "E://userData/";
 // 可以使用自定义的名称,也可以使用UUID
 String fileName = UUID.randomUUID().toString();
 // 从登陆信息中获取当前用户的唯一标识
 String userId = "1";
 // 使用write方法向路径中写入文件
 part.write(path + File.separator + fileName);
 // 从配置文件中读取所需参数
 PropertiesUtil propertiesUtil = new PropertiesUtil("system.properties");
 String hostName = propertiesUtil.readPropertyByKey("hostName");
 String userDataDir = propertiesUtil.readPropertyByKey("userDataDir");
 HDFSUtil hdfsUtil = new HDFSUtil(hostName);
 // 使用工具类进行上传
 hdfsUtil.upLoad(true, true, new String[]{path + fileName}, userDataDir + userId + "/" + fileName);
 PrintWriter printWriter = response.getWriter();
 // 使用工具类获得文件信息
 List<String> list = hdfsUtil.getFileInfo(userDataDir + userId);
 // 将内容输出至页面
 for (String info : list) {
 printWriter.write(info + "\n");
 }
 printWriter.flush();
 printWriter.close();
 }
 /**
 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
 * response)
 */
 protected void doPost(HttpServletRequest request, HttpServletResponse response)
 throws ServletException, IOException {
 // TODO Auto-generated method stub
 doGet(request, response);
 }
}

展示hdfs文件系统中的文件

从根目录开始展示,当目标是目录时,可以继续点击展示其中的内容

CheckMsgServlet.java

import java.io.IOException;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.sand.util.HDFSUtil;
import com.sand.util.PropertiesUtil;
/**
 * Servlet implementation class CheckMsgServlet
 */
@WebServlet("/CheckMsgServlet")
public class CheckMsgServlet extends HttpServlet {
 private static final long serialVersionUID = 1L;
 public CheckMsgServlet() {
 super();
 }
 protected void doGet(HttpServletRequest request, HttpServletResponse response)
 throws ServletException, IOException {
 String method = request.getParameter("method");
 System.out.println(method);
 response.setCharacterEncoding("UTF-8");
 response.setContentType("text/plain; charset=UTF-8");
 PropertiesUtil propertiesUtil = new PropertiesUtil("system.properties");
 String host = propertiesUtil.readPropertyByKey("hostName");
 String userName = propertiesUtil.readPropertyByKey("hadoopUser");
 String userPwd = propertiesUtil.readPropertyByKey("hadoopPwd");
 // 使用Java API的方式获取文件信息
 HDFSUtil hdfsUtil = new HDFSUtil(host);
 //PrintWriter printWriter = response.getWriter();
 List<String> list = null;
 if (method == null) {
 list = hdfsUtil.getFileInfo("/");
 request.setAttribute("infoList", list);
 request.getRequestDispatcher("show.jsp").forward(request, response);
 /*
 * for (String info : list) { printWriter.write(info + "\n"); }
 */
 }else if("dir".equals(method)){
 String path = request.getParameter("path");
 System.out.println(path);
 list = hdfsUtil.getFileInfo(path);
 request.setAttribute("infoList", list);
 request.getRequestDispatcher("show.jsp").forward(request, response);
 }
 }
 protected void doPost(HttpServletRequest request, HttpServletResponse response)
 throws ServletException, IOException {
 // TODO Auto-generated method stub
 doGet(request, response);
 }
}

show.jsp

用到jstl标签库,需要导入jstl的jar包

<%@ page language="java" contentType="text/html; charset=UTF-8"
 pageEncoding="UTF-8"%>
 <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
 <c:forEach items="${infoList}" var="info">
 ${info}<br />
 </c:forEach>
</body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

此实现方式较为简单,由于未包装返回项目信息的实体类,所以直接在HDFSUtil中通过判断封装了a标签进行判断跳转

HDFSUtil.java

/**
 * 获得某一路径下的文件信息
 * @param path 待查看路径
 * @return 文件信息列表-包含文件类型,文件大小,所有者,所在组,文件名称
 */
 public List<String> getFileInfo(String path){
 List<String> infos = new ArrayList<>();
 try {
 // 通过FileSystem获得某一路径下的文件状态列表
 FileStatus[] fileStatus = fs.listStatus(new Path(path));
 for (FileStatus temp : fileStatus) {
 String info = "";
 // 判断文件类型
 if (temp.isDirectory()) {
 info += "目录\t" + "0" + "\t";
 info += temp.getOwner() + "\t" + temp.getGroup() + "\t" + "<a href='CheckMsgServlet?method=dir&path=" + temp.getPath() + "'>" + temp.getPath().getName() + "</a>";
 }else {
 info += "文件\t" + sizeFormat(temp.getLen()) + "\t";
 info += temp.getOwner() + "\t" + temp.getGroup() + "\t" + temp.getPath().getName();
 }
 // 拼接文件信息
 //info += temp.getOwner() + "\t" + temp.getGroup() + "\t" + temp.getPath().getName();
 infos.add(info);
 }
 } catch (Exception e) {
 e.printStackTrace();
 }
 return infos;
 }



相关推荐

5分钟调色大片的方法(5分钟调色大片的方法有哪些)

哈喽大家好。在大家印象中一定觉得ps非常难学非常难。大家不要着急,小编的教学都是针对ps零基础的同学的,而且非常实用哦。只要大家跟着图文练习一两遍,保证大家立马学会~!好了,废话少说,下面开始我们今天...

闪白特效原来是这么用的(闪白特效怎么使用)

作者|高艳侠订阅|010-86092062闪白特效是影视作品中应用比较多的效果之一,那么具体该在哪些场景使用闪白特效?具体该如何操作?下面就以AdobePremiere(以下简称PR)为例,...

ppt常用小图标去哪里找?3个矢量素材网站推荐!

ppt是一个注重可视化表达的演示载体,除了高清图片,ppt中另一类常用的素材是各种小图标,也叫矢量图标,巧妙运用小图标能提升整体美观度和表现力,那么ppt常用小图标去哪里找呢?为方便各位快速找到合适的...

有什么好用的截图录屏工具?试试这9款

经常有朋友反馈苦于缺乏截屏和录屏的趁手工具,本期我们分享几个相当好用的截屏和录屏工具,希望能帮到大家。ScreenToGifScreenToGif是一款免费且开源的录屏工具。此款工具最大的特点是可以...

配色苦手福音!专业快速色环配色PS插件

今天橘子老师给的大家介绍的是一款快速配色的插件,非常强大配色苦手福音来啦!(获取方式见文末)【插件介绍】配色在后期设计中占有主导地位,好的配色能让作品更加抢眼Coolorus这款专业的配色插件,能够...

如何用PS抠主体?(ps怎么抠主体)

1.主体法抠图-抠花苞和花梗导入一张荷花苞的照片,点击上图中顶部“选择”菜单栏,下拉单击“主体”。可以看到,只有花苞被选中,但是花梗并没有被选中。接下来单击上图中左侧工具栏的“快速选择工具”,上图中顶...

2799元的4K电视,有保障吗?(买4k电视机哪个品牌好)

在上一期《电脑报》的3·15专题报道中,我们揭露了一款不靠谱的42英寸4K智能电视——TCLD42A561U。这款售价2699元的4K智能电视不仅4K画质方面存在严重问题,而且各种功能和应用体验也不理...

苹果电脑的Touch Bar推出一段时间了 这款工具可以帮你开发适用于它的APP

距离苹果推出带有TouchBar的MacBookPro已经有一段时间了,除了那些像Adobe、Google和Microsoft大公司在开发适用于TouchBar的应用之外,其实还有很多独立的开...

如魔法般吸取颜色的桌灯(如魔法般吸取颜色的桌灯叫什么)

色彩为生活带来的感官刺激,逐渐被视为理所当然。一盏桌灯运用它的神奇力量,将隐藏于物件中的颜色逐一释放,成为装点环境的空间魔法师。ColorUp是一款可以改变颜色的吸色台灯,沿用传统灯泡的造型,融入了拾...

一篇文章带你用jquery mobile设计颜色拾取器

【一、项目背景】现实生活中,我们经常会遇到配色的问题,这个时候去百度一下RGB表。而RGB表只提供相对于的颜色的RGB值而没有可以验证的模块。我们可以通过jquerymobile去设计颜色的拾取器...

ps拾色器快捷键是什么?(ps2019拾色器快捷键)

ps拾色器快捷键是什么?文章末尾有获取方式,按照以下步骤就能自动获得!学会制作PS特效需要一定程度的耐心和毅力。初学者可以从基本的工具和技术开始学习,逐渐提高他们的技能水平。同时,观看更多优秀的特效作...

免费开源的 Windows 截图录屏工具,支持 OCR 识别和滚动截图等

功能很强大、安装很小巧的免费截图、录屏工具,提供很多使用的工具来帮我么能解决问题,推荐给大家。关于ShareXShareX是一款免费的windows工具,起初是一个小巧的截图工具,经过多年的迭...

入门到精通系列PS教程:第13篇 · 拾色器、颜色问题说明及补充

入门到精通系列PS教程:第13篇·拾色器、颜色问题说明及补充作者|侯潇问题说明我的第12篇教程里,有个小问题没有说清楚。要说是错误,又不算是错误,只是没有说准确。写完那篇教程后,因为已经到了深...

PS冷知识:用吸管工具吸取屏幕上的任意颜色

今天,我们给大家介绍PS中的一个冷知识:用吸管工具可以吸取屏幕上的任意颜色。其实,操作起来是非常简单的。大多数情况下,我们认为,PS的吸管工具只能吸取PS软件作图区域范围内的颜色,最多加上画布四周的...

Windows 11 将提供内置颜色选择器工具

Windows11内置了颜色选择器,可以扫描并识别屏幕上的颜色并生成颜色代码。此外,微软还利用人工智能技术,让屏幕上的文本扫描和选择变得更加便捷。这两项功能均已在SnippingToolv1...