通过FSDataOutputStream向HDFS上写数据

本文介绍如何使用FSDataOutputStream类在HDFS中创建和追加数据。通过FileSystem类与HDFS建立连接并提供实用方法实现文件系统的初始化和关闭。示例代码展示了如何检查文件是否存在以及如何根据情况选择创建新文件或追加到现有文件。

FSDataOutputStream,这个类重载了很多write方法,用于写入很多类型的数据:比如字节数组,long,int,char等等。

像FSDataInputStream一样,要获得FSDataOutputStream的实例,必须通过FileSystem该类来和HDFS建立连接,然后通过路径返回FSDataOutputStream实例。

FileSystem返回FSDataOutputStream实例的方法有两组

  1.create(Path p)函数,创建一个空文件,然后可以向该文件顺序写入

  2.append(Path p)函数,打开一个已有文件,并最做文件末尾追加数据

 

FileSystemUtil

public class FileSystemUtil {
    
    private static FileSystem fileSystem;
    
   //代码中Kerberos认证根据自己环境替换即可
public synchronized static FileSystem getFileSystem() throws IOException{ if(fileSystem==null){ Configuration conf=new Configuration(); conf.set("fs.defaultFS", "hdfs://host12.master.cluster.enn.cn:8020"); conf.set("dfs.client.block.write.replace-datanode-on-failure.policy" ,"NEVER" ); conf.set("dfs.client.block.write.replace-datanode-on-failure.enable" ,"true" ); KerberosClient.login(Constants.Kerberos_USER_NAME, Constants.Kerberos_KEYTAB_FILE); fileSystem=FileSystem.get(conf); } return fileSystem; } public synchronized static void shutdown(){ if(fileSystem!=null){ try { fileSystem.close(); fileSystem=null; } catch (IOException e) { e.printStackTrace(); } } } public static void main(String[] args) throws Exception { System.out.println(FileSystemUtil.getFileSystem()); } }

 

FSDataOutputStreamTest

public class FSDataOutputStreamTest{
    private static final Logger LOGGER = LoggerFactory.getLogger(Test.class);
    private static void hfdsAppendData() {
        String filePath = "/user/hive/warehouse/test.db/t_test/day=2017-11-29/hour=16/backup_ycgqh";
        FileSystem fileSystem = null;
        FSDataOutputStream fileOutputStream = null;
        Path hdfsPath = new Path(filePath);
        try {
            fileSystem=FileSystemUtil.getFileSystem();
            if (!fileSystem.exists(hdfsPath)) {
                fileOutputStream = fileSystem.create(hdfsPath,false);
            }else{
                fileOutputStream = fileSystem.append(hdfsPath);
            }
            fileOutputStream.writeUTF("");
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if(fileOutputStream!=null){
                try {
                    fileOutputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                FileSystemUtil.shutdown();
            }
        }
    }
}

 

转载于:https://www.cnblogs.com/weishao-lsv/p/8159285.html

### HDFS 数据的方法和流程 #### 数据入方法概述 为了在分布式文系统Hadoop Distributed File System (HDFS) 中数据,应用程序通常采用Java API来创建文入内容。这涉及到与NameNode交互以获得目标DataNodes列表,并直接同这些DataNodes通信来进行实际的数据传输。 #### 初始化连接过程 当客户端准备向HDFS上传新文时,它首先联系NameNode发起建立文的过程。此时并不立即传送任何真实的数据,而是请求分配存储空间以及获取一系列适合存放该文副本的目标DataNodes地址信息[^1]。 #### 创建管道机制 一旦得到了由NameNode返回的一组推荐用于放置首个Block的DataNodes名单后,客户端便着手构建起通往各节点之间的通讯路径——即所谓的Pipeline(管道)。此阶段还包括设置必要的参数配置如复制因子等[^3]。 #### 数据分片处理 随着pipeline的成功搭建,在正式开始发送之前,待传入的信息会被分割打包成固定大小的小单元Packet,默认情况下每64KB构成一个这样的单位。与此同时,还存在更细粒度划分出来的Chunk用来辅助校验错误检测工作。整个过程中产生的所有Packets都会被暂存于名为“数据队列”的内存缓冲区内等待进一步操作。 #### 实际数据传输环节 真正意义上的数据流动发生在上述准备工作完成后。具体而言就是从Client端发出的第一份Packet沿着预先设定好的Pipeline依次传递给每一个参与其中的Datanode直至末端。值得注意的是这里采用了流水线式的并发模式而非串行方式,从而大大提高了效率。每当有新的Block需要加入现有链条之中,则重复类似的协商定位步骤再继续扩展下去[^4]。 #### 确认反馈循环结构 在整个入期间内始终保持着一种基于ACK信号交换形成的闭环控制系统。这意味着只有当下游接收到完整的Packet并且成功持久化至磁盘之后才会向上游回送肯定应答;反之如果遇到失败情况则触发重试逻辑甚至中断整个事务。这种设计有效保障了最终一致性的同时也兼顾到了性能表现方面的要求。 #### 动态调整策略应用 考虑到集群内部拓扑变化可能带来的影响因素,对于后续新增加Blocks的选择上并非一成不变地遵循最初规划路线。相反地,每次完成一定数量级后的转储动作前都需要再次咨询NameNode意见以便及时作出最优决策。如此这般既能够充分利用资源又能维持良好的负载均衡状态[^5]。 ```java // Java代码示例:使用FileSystem类进行简单文入 Configuration conf = new Configuration(); conf.set("fs.defaultFS", "hdfs://localhost:9000"); try (FileSystem fs = FileSystem.get(conf); FSDataOutputStream output = fs.create(new Path("/user/test.txt"))) { String content = "This is a test."; output.writeBytes(content); } catch (IOException e) { e.printStackTrace(); } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值