HDFS操作编程实现

厦门大学林子雨《大数据原理与技术》实验2

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.FsUrlStreamHandlerFactory;
import org.apache.hadoop.fs.LocatedFileStatus;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.fs.RemoteIterator;
import org.apache.hadoop.io.IOUtils;
import org.apache.hadoop.fs.FSDataInputStream;
import org.apache.hadoop.fs.FSDataOutputStream;
import org.apache.hadoop.fs.FileStatus;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import java.text.SimpleDateFormat;

/*编程实现实验报告要求的功能*/
public class HDFSOperations {
	
	/*1.向HDFS中上传任意文本文件,如果指定的文件在HDFS中已经存在,由用户指定是追加到原有文件末尾还是覆盖原有的文件*/
	public static void operation1(Configuration conf, String choice) {
		//本地路径
		String localFilePath = "/usr/local/hadoop/uploadtest.txt";
		//HDFS路径
		String remoteFilePath = "/usr/hadoop/uploadtest.txt";

		try (FileSystem fs = FileSystem.get(conf)){
			// 判断HDFS文件路径是否存在
			if(fs.exists(new Path(remoteFilePath))) {
				//存在
				System.out.println(remoteFilePath+ "已存在。");
				//用户指定文件处理方式
				if(choice.equals("append")) {	//选择追加到末尾
					FileInputStream in = new FileInputStream(localFilePath);
					FSDataOutputStream out = fs.append(new Path(remoteFilePath));
					byte[] data = new byte[1024];
					int read = -1;
					while((read = in.read(data))>0) {
						out.write(data,0,read);
					}
					out.close();
				}else if(choice.equals("overwrite")){		//选择覆盖
					//第一个参数表示是否删除源文件,第二个参数表示是否覆盖
					fs.copyFromLocalFile(false, true, new Path(localFilePath), new Path(remoteFilePath));
				}
			}else {
				System.out.println(remoteFilePath+ "不存在。");
				//上传文件
				fs.copyFromLocalFile(false, true, new Path(localFilePath), new Path(remoteFilePath));
			}
		}catch(IOException e) {
			e.printStackTrace();
		}	
	}

	/*2.从HDFS中下载指定文件,如果本地文件与要下载的文件名称相同,则自动对下载的文件重命名。*/
	
	public static void operation2(Configuration conf) {
		//本地路径
		String localFilePath = "/usr/local/hadoop/downloadtest.txt";
		//HDFS路径
		String remoteFilePath = "/usr/hadoop/downloadtest.txt";
		try (FileSystem fs = FileSystem.get(conf)){
			//判断本地文件是否存在
			File f = new File(localFilePath);
			if(f.exists()) {
				//文件存在:自动重命名
				System.out.println(localFilePath+"已存在");
				Integer i = Integer.valueOf(0);
				while(true) {
					localFilePath = localFilePath+"_"+i.toString();
					f = new File(localFilePath);
					if(!f.exists()) {
						break;
					}else {
						i++;
						continue;
					}
				}
			}
			System.out.println("将重新命名为:"+localFilePath);
			
			//下载文件到本地
			fs.copyToLocalFile(new Path(remoteFilePath), new Path(localFilePath));
			System.out.println("下载完成");
		}catch(IOException e) {
			e.printStackTrace();
		}
	}

	/*3.将HDFS中指定文件的内容输出到终端中。*/
	public static void operation3(Configuration conf) {
		//HDFS路径
		String remoteFilePath = "/usr/hadoop/downloadtest.txt";
		try(FileSystem fs = FileSystem.get(conf); 
				FSDataInputStream in = fs.open(new Path(remoteFilePath)); //打开HDFS上文件
				BufferedReader d = new BufferedReader(new InputStreamReader(in));) 
		{
			String line;
			while((line=d.readLine())!=null) {	//读取完整的一行字符串
				System.out.println(line); //输出
			}
		}catch(IOException e) {
			e.printStackTrace();
		}
	}
	
	/*4.显示HDFS中指定的文件的读写权限、大小、创建时间、路径等信息。*/
	public static void operation4(Configuration conf) {
		String remoteFilePath = "/usr/hadoop/downloadtest.txt";
		try(FileSystem fs = FileSystem.get(conf)){
			//FileStatus对象通过listStatus()获取文件状态信息
			FileStatus[] fileStatuses = fs.listStatus(new Path(remoteFilePath));
			for(FileStatus s: fileStatuses) {
				System.out.println("路径:"+s.getPath().toString());
				System.out.println("权限:"+s.getPermission().toString());
				System.out.println("大小:"+s.getLen());
				//返回的是时间戳,转化为时间日期格式
				long timeStamp = s.getModificationTime();
				SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
				String date = format.format(timeStamp);
				System.out.println("时间:"+date);
			}
		}catch(IOException e) {
			e.printStackTrace();
		}
	}
	
	/*5.给定HDFS中某一个目录,输出该目录下的所有文件的读写权限、大小、创建时间、路径等信息,
	 * 如果该文件是目录,则递归输出该目录下所有文件相关信息*/
	public static void operation5(Configuration conf) {
		String remotePath = "/usr/";
		try(FileSystem fs = FileSystem.get(conf)){
			//递归获取目录下的所有文件
			RemoteIterator<LocatedFileStatus> remoteIterator = fs.listFiles(new Path(remotePath), true);
			/*输出每个文件的信息*/
			while(remoteIterator.hasNext()) {
				FileStatus s = remoteIterator.next();
				System.out.println("路径:"+s.getPath().toString());
				System.out.println("权限:"+s.getPermission().toString());
				System.out.println("大小:"+s.getLen());
				//返回的是时间戳,转化为时间日期格式
				long timeStamp = s.getModificationTime();
				SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
				String date = format.format(timeStamp);
				System.out.println("时间:"+date);
			}
		}catch(IOException e) {
			e.printStackTrace();
		}
	}
	
	/*6.提供一个HDFS内的文件的路径,对该文件进行创建和删除操作。
	 * 如果文件所在目录不存在,则自动创建目录*/
	public static void operation6(Configuration conf) {
		String remoteFile = "/usr/hadoop/test1/test.txt";
		String remotePath = "/usr/hadoop/test1/"; 
		
		//判断文件路径是否存在,存在则删除,否则进行创建。
		try(FileSystem fs = FileSystem.get(conf)){
			if(fs.exists(new Path(remoteFile))) {
				boolean b = fs.delete(new Path(remoteFile), false); //false表示不递归删除
				System.out.println("删除文件:"+remoteFile+" "+b);
			}else {
				//判断目录是否存在,不存在则创建
				if(!fs.exists(new Path(remotePath))) {
					fs.mkdirs(new Path(remotePath));
					System.out.println("创建目录:"+remotePath);
				}
				FSDataOutputStream outputStream = fs.create(new Path(remoteFile));
				outputStream.close();
				System.out.println("创建文件:"+remoteFile);
			}		
		}catch(IOException e) {
			e.printStackTrace();
		}	
	}
	
	/*7.提供一个HDFS的目录的路径,对该目录进行创建和删除操作。
	 * 创建目录时,如果目录文件所在目录不存在则自动创建相应目录;删除目录时,由用户指定当该目录不为空时是否还删除该目录*/
	public static void operation7(Configuration conf) {
		
		String remotePath = "/usr/hadoop/test"; 
		
		//判断文件路径是否存在,存在则删除,否则进行创建。
		try(FileSystem fs = FileSystem.get(conf)){
			if(fs.exists(new Path(remotePath))) {
				boolean deleteNotEmpty = true;	//用户指定:目录不为空仍然删除
				FileStatus[] listStatus = fs.listStatus(new Path(remotePath));
				if((listStatus.length!=0&&deleteNotEmpty)) { 
						fs.delete(new Path(remotePath),true);
						System.out.println("目录不为空,仍然删除"+remotePath.toString());
				}else if(listStatus.length==0) {
					boolean b = fs.delete(new Path(remotePath), true); //true表示递归删除
					System.out.println("删除"+remotePath);
				}
			}else {
				//目录不存在则创建
				if(!fs.exists(new Path(remotePath))) {
					fs.mkdirs(new Path(remotePath));
					System.out.println("创建目录:"+remotePath);
				}
			}		
		}catch(IOException e) {
			e.printStackTrace();
		}	
	}
	
	/*8.向HDFS中指定的文件追加内容,由用户指定内容追加到原有文件的开头或结尾。*/
	
	public static void operation8(Configuration conf) {
		
		String remotePath = "usr/hadoop/uploadtest.txt"; 
		String contentHead = "追加在开头的内容。";
		String contentTail= "追加在结尾的内容。";
		
		//判断文件路径是否存在
		try(FileSystem fs = FileSystem.get(conf)){
			if(fs.exists(new Path(remotePath))) {
				String choice = "tail";
				if(choice.equals("head")) {
					//先把原来内容传到本地
					String localTemPath = "/usr/local/hadoop/tmp.txt";
					fs.moveToLocalFile(new Path(remotePath), new Path(localTemPath));
					//创建新文件
					FSDataOutputStream outputStream = fs.create(new Path(remotePath));
					outputStream.close();
					//先写入新内容
					FSDataOutputStream out = fs.append(new Path(remotePath));
					out.write(contentHead.getBytes());
					out.close();
					//把原来内容追加到末尾
					FileInputStream in = new FileInputStream(localTemPath);
					FSDataOutputStream out1 = fs.append(new Path(remotePath));
					byte[] data = new byte[1024];
					int read = -1;
					while((read = in.read(data))>0) {
						out1.write(data,0,read);
					}
					out1.close();
					//删除本地文件
					File file1 = new File(localTemPath);
					file1.delete();
					System.out.println("已追加内容到文件开头"+remotePath);
				}else if(choice.equals("tail")) {
					//创建一个文件输出流,输出的内容将追加到文件末尾
					FSDataOutputStream out = fs.append(new Path(remotePath));
					out.write(contentTail.getBytes());
					out.close();
					System.out.println("已追加内容到文件末尾"+remotePath);
				}
			}else {
				System.out.println("文件不存在"+remotePath);
			}		
		}catch(IOException e) {
			e.printStackTrace();
		}	
	}

	/*9.删除HDFS中指定的文件。*/
	public static void operation9(Configuration conf) {
		
		String remotePath = "/usr/hadoop/uploadtest.txt"; 
		
		//判断文件路径是否存在,存在则删除,否则进行创建。
		try(FileSystem fs = FileSystem.get(conf)){
			fs.delete(new Path(remotePath));
			System.out.println("删除文件"+remotePath);
		}catch(IOException e) {
			e.printStackTrace();
		}	
	}
	
	/*10.删除HDFS中指定的目录,由用户指定目录中如果存在文件时是否删除目录。*/
	public static void operation10(Configuration conf) {
		
		String remotePath = "usr/hadoop/testdir"; 
	
		try(FileSystem fs = FileSystem.get(conf)){
			//判断路径是否存在。
			if(fs.exists(new Path(remotePath))) {
				boolean deleteNotEmpty = true;	//用户指定:目录不为空是否删除
				FileStatus[] listStatus = fs.listStatus(new Path(remotePath));
				if(listStatus.length!=0) { //目录不为空
					if(deleteNotEmpty) {
						fs.delete(new Path(remotePath),true);
						System.out.println("目录不为空,仍然删除"+remotePath.toString());
					}else {
						System.out.println("目录不为空,不删除"+remotePath.toString());
					}
				}else{	//目录为空,直接删除
					fs.delete(new Path(remotePath)); 
					System.out.println("删除"+remotePath);
				}
			}else {
				//目录不存在				
				System.out.println("目录不存在"+remotePath);
			}		
		}catch(IOException e) {
			e.printStackTrace();
		}	
	}
	
	/*11.在HDFS中,将文件从源路径移动到目的路径。*/
	
	public static void operation11(Configuration conf) {
		
		String remoteSrcPath = "usr/hadoop/dir2/uploadtest_local.txt"; 
		String remoteDstPath = "usr/hadoop/uploadtest_local.txt"; 
	
		try(FileSystem fs = FileSystem.get(conf)){
			fs.rename(new Path(remoteSrcPath), new Path(remoteDstPath));
			System.out.println("将文件"+remoteSrcPath+"移动到"+remoteDstPath);
		}catch(IOException e) {
			e.printStackTrace();
		}	
	}
	
	/*12-3.查看Java帮助手册或其它资料,用“java.net.URL”和“org.apache.hadoop.fs.FsURLStreamHandlerFactory”
	 * 编程完成输出HDFS中指定文件的文本到终端中。
	 */
	static {
		//注册HDFS流处理器
		URL.setURLStreamHandlerFactory(new FsUrlStreamHandlerFactory());
	}
	
	public static void operation12_3() throws Exception{
		String remotePath = "hdfs://localhost:9000/usr/hadoop/downloadtest.txt"; 
		InputStream in = null;
		try {
			// 通过URL对象打开数据流,从中读取数据
			URL url = new URL(remotePath);
			//拿到链接
			URLConnection con = url.openConnection();
			in = con.getInputStream();
			IOUtils.copyBytes(in, System.out, 4096, false);
		}finally {
			IOUtils.closeStream(in);
		}
	}
	
	
	public static void main(String[] args) {
		try {
			
//			Configuration conf = new Configuration();
//			conf.set("fs.defaultFS", "hdfs://localhost:9000");
//			conf.set("dfs.support.append", "true");
//			conf.set("dfs.client.block.write.replace-datanode-on-failure.policy", "NEVER");
//			conf.set("dfs.client.block.write.replace-datanode-on-failure.enable", "true");
			
			/*编程任务1*/
			
			/*
			//若文件存在,添加到文件末尾
			String append = "append";
			//若文件存在,覆盖
			String overwrite = "overwrite";
			operation1(conf, overwrite);*/
			
			operation12_3();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
			


}
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

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

/*编程实现一个类“MyFSDataInputStream”,该类继承“org.apache.hadoop.fs.FSDataInputStream”*/
public class MyFSDataInputStream extends FSDataInputStream{

	public MyFSDataInputStream(InputStream in) {
		super(in);
	}
	

	/*1.实现按行读取HDFS中指定文件的方法“readLine()”,如果读到文件末尾,则返回空,否则返回文件一行的文本。*/
	public static String readLine(BufferedReader br) {
		try {
			char[] data = new char[1024];
			int read = -1;
			int off = 0; //循环执行时,br每次会从上一次读取结束的位置继续读取,因此该函数里,off每次都从0开始。
			while((read = br.read(data, off, 1)) != -1) {
				if(String.valueOf(data[off]).equals("\n")) {
					// 遇到换行符
					off += 1;
					break;
				}
				off += 1; //在遇到换行符之前正常读字节流
			}
			
			//读文件循环结束后,判断是否读到文件末尾
			if(off>0) {
				//不是文件末尾
				return String.valueOf(data);
			}else {
				return null;
			}
		}catch(IOException e){}
		return null;
	}
	
	/*2.实现缓存功能,即利用“MyFSDataInputStream”读取若干字节数据时,首先查找缓存,
	 * 如果缓存中有所需数据,则直接由缓存提供,否则向HDFS读取数据。*/
	public static void cat(Configuration conf, String remotePath) {
		try {
			FileSystem fs = FileSystem.get(conf);
			FSDataInputStream in = fs.open(new Path(remotePath));
			BufferedReader br = new BufferedReader(new InputStreamReader(in));
			String line = null;
			while((line = MyFSDataInputStream.readLine(br)) != null) {
				System.out.println(line);
			}
			br.close();
			in.close();
			fs.close();
		}catch(IOException e) {}
		
		System.out.println("读取完成");
	}
	
	public static void main(String[] args) {
		try {
			Configuration conf = new Configuration();
			conf.set("fs.defaultFS", "hdfs://localhost:9000");
			conf.set("dfs.support.append", "true");
			conf.set("dfs.client.block.write.replace-datanode-on-failure.policy", "NEVER");
			conf.set("dfs.client.block.write.replace-datanode-on-failure.enable", "true");
			
			String remotePath = "usr/hadoop/uploadtest.txt"; 
			MyFSDataInputStream.cat(conf, remotePath);
		}catch(Exception e) {
				e.printStackTrace();
		}
	}
		
}

  • 3
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值