1.Java代码操作HDFS需要用到Jar包和Java类
Jar包:
hadoop-common-2.6.0.jar和hadoop-hdfs-2.6.0.jar
Java类:
java.net.URL
org.apache.hadoop.fs.FsUrlStreamHandlerFactory
java.net.URI
org.apache.hadoop.conf.Configuration
org.apache.hadoop.fs.FileSystem
org.apache.hadoop.fs.Path
org.apache.hadoop.io.IOUtils
2.读文件的过程
客户端(client)用FileSystem的open()函数打开文件,DistributedFileSystem用RPC调用名称节点,得到文件的数据块信息。对于每一个数据块,名称节点返回保存数据块的数据节点的地址。
DistributedFileSystem返回FSDataInputStream给客户端,用来读取数据。
客户端调用stream的read()函数开始读取数据。DFSInputStream连接保存此文件第一个数据块的最近的数据节点。
Data从数据节点读到客户端(client),当此数据块读取完毕时,DFSInputStream关闭和此数据节点的连接,然后连接此文件下一个数据块的最近的数据节点。
当客户端读取完毕数据的时候,调用FSDataInputStream的close函数。
在读取数据的过程中,如果客户端在与数据节点通信出现错误,则尝试连接包含此数据块的下一个数据节点。失败的数据节点将被记录,以后不再连接。
3.上代码:
写文件 create
读取文件 open
删除文件delete
创建目录 mkdirs
删除文件或目录 delete
列出目录的内容 listStatus
显示文件系统的目录和文件的元数据信息 getFileStatus
ReadHdfsFile.java
1 importjava.io.IOException;2 importjava.io.InputStream;3 importjava.net.URISyntaxException;4 importjava.net.URL;5
6 importorg.apache.hadoop.conf.Configuration;7 importorg.apache.hadoop.fs.FSDataInputStream;8 importorg.apache.hadoop.fs.FSDataOutputStream;9 importorg.apache.hadoop.fs.FileStatus;10 importorg.apache.hadoop.fs.FileSystem;11 importorg.apache.hadoop.fs.FsUrlStreamHandlerFactory;12
13 importjava.net.URI;14 importorg.apache.hadoop.fs.Path;15 importorg.apache.hadoop.io.IOUtils;16
17 public classReadHdfsFile {18 //让Java程序识别HDFS的URL
19 static{20 URL.setURLStreamHandlerFactory(newFsUrlStreamHandlerFactory());21 }22 static String fileSystemUri = "hdfs://192.168.211.130:9000";23
24 public static void main(String[] args) throwsException {25 String fileHdfsPath = "hdfs://192.168.211.130:9000/user/root/metafile2.xml";26 String fileHdfsPath2 = "hdfs://192.168.211.130:9000/user/root/metafile.xml";27 String fileHdfsPath3 = "hdfs://192.168.211.130:9000/user/root/metafile3.xml";28 String fileHdfsPath4 = "hdfs://192.168.211.130:9000/user/root/testCopy.txt";29 String localFilePath = "D://test.txt";30 String folderHdfsPath = "hdfs://192.168.211.130:9000/bbb";31 //mkdir(folderHdfsPath);32 //readFilePrint(fileHdfsPath);33 //judgeFileOrFolder(fileHdfsPath2);34 //rmdir(folderHdfsPath);
35 readFileAndCopy(localFilePath,fileHdfsPath4);36 readFilePrint(fileHdfsPath4);37
38 }39 /**
40 * 打印hdfs上指定的文本文件41 *@paramfileHdfsPath42 *@throwsURISyntaxException43 *@throwsIOException44 */
45 private static void readFilePrint(String fileHdfsPath) throwsURISyntaxException, IOException {46 FileSystem fileSystem =getFileSystem(fileSystemUri);47 FSDataInputStream hdfsInputStream = fileSystem.open(newPath(fileHdfsPath));48
49 byte[] ioBuffer = new byte[1024];50 int readLen =hdfsInputStream.read(ioBuffer);51 while(readLen != -1){52 System.out.write(ioBuffer, 0, readLen);53 readLen =hdfsInputStream.read(ioBuffer);54 }55 hdfsInputStream.close();56 fileSystem.close();57 }58 /**
59 * 得到hdfs文件系统对象60 *@paramfileSystemUri61 *@return
62 *@throwsURISyntaxException63 *@throwsIOException64 */
65 private static FileSystem getFileSystem(String fileSystemUri) throwsURISyntaxException,66 IOException {67 Configuration conf = newConfiguration();68 conf.set("fs.hdfs.impl",org.apache.hadoop.hdfs.DistributedFileSystem.class.getName());69 conf.set("fs.file.impl", org.apache.hadoop.fs.LocalFileSystem.class.getName());70 URI uri = newURI(fileSystemUri);71 final FileSystem fileSystem =FileSystem.get(uri, conf);72 returnfileSystem;73 }74
75 /**
76 * 读取文件,调用fileSystem的open(path)77 *@throwsException78 */
79 private static void readFileAndCopy(String sourceFileHdfsPath,String targetFileHdfsPath) throwsException {80 FileSystem fileSystem =getFileSystem(fileSystemUri);81 //获得这段代码运行的时所处的系统(如果在windows上运行就是Windows本地操作系统)
82 Configuration configuration=newConfiguration();83 FileSystem locationFileSystem=FileSystem.getLocal(configuration);84
85 FSDataInputStream inputStream = null;86 FSDataOutputStream outputStream = null;87 //输出路径
88 Path outPath = newPath(targetFileHdfsPath);89 if(sourceFileHdfsPath.startsWith("hdfs://")){90 inputStream = fileSystem.open(newPath(sourceFileHdfsPath));91 }else{92 inputStream = locationFileSystem.open(newPath(sourceFileHdfsPath));93 }94 //打开输出流
95 if(!(fileSystem.exists(outPath))){96 outputStream =fileSystem.create(outPath);97 }else{98 outputStream =fileSystem.append(outPath);99 }100
101 IOUtils.copyBytes(inputStream, outputStream, 1024, false);102 IOUtils.closeStream(inputStream);103 }104 /*
105 各个参数所代表的含义:106 in: 是FSDataInputStream类的对象,是有关读取文件的类,也就是所谓“输入流”107 out:是FSDataOutputStream类的对象,是有关文件写入的类,也就是“输出流”108 4096表示用来拷贝的buffer大小(buffer是缓冲区)109 false表明拷贝完成后我们并不关闭拷贝源可拷贝目的地110 上面inputStream和outputStream都是通过FileSystem类111 fileSystem和fs都是FileSystem类的对象,path和block都是路径Path类的对象112 然后IOUtils.copyBytes(in, out, 4096, false)方法实现了文件合并及上传至hdfs上113 */
114
115
116 /**
117 * 创建目录,调用fileSystem的mkdirs(path)118 *@throwsException119 */
120 private static void mkdir(String folderHdfsPath) throwsException {121 FileSystem fileSystem =getFileSystem(fileSystemUri);122 fileSystem.mkdirs(newPath(folderHdfsPath));123 }124
125 /**
126 * 删除目录,调用fileSystem的deleteOnExit(path)127 *@throwsException128 */
129 private static void rmdir(String folderHdfsPath) throwsException {130 FileSystem fileSystem =getFileSystem(fileSystemUri);131 fileSystem.delete(newPath(folderHdfsPath));132 }133
134 /**
135 * 遍历目录,使用FileSystem的listStatus(path) 如果要查看file状态,使用FileStatus对象136 *@throwsException137 */
138 private static void judgeFileOrFolder(String fileHdfsPath) throwsException {139 FileSystem fileSystem =getFileSystem(fileSystemUri);140 FileStatus[] listStatus = fileSystem.listStatus(newPath(fileHdfsPath));141 for(FileStatus fileStatus : listStatus) {142 String isDir = fileStatus.isDir() ? "目录" : "文件";143 String name =fileStatus.getPath().toString();144 System.out.println(isDir + " " +name);145 }146 }147
148 }
如果代码中报AccessControlException: Permission denied:
在conf/hdfs-site.xml增加
dfs.permissions
false
中文字符集:/etc/sysconfig/i18n