这里主要是利用Hadoop提供的API来操作,在本地编写代码,操作集群上的HDFS.
本篇介绍的是若干从HDFS读取文件的操作.
工具:IntelliJ IDEA Community Edition 2018.1.3
使用此方法的话,需要进行一些其他操作.此处读取的是hdfs-site.xml这个配置文件,取出前100字节并输出.
import org.apache.hadoop.fs.FsUrlStreamHandlerFactory;
import org.apache.hadoop.io.IOUtils;
import java.io.InputStream;
import java.net.URL;
public class ReadFromHdfs {
static {
//若想让Java识别hdfs地址,还需要进行如下操作:
URL.setURLStreamHandlerFactory(new FsUrlStreamHandlerFactory());
}
public static void main(String[] args) throws Exception{
//创建一个输入流,URL对象传入namenode的地址,默认端口是9000.
InputStream in = new URL("hdfs://192.168.133.153:9000/test/read/hdfs-site.xml").openStream();
//有一个问题,如果配置了HA,那么就需要传入active状态的namenode的地址.
byte[] get = new byte[100];
in.read(get);
String read = new String(get);
IOUtils.closeStream(in);//非常实用的IOUtils类,在hadoop.io包中
System.out.println(read);
}
}
运行结果如下(只贴上输出内容):
<
上面出现了一个IOUtils类,这次我们使用它来进行读取并输出.
同样需要进行准备工作,这里只贴出主方法的代码.
InputStream in = new URL("hdfs://192.168.133.153:9000/test/read/hdfs-site.xml").openStream();
//参数顺序:输入流,输出流,缓冲区大小,结束后是否关闭流
IOUtils.copyBytes(in, System.out, 100, false);
IOUtils.closeStream(in);
输出内容就是整个hdfs-site.xml文件.
每次都要使用static块进行准备工作,那么有没有不需要static块的方法呢?此时可以利用FileSystem类.
注意这里是URI对象,不是URL对象,这次选择在IOUtils里面关闭流.还有要注意Path应该是hadoop.fs下的Path
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IOUtils;
import java.io.InputStream;
import java.net.URI;
public class ReadFromHdfs {
public static void main(String[] args) throws Exception{
String uri = "hdfs://192.168.133.153:9000/test/read/hdfs-site.xml";//文件地址
Configuration configuration = new Configuration();//创建配置对象,封装了客户端或服务器的配置.
FileSystem fs = FileSystem.get(URI.create(uri), configuration);//获取FileSystem实例
InputStream in = fs.open(new Path(uri));//Path同Java中的File,但是不能替换使用.
IOUtils.copyBytes(in, System.out, 100, true);
}
}
输出结果依旧是hdfs-site.xml文件的内容,只是输出结果的速度要慢于URL方式.
下面来试试把HDFS的文件下载至本地.
需要考虑何时利用Path或File.针对本地文件的操作要使用File,针对HDFS的操作要使用Path.
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.io.IOUtils;
import org.apache.hadoop.fs.*;
import java.io.*;
import java.net.URI;
public class CopyToLocal {
public static void main(String[] args) throws Exception{
String localPath = "E:\\Hadoop\\hdfs-site.xml";//本地磁盘位置
String hdfsPath = "hdfs://192.168.133.153:9000/test/read/hdfs-site.xml";//hdfs位置
Configuration configuration = new Configuration();
FileSystem fs = FileSystem.get(URI.create(hdfsPath), configuration);
FileOutputStream out = new FileOutputStream(new File(localPath));//通过输出流保存至本地
InputStream in = fs.open(new Path(hdfsPath));
IOUtils.copyBytes(in, out, 100, true);
System.out.println("下载完成.");
}
}
这次我们试试从任意位置开始读取文件,使用的是seek(long 文件位置).这次使用FSDataInputStream对象进行读取.
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.*;
import org.apache.hadoop.io.IOUtils;
import java.net.URI;
public class RandomRead {
public static void main(String[] args) throws Exception{
String uri = "hdfs://192.168.133.153:9000/test/read/hdfs-site.xml";
Configuration configuration = new Configuration();
FileSystem fs = FileSystem.get(URI.create(uri), configuration);
FSDataInputStream in = fs.open(new Path(uri));
in.seek(100);//可以跳到指定的字节开始读取
IOUtils.copyBytes(in, System.out, 100, true);
}
}
输出内容就是从第101字节开始的内容.跳过的内容就是第1个例子的输出~
!--
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
..........