厦门大学林子雨《大数据原理与技术》实验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();
}
}
}