最近好久没有更新博客了,因为最近的工作鞋的代码都是自己不怎么熟悉的领域的,所以感觉这些代码写的有点困难。今天特此写这个博客把自己最近研究的东西稍作总结。
工作的需求是,在HDFS上有每天不断产生的的日志文件文件夹,每一个文件夹下都有两个文件,一个是.log文件,还有一个是.out文件。现在要求根据日志产生的时间,按照天计算,将同一天产生的文件夹打包压缩成一个文件归档在 HDFS某个特定的目录下。操作HDFS上的文件当然就不能java自带的那一套操作文件的方式去处理了。事实上,Hadoop提供了一套api为java来操作hdfs,下面我们来看看具体是怎么实现的。
第一步,获取HDFS的FileSystem对象,对所有在HDFS中的文件的操作,都要使用这个对象提供的方法去操作,需要添加当前项目下的hadoop的两个配置文件。
1 public static FileSystem getFileSystem() throws IOException { 2 Configuration conf = new Configuration(); 3 conf.addResource(new Path("conf/core-site.xml")); 4 conf.addResource(new Path("conf/hdfs-site.xml")); 5 conf.set("fs.file.impl", "org.apache.hadoop.fs.RawLocalFileSystem"); 6 return FileSystem.get(conf); 7 }
第二步,获取HDFS某文件夹下所有的文件信息:
1 FileStatus[] stats = fs.listStatus(path); 2 for (FileStatus stat : stats) { 3 long time = stat.getModificationTime(); //文件的最后编辑时间 4 String filePath = stat.getPath().toString(); //文件的全路径 5 String fileName = stat.getPath().getName(); //文件名 6 boolean isFile = stat.isFile(); //路径是否是文件 7 boolean isDir = stat.isDirectory(); //路径是否是目录 8 }
第三步,得到某一个文件的输入流 ,使用hdfs提供的流:
1 FSDataInputStream HDFSIn = fs.open(new Path(fileStatus[j].getPath().toString())); //getPath():文件的完整路径 2 BufferedInputStream bis = new BufferedInputStream(HDFSIn);
第四步,在文件经过相应的处理之后,向HDFS写文件:
1 byte[] buf = new byte[1024]; 2 FSDataOutputStream fsDataOutputStream = getFileSystem().create(new Path(“HDFDPath”)); 3 fsDataOutputStream.write(buf);
第五步,删除没用的文件(谨慎操作!):
1 FileSystem fs = getFileSystem(); 2 fs.delete(new Path(file), true); //true表示非空目录和文件会被删除,通过java删除的文件将会被永久删除,不会被放入HDFS的回收站
作此总结,希望自己再接再厉。
附上HDFS常用命令:
命令 | 作用 |
| 列出hdfs文件系统根目录下的目录和文件 |
hadoop fs -put < local file > < hdfs file > | 向HDFS添加本地文件 |
hadoop fs -get < hdfs file > < local file or dir> | 拷贝文件至本地 |
| 删除文件或者目录 |
hadoop fs -mkdir < hdfs path> | 创建目录 |
hadoop fs -cp < hdfs file > < hdfs file > | 给文件重命名并且保存,源文件还在 |
hadoop fs -mv < hdfs file > < hdfs file > | 给文件重命名并且保存,源文件不在 |
hadoop fs -count < hdfs path > | 统计目录下文件个数,目录个数,文件总大小 |
hadoop fs -tail < hdfs file > | 显示文件末尾1KB的数据 |
| 均衡内部dataNode中的文件 |