利用API写入文件
- 写入HDFS文件
- (1)将数据直接写入HDFS文件
- (2)将本地文件写入HDFS文件
写入HDFS文件
- 类似于HDFS Shell里的
hdfs dfs -put
命令 - 在
net.zwh.hdfs
包里创建WriteFileOnHDFS
类
(1)将数据直接写入HDFS文件
- 在
/ied01
目录里创建hello.txt
文件 - 创建
write1()
方法
package net.hw.hdfs;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FSDataOutputStream;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.junit.Test;
import java.net.URI;
/**
* 功能:写入HDFS文件
*/
public class WriteFileOnHDFS {
@Test
public void write1() throws Exception {
// 创建配置对象
Configuration conf = new Configuration();
// 定义统一资源标识符(uri: uniform resource identifier)
String uri = "hdfs://master:9000";
// 创建文件系统对象(基于HDFS的文件系统)
FileSystem fs = FileSystem.get(new URI(uri), conf);
// 创建路径对象(指向文件)
Path path = new Path(uri + "/ied01/hello.txt");
// 创建文件系统数据字节输出流(出水管:数据从程序到文件)
FSDataOutputStream out = fs.create(path);
// 通过字节输出流向文件写数据
out.write("Hello Hadoop World".getBytes());
// 关闭文件系统数据字节输出流
out.close();
// 关闭文件系统对象
fs.close();
// 提示用户写文件成功
System.out.println("文件[" + path + "]写入成功!");
}
}
-
运行
write1()
测试方法,查看结果,抛出RemoteException
异常,三个数据节点都在运行,但是无法写入数据
-
修改代码,设置数据节点主机名属性,如下图所示
-
运行程序,查看结果
- 利用Hadoop WebUI查看
hello.txt
文件
(2)将本地文件写入HDFS文件
- 在项目根目录创建一个文本文件
test.txt
- 创建write2()方法
@Test
public void write2() throws Exception {
// 创建配置对象
Configuration conf = new Configuration();
// 设置数据节点主机名属性
conf.set("dfs.client.use.datanode.hostname", "true");
// 定义统一资源标识符(uri: uniform resource identifier)
String uri = "hdfs://master:9000";
// 创建文件系统对象(基于HDFS的文件系统)
FileSystem fs = FileSystem.get(new URI(uri), conf, "root");
// 创建路径对象(指向文件)
Path path = new Path(uri + "/ied01/exam.txt");
// 创建文件系统数据字节输出流(出水管:数据从程序到文件)
FSDataOutputStream out = fs.create(path);
// 创建文件字符输入流对象(进水管:数据从文件到程序)
FileReader fr = new FileReader("test.txt");
// 创建缓冲字符输入流对象
BufferedReader br = new BufferedReader(fr);
// 定义行字符串变量
String nextLine = "";
// 通过循环遍历缓冲字符输入流
while ((nextLine = br.readLine()) != null) {
// 在控制台输出读取的行
System.out.println(nextLine);
// 通过文件系统数据字节输出流对象写入指定文件
out.write((nextLine + "\n").getBytes());
}
// 关闭缓冲字符输入流
br.close();
// 关闭文件字符输入流
fr.close();
// 关闭文件系统数据字节输出流
out.close();
// 提示用户写入文件成功
System.out.println("本地文件[test.txt]成功写入[" + path + "]!");
}
- 运行
write2()
测试方法,查看结果
-
查看
/ied01/exam.txt
内容
-
其实这个方法的功能就是将本地文件复制(上传)到HDFS,有没有更简单的处理方法呢?有的,通过使用一个工具类
IOUtils
来完成文件的相关操作。
- 编写write2_()方法
@Test
public void write2_() throws Exception {
// 创建配置对象
Configuration conf = new Configuration();
// 设置数据节点主机名属性
conf.set("dfs.client.use.datanode.hostname", "true");
// 定义统一资源标识符(uri: uniform resource identifier)
String uri = "hdfs://master:9000";
// 创建文件系统对象(基于HDFS的文件系统)
FileSystem fs = FileSystem.get(new URI(uri), conf, "root");
// 创建路径对象(指向文件)
Path path = new Path(uri + "/ied01/test.txt");
// 创建文件系统数据字节输出流(出水管:数据从程序到文件)
FSDataOutputStream out = fs.create(path);
// 创建文件字节输入流(进水管:数据从文件到程序)
FileInputStream in = new FileInputStream("test.txt");
// 利用IOUtils类提供的字节拷贝方法在控制台显示文件内容
IOUtils.copyBytes(in, System.out, 1024, false);
// 利用IOUtils类提供的字节拷贝方法来复制文件
IOUtils.copyBytes(in, out, conf);
// 关闭文件字节输入流
in.close();
// 关闭文件系统数据字节输出流
out.close();
// 提示用户写入文件成功
System.out.println("本地文件[test.txt]成功写入[" + path + "]!");
}
注意导包问题
- 运行
write2_()
测试方法,查看结果
- 查看
/ied01/test.txt
内容,文件是存在的,但是没有内容
因为字节输入流的数据已经输出到到控制台,此时字节输入流里已经没有数据,此时执行
IOUtils.copyBytes(in, out, conf)
;,因此输出流肯定也没有数据可以写入文件,那该怎么办呢?再次读取文件,让字节输入流有数据。
-
运行
write2_()
方法,查看结果
-
查看
/ied01/test.txt
文件