Hadoop是采用Java实现的,所有的命令和操作全部采用Java完成。
HDFS: Hadoop Distributed File System 是Hadoop提供的分布式文件系统。
本文介绍HDFS的Java API
1 2 3 4 5
| <dependency> <groupId>org.apache.hadoop</groupId> <artifactId>hadoop-core</artifactId> <version>1.2.1</version> </dependency>
|
首先,看一个例子:
putMerge: 本地文件合并并保存到HDFS
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
|
private static void putMerge(String srcDir, String objectFileName) { System.out.println("srcDir:" + srcDir+"\t objDir:" + objectFileName); Configuration conf = new Configuration(); FileSystem hdfs = null; LocalFileSystem local = null;
try { hdfs = FileSystem.get(conf); local = FileSystem.getLocal(conf); Path inputDir = new Path(srcDir); System.out.println("inputDir: " + inputDir); System.out.println("local.homeDirectory: " + local.getHomeDirectory()); System.out.println("local.workingDirectory: " + local.getWorkingDirectory()); System.out.println("local.uri: " + local.getUri()); System.out.println("local.conf: " + local.getConf());
FileStatus[] inputFiles = local.listStatus(inputDir); System.out.println("inputFiles: " + inputFiles); for (FileStatus inputFile : inputFiles) { System.out.println("inputFile: " + inputFile); } if (inputFiles.length == 0) { System.err.println("input file path is empty!"); System.exit(1); } Path hdfsFile = new Path(objectFileName); FSDataOutputStream out = hdfs.create(hdfsFile, new Progressable() { @Override public void progress() { System.out.print("*"); } }); for (FileStatus inputFile : inputFiles) { System.out.println("inputFile.path.name: " + inputFile.getPath().getName()); FSDataInputStream in = local.open(inputFile.getPath()); byte buffer[] = new byte[256]; int bytesRead = 0; while ((bytesRead = in.read(buffer)) > 0) { out.write(buffer, 0, bytesRead); } in.close(); System.out.println(); } out.close(); } catch (IOException e) { e.printStackTrace(); } System.out.println(); }
|
执行:
- 打包
- 复制到container
1
| docker cp ~/IdeaProjects/MyTest/out/artifacts/HadoopTest_jar/HadoopTest.jar hadoop0:/root/putMerge.jar
|
- 执行
1
| hadoop jar putMerge.jar en002 en002.txt
|
执行结果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| version 1 args:en002 args:en002.txt srcDir:en002 objDir:en002.txt inputDir: en002 local.homeDirectory: file:/root local.workingDirectory: file:/root local.uri: file:/// local.conf: Configuration: core-default.xml, core-site.xml, mapred-default.xml, mapred-site.xml, yarn-default.xml, yarn-site.xml, hdfs-default.xml, hdfs-site.xml inputFiles: [Lorg.apache.hadoop.fs.FileStatus;@4073c6c9 inputFile: DeprecatedRawLocalFileStatus{path=file:/root/en002/shengjing.txt; isDirectory=false; length=4467663; replication=1; blocksize=33554432; modification_time=1495535613000; access_time=0; owner=; group=; permission=rw-rw-rw-; isSymlink=false} inputFile: DeprecatedRawLocalFileStatus{path=file:/root/en002/at.txt; isDirectory=false; length=829203; replication=1; blocksize=33554432; modification_time=1495535613000; access_time=0; owner=; group=; permission=rw-rw-rw-; isSymlink=false} inputFile: DeprecatedRawLocalFileStatus{path=file:/root/en002/abc.txt; isDirectory=false; length=0; replication=1; blocksize=33554432; modification_time=1495543277000; access_time=0; owner=; group=; permission=rw-rw-rw-; isSymlink=false} inputFile: DeprecatedRawLocalFileStatus{path=file:/root/en002/a.txt; isDirectory=false; length=18516; replication=1; blocksize=33554432; modification_time=1495535613000; access_time=0; owner=; group=; permission=rw-rw-rw-; isSymlink=false} inputFile: DeprecatedRawLocalFileStatus{path=file:/root/en002/av.txt; isDirectory=false; length=189407; replication=1; blocksize=33554432; modification_time=1495535613000; access_time=0; owner=; group=; permission=rw-rw-rw-; isSymlink=false} inputFile: DeprecatedRawLocalFileStatus{path=file:/root/en002/David.txt; isDirectory=false; length=1519616; replication=1; blocksize=33554432; modification_time=1495535613000; access_time=0; owner=; group=; permission=rw-rw-rw-; isSymlink=false} inputFile: DeprecatedRawLocalFileStatus{path=file:/root/en002/Oliver.txt; isDirectory=false; length=981553; replication=1; blocksize=33554432; modification_time=1495535613000; access_time=0; owner=; group=; permission=rw-rw-rw-; isSymlink=false} inputFile: DeprecatedRawLocalFileStatus{path=file:/root/en002/Jane.txt; isDirectory=false; length=1114997; replication=1; blocksize=33554432; modification_time=1495535613000; access_time=0; owner=; group=; permission=rw-rw-rw-; isSymlink=false} inputFile: DeprecatedRawLocalFileStatus{path=file:/root/en002/Romeo.txt; isDirectory=false; length=145397; replication=1; blocksize=33554432; modification_time=1495535613000; access_time=0; owner=; group=; permission=rw-rw-rw-; isSymlink=false} inputFile.path.name: shengjing.txt
inputFile.path.name: at.txt ******* inputFile.path.name: abc.txt
inputFile.path.name: a.txt
inputFile.path.name: av.txt ******* inputFile.path.name: David.txt ****************************************************************** inputFile.path.name: Oliver.txt *************************** inputFile.path.name: Jane.txt ********************************** inputFile.path.name: Romeo.txt ** **
|
可能出现的问题:
LocalFileSystem.listStatus返回为 empty, 可能的原因有:
- Hadoop没有权限读取目录或目录中的文件
- 本地目录中的文件是中文的,而系统不支持显示中文
FileSystem
DOCS-FileSystem
FileSystem 是Hadoop提供的操作本地文件和HDFS中文件的API,可以实现CRUD等操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
|
public FSDataOutputStream append(Path f) throws IOException
public void concat(Path trg,Path[] psrcs) throws IOException
public abstract boolean rename(Path src, Path dst) throws IOException
|
创建目录
1 2 3 4 5
| Configuration conf = new Configuration(); FileSystem fs = FileSystem.get(conf); Path path = new Path("/user/hadoop/data/20130709"); fs.create(path); fs.close();
|
删除目录
1 2 3 4 5
| Configuration conf = new Configuration(); FileSystem fs = FileSystem.get(conf); Path path = new Path("/user/hadoop/data/20130710"); fs.delete(path); fs.close();
|
写文件
1 2 3 4 5 6
| Configuration conf = new Configuration(); FileSystem fs = FileSystem.get(conf); Path path = new Path("/user/hadoop/data/write.txt"); FSDataOutputStream out = fs.create(path); out.writeUTF("da jia hao,cai shi zhen de hao!"); fs.close();
|
读文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| Configuration conf = new Configuration(); FileSystem fs = FileSystem.get(conf); Path path = new Path("/user/hadoop/data/write.txt"); if(fs.exists(path)){ FSDataInputStream is = fs.open(path); FileStatus status = fs.getFileStatus(path); byte[] buffer = new byte[Integer.parseInt(String.valueOf(status.getLen()))]; is.readFully(0, buffer); is.close(); fs.close(); System.out.println(buffer.toString()); }
|
上传本地文件到HDFS
1 2 3 4 5 6 7
| Configuration conf = new Configuration(); FileSystem fs = FileSystem.get(conf); Path src = new Path("/home/hadoop/word.txt"); Path dst = new Path("/user/hadoop/data/");
fs.copyFromLocalFile(src, dst); fs.close();
|
删除文件
1 2 3 4 5 6
| Configuration conf = new Configuration(); FileSystem fs = FileSystem.get(conf);
Path path = new Path("/user/hadoop/data/word.txt"); fs.delete(path); fs.close();
|
获取给定目录下的所有子目录以及子文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| Configuration conf = new Configuration(); FileSystem fs = FileSystem.get(conf); Path path = new Path("/user/hadoop"); getFile(path,fs);
...
public static void getFile(Path path,FileSystem fs) throws IOException { FileStatus[] fileStatus = fs.listStatus(path); for(int i=0;i<fileStatus.length;i++){ if(fileStatus[i].isDir()){ Path p = new Path(fileStatus[i].getPath().toString()); getFile(p,fs); }else{ System.out.println(fileStatus[i].getPath().toString()); } } }
|
查找某个文件在HDFS集群的位置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
|
public static void getFileLocal() throws IOException{ Configuration conf = new Configuration(); FileSystem fs = FileSystem.get(conf); Path path = new Path("/user/hadoop/data/write.txt"); FileStatus status = fs.getFileStatus(path); BlockLocation[] locations = fs.getFileBlockLocations(status, 0, status.getLen()); int length = locations.length; for(int i=0;i<length;i++){ String[] hosts = locations[i].getHosts(); System.out.println("block_" + i + "_location:" + hosts[i]); } }
|
HDFS集群上所有节点名称信息
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
|
public static void getHDFSNode() throws IOException{ Configuration conf = new Configuration(); FileSystem fs = FileSystem.get(conf);
DistributedFileSystem dfs = (DistributedFileSystem)fs; DatanodeInfo[] dataNodeStats = dfs.getDataNodeStats(); for(int i=0;i<dataNodeStats.length;i++){ System.out.println("DataNode_" + i + "_Node:" + dataNodeStats[i].getHostName()); } }
|
读写
FSDataInputStream 与 FSDataOutputStream
FSDataInputStream 扩展了 DataInputStream 以支持随机读
TextInputFormat 是 InputFormat 的默认实现, TextInputFormat
返回的键是每行的字节偏移量,返回的值是该行的数据。
key: LongWritable
value: Text
KeyValueTextInputFormat 使用分隔符分割每行,分隔符之前的是键,之后的是值。默认的分隔符是制表符(\T),分离器的属性通过
key.value.separator.in.input.line中指定
key: Text
value: Text
SequenceFileInputFormat<K,V> 用户自定义的序列化格式, 序列化文件为Hadoop专用的压缩二进制文件格式
key: K 用户定义
value: V 用户定义
NLineInputFormat key为分片的偏移量,value为包含N行数据的片段,N通过属性 mapred.line.inout.format.linespermap中指定,默认为1
key: LongWritable
value: Text
【参考文献】