赞
踩
@Test public void urlHdfs() throws IOException { //1:注册url URL.setURLStreamHandlerFactory( new FsUrlStreamHandlerFactory()); //2:获取hdfs文件的输入流 InputStream inputStream = new URL("hdfs://node01:8020/a.txt").openStream(); //3:获取本地文件的输出流 FileOutputStream outputStream = new FileOutputStream(new File("D:\\hello2.txt")); //4:实现文件的拷贝 IOUtils.copy(inputStream, outputStream); //5:关流 IOUtils.closeQuietly(inputStream); IOUtils.closeQuietly(outputStream); }
在Java中操作HDFS,主要涉及以下class:
FileSystem fs = FileSystem.get(conf)
/* 获取FileSystem;方式1 */ @Test public void getFileSystem1() throws IOException { //1:创建Configuration对象 Configuration configuration = new Configuration(); //2:设置文件系统的类型 configuration.set("fs.defaultFS", "hdfs://node01:8020"); //3:获取指定的文件系统 FileSystem fileSystem = FileSystem.get(configuration); //4:输出 System.out.println(fileSystem); }
/*
获取FileSystem;方式2
*/
@Test
public void getFileSystem2() throws URISyntaxException, IOException {
FileSystem fileSystem = FileSystem.get(new URI("hdfs://node01:8020"), new Configuration());
System.out.println(fileSystem);
}
/*
获取FileSystem;方式3
*/
@Test
public void getFileSystem3() throws IOException {
Configuration configuration = new Configuration();
//指定文件系统类型
configuration.set("fs.defaultFS", "hdfs://node01:8020");
//获取指定的文件系统
FileSystem fileSystem = FileSystem.newInstance(configuration);
System.out.println(fileSystem);
}
/*
获取FileSystem;方式4
*/
@Test
public void getFileSystem4() throws URISyntaxException, IOException {
FileSystem fileSystem = FileSystem.newInstance(new URI("hdfs://node01:8020"), new Configuration());
System.out.println(fileSystem);
}
/* hdfs文件的遍历 */ @Test public void listFiles() throws URISyntaxException, IOException { //1:获取FileSystem实例 FileSystem fileSystem = FileSystem.get(new URI("hdfs://node01:8020"), new Configuration()); //2:调用方法listFiles 获取 /目录下所有的文件信息,,参数true代表递归遍历 RemoteIterator<LocatedFileStatus> iterator = fileSystem.listFiles(new Path("/"), true); //3:遍历迭代器 while (iterator.hasNext()){ LocatedFileStatus fileStatus = iterator.next(); //获取文件的绝对路径 : hdfs://node01:8020/xxx //getPath()方法就是获取绝对路径 System.out.println(fileStatus.getPath() + "----" +fileStatus.getPath().getName()); //文件的block信息 BlockLocation[] blockLocations = fileStatus.getBlockLocations(); System.out.println("block数:"+blockLocations.length); } }
/* hdfs创建文件夹 */ @Test public void mkdirsTest() throws URISyntaxException, IOException { //1:获取FileSystem实例 FileSystem fileSystem = FileSystem.get(new URI("hdfs://node01:8020"), new Configuration()); //2:创建文件夹 //boolean bl = fileSystem.mkdirs(new Path("/aaa/bbb/ccc")); //创建文件 fileSystem.create(new Path("/aaa/bbb/ccc/a.txt")); //如果父目录不存在,则会一并创建 fileSystem.create(new Path("/aaa2/bbb/ccc/a.txt")); //System.out.println(bl); //3: 关闭FileSystem //fileSystem.close(); }
/* 实现文件的下载 */ @Test public void downloadFile() throws URISyntaxException, IOException { //1:获取FileSystem FileSystem fileSystem = FileSystem.get(new URI("hdfs://node01:8020"), new Configuration()); //2:获取hdfs的输入流,,注意获取的HDFS文件系统上的路径 FSDataInputStream inputStream = fileSystem.open(new Path("/a.txt")); //3:获取本地路径的输出流,,注意这里获取的是本地磁盘路径 FileOutputStream outputStream = new FileOutputStream("D://a.txt"); //4:文件的拷贝 IOUtils.copy(inputStream, outputStream); //5:关闭流 IOUtils.closeQuietly(inputStream); IOUtils.closeQuietly(outputStream); fileSystem.close(); }
通过对比方式1,可以使用copyToLocalFile方法一步到位。
/*
实现文件的下载:方式2
*/
@Test
public void downloadFile2() throws URISyntaxException, IOException, InterruptedException {
//1:获取FileSystem
FileSystem fileSystem = FileSystem.get(new URI("hdfs://node01:8020"), new Configuration(),"root");
//2:调用方法,实现文件的下载
fileSystem.copyToLocalFile(new Path("/a.txt"), new Path("D://a4.txt"));
//3:关闭FileSystem
fileSystem.close();
}
和文件下载格式一样,,不同的是方法不同,
文件上传使用copyFromLocalFile方法一步到位。
注意:
/* 文件的上传 */ @Test public void uploadFile() throws URISyntaxException, IOException { //1:获取FileSystem FileSystem fileSystem = FileSystem.get(new URI("hdfs://node01:8020"), new Configuration()); //2:调用方法,实现上传 fileSystem.copyFromLocalFile(new Path("D://set.xml"), new Path("/")); //3:关闭FileSystem fileSystem.close(); }
注意查看该文件的编辑内容, 默认为 false ,, 就是说让所有权限自身的作用失效,,也就是说在hdfs上显示的rwx权限没有任何意义。 所以要想修改文件的权限,就得修改为true
接下来我们验证上面参数的作用
首先通过命令来修改hdfs系统上的a.txt文件权限
hdfs dfs -chmod 000 /a.txt
结果如下
然后我们通过Java Api 来下载该文件到本地磁盘D盘下
@Test
public void mkdirsTest() throws URISyntaxException, IOException {
//1:获取FileSystem实例
FileSystem fileSystem = FileSystem.get(new URI("hdfs://192.168.217.128:9000"), new Configuration());
//2:调用方法,实现文件的下载
fileSystem.copyToLocalFile(new Path("/a.txt"), new Path("D://a2.txt"));
//3:关闭FileSystem
fileSystem.close();
}
运行后发现在本地D盘下有a2.txt文件,
通过测试,发现即使该文件的权限被改为000,结果还是可以被访问,然后被下载到本地,,所以说,,,httpfs-site.xml文件中该部分参数为false的话,就是让所有权自身的作用失效。
注意:如果要将该参数改为true,则首先必须将hdfs集群关闭,不能在运行状态下修改配置文件。
下面我们继续进行验证,,这次先在Hadoop主目录下的sbin目录关闭hdfs文件系统,通过如下命令
sbin/stop-dfs.sh
注意:
这里如果将master主节点上的配置文件改为true的话,也必须修改其他节点的配置文件。
然后通过分发命令,进行分发:
scp hdfs-site.xml slave1:$PWD
scp hdfs-site.xml slave2:$PWD
然后我们再次启动hdfs集群
sbin/start-all.sh
然后我们使用Java Api 再次进行下载文件,,会发生如下报错,,应为此时我们将配置文件中的参数修改为true,就是使得所有的文件权限生效。所以再次下载访问时,回报如下错误。
由于权限rwx作用全部生效,,所以我们如果还想通过Java Api进行下载的话,就必须得修改该文件的权限。 同时一定要注意该文件的所属用户!!!
hdfs dfs -chmod 666 /a.txt
此时便能通过Java Api 下载到本地
如果想要不修改该文件的权限就下载访问该文件,就可以通过伪装用户的方式,来进行下载。
就是在Java代码中的get方法中多添加一个参数,该参数则是要伪装的用户名字。例如下面代码:
@Test
public void mkdirsTest() throws URISyntaxException, IOException, InterruptedException {
//1:获取FileSystem实例
FileSystem fileSystem = FileSystem.get(new URI("hdfs://192.168.217.128:9000"), new Configuration(),"root");
//2:调用方法,实现文件的下载
fileSystem.copyToLocalFile(new Path("/a.txt"), new Path("D://a4.txt"));
//3:关闭FileSystem
fileSystem.close();
}
如下图,本地有a4.txt文件,,同样可以执行成功!!!
由于Hadoop擅长储存大文件,因为大文件的元数据信息比较少,如果Hadoop集群中有大量的小文件,那么每个小文件都需要维护一份元数据信息,会大大的增加集群管理元数据的内存压力,所以在实际工作当中,如果有必要一定要将小文件合并成为大文件进行一起处理。
在我们的HDFS的Shell命令模式下,可以通过命令行将很多hdfs文件合并成一个大文件下载到本地。
例如我们将hdfs根目录下的xml文件合并成hello.xml文件并且下载到本地:
hdfs dfs -getmerge /*.xml ./hello.xml
如上图所示,本地hello.xml文件的内容则是core-site.xml文件和hdfs-site.xml文件内容的合并。
既然可以在下载的时候将这些小文件合并成一个大文件下载,那么就能在本地合并小文件进行上传。
/* 小文件的合并 */ @Test public void mergeFile() throws URISyntaxException, IOException, InterruptedException { //1:获取FileSystem(分布式文件系统),,伪装用户root FileSystem fileSystem = FileSystem.get(new URI("hdfs://node01:8020"), new Configuration(),"root"); //2:获取hdfs大文件的输出流 FSDataOutputStream outputStream = fileSystem.create(new Path("/big_txt.txt")); //3:获取一个本地文件系统 LocalFileSystem localFileSystem = FileSystem.getLocal(new Configuration()); //4:获取本地文件夹下所有文件的详情 FileStatus[] fileStatuses = localFileSystem.listStatus(new Path("D:\\input")); //5:遍历每个文件,获取每个文件的输入流 for (FileStatus fileStatus : fileStatuses) { FSDataInputStream inputStream = localFileSystem.open(fileStatus.getPath()); //6:将小文件的数据复制到大文件 IOUtils.copy(inputStream, outputStream); IOUtils.closeQuietly(inputStream); } //7:关闭流 IOUtils.closeQuietly(outputStream); localFileSystem.close(); fileSystem.close(); }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。