java 操作hdfs

 

1.windows mapreduce开发环境

linux下进行hadoop应用的开发,不会存在兼容性问题。如在window上做客户端应用开发,需要设置以下环境:

A、在windows的某个目录下解压一个hadoop的安装包
B、将安装包下的lib和bin目录用对应windows版本平台编译的本地库替换
C、在window系统中配置HADOOP_HOME指向你解压的安装包

D、在windows系统的path变量中加入hadoop的bin目录

 

java对hdfs相关的操作

package com.lei.bigdata.hdfs;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.URI;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.BlockLocation;
import org.apache.hadoop.fs.FileStatus;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.LocatedFileStatus;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.fs.RemoteIterator;
import org.apache.hadoop.hdfs.DistributedFileSystem;
import org.apache.hadoop.hdfs.protocol.DatanodeInfo;
import org.junit.Before;
import org.junit.Test;

public class HdfsClient {

	FileSystem fs = null;

	@Before
	public void init() throws Exception {

		// 构造一个配置参数对象,设置一个参数:我们要访问的hdfs的URI
		// 从而FileSystem.get()方法就知道应该是去构造一个访问hdfs文件系统的客户端,以及hdfs的访问地址
		// new Configuration();的时候,它就会去加载jar包中的hdfs-default.xml
		// 然后再加载classpath下的hdfs-site.xml
		Configuration conf = new Configuration();
		conf.set("fs.defaultFS", "hdfs://bigdata-sg-a-05:9000");
		/**
		 * 参数优先级: 1、客户端代码中设置的值 2、classpath下的用户自定义配置文件 3、然后是服务器的默认配置
		 */
		conf.set("dfs.replication", "2");
		conf.set("dfs.block.size","64m");

		// 获取一个hdfs的访问客户端,根据参数,这个实例应该是DistributedFileSystem的实例
//		 fs = FileSystem.get(conf);

		// 如果这样去获取,那conf里面就可以不要配"fs.defaultFS"参数,而且,这个客户端的身份标识已经是hadoop用户
		fs = FileSystem.get(new URI("hdfs://bigdata-sg-a-05:9000"), conf, "hadoop");
		
		// 获取文件系统相关信息
		DatanodeInfo[] dataNodeStats = ((DistributedFileSystem) fs).getDataNodeStats();
		for(DatanodeInfo dinfo: dataNodeStats){
			System.out.println(dinfo.getHostName());
		}

	}

	/**
	 * 往hdfs上传文件
	 * 
	 * @throws Exception
	 */
	@Test
	public void testAddFileToHdfs() throws Exception {

		// 要上传的文件所在的本地路径
		Path src = new Path("g:/apache-flume-1.6.0-bin.tar.gz");
		// 要上传到hdfs的目标路径
		Path dst = new Path("/");
		fs.copyFromLocalFile(src, dst);

		fs.close();
	}

	/**
	 * 从hdfs中复制文件到本地文件系统
	 * 
	 * @throws IOException
	 * @throws IllegalArgumentException
	 */
	@Test
	public void testDownloadFileToLocal() throws IllegalArgumentException, IOException {

//		fs.copyToLocalFile(new Path("/apache-flume-1.6.0-bin.tar.gz"), new Path("d:/"));
		fs.copyToLocalFile(false,new Path("/apache-flume-1.6.0-bin.tar.gz"), new Path("d:/"),true);
		fs.close();

	}

	/**
	 * 目录操作
	 * @throws IllegalArgumentException
	 * @throws IOException
	 */
	@Test
	public void testMkdirAndDeleteAndRename() throws IllegalArgumentException, IOException {

		// 创建目录
		fs.mkdirs(new Path("/a1/b1/c1"));

		// 删除文件夹 ,如果是非空文件夹,参数2必须给值true
		fs.delete(new Path("/aaa"), true);

		// 重命名文件或文件夹
		fs.rename(new Path("/a1"), new Path("/a2"));

	}

	/**
	 * 查看目录信息,只显示文件
	 * 
	 * @throws IOException
	 * @throws IllegalArgumentException
	 * @throws FileNotFoundException
	 */
	@Test
	public void testListFiles() throws FileNotFoundException, IllegalArgumentException, IOException {

		// 思考:为什么返回迭代器,而不是List之类的容器, 如果文件特大, 那不就崩啦! 迭代器是每迭代一次都向服务器取一次
		RemoteIterator<LocatedFileStatus> listFiles = fs.listFiles(new Path("/"), true);

		while (listFiles.hasNext()) {

			LocatedFileStatus fileStatus = listFiles.next();

			System.out.println(fileStatus.getPath().getName());//文件名
			System.out.println(fileStatus.getBlockSize());//block块的大小
			System.out.println(fileStatus.getPermission());//文件的权限
			System.out.println(fileStatus.getLen());//字节数
			BlockLocation[] blockLocations = fileStatus.getBlockLocations();//获取block块
			for (BlockLocation bl : blockLocations) {
				System.out.println("block-length:" + bl.getLength() + "--" + "block-offset:" + bl.getOffset());
				String[] hosts = bl.getHosts();	//主机名
				for (String host : hosts) {
					System.out.println(host);
				}

			}

			System.out.println("--------------为angelababy打印的分割线--------------");

		}

	}

	/**
	 * 查看文件及文件夹信息
	 * 
	 * @throws IOException
	 * @throws IllegalArgumentException
	 * @throws FileNotFoundException
	 */
	@Test
	public void testListAll() throws FileNotFoundException, IllegalArgumentException, IOException {

		FileStatus[] listStatus = fs.listStatus(new Path("/"));

		String flag = "d-- ";
		for (FileStatus fstatus : listStatus) {

			if (fstatus.isFile())  flag = "f-- ";

			System.out.println(flag + fstatus.getPath().getName());
			System.out.println(fstatus.getPermission());

		}
		
		

	}
	

}

 

 

写MapReduce程序时,最后加一个判断当前输出路径是否存在的代码,如果输出路径存在则删除。这样可以避免出现如下错误:

Output directory hdfs://bigdata-sg-a-05:9000/output already exists

 

具体代码如下:

final static String OUTPUT_PATH = "hdfs://bigdata-sg-a-05:9000/output";   
//输出路径用字符串表示,在主类中定义,或者由主方法参数给出
 
Path path = new Path(OUTPUT_PATH);
    FileSystem fileSystem = path.getFileSystem(conf);     
//getFileSystem()函数功能  Return the FileSystem that owns this Path. 
	if (fileSystem.exists(new Path(OUTPUT_PATH))) {
	    fileSystem.delete(new Path(OUTPUT_PATH),true);

 

 

 

在FileSystem 类下的delete()函数源码如下:

public boolean delete(Path f) throws IOException {
    return delete(f, true);
  }
 
  /** Delete a file.
   *
   * @param f the path to delete.
   * @param recursive if path is a directory and set to
   * true, the directory is deleted else throws an exception. In
   * case of a file the recursive can be set to either true or false.
   * @return  true if delete is successful else false.
   * @throws IOException
   */
  public abstract boolean delete(Path f, boolean recursive) throws IOException;

函数由两个参数,第一个为要删除文件的路径(类型Path),第二个函数为是否递归删除文件夹及其字目录(类型boolean),一般为true。删除失败抛出IOException异常。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值