
# HDFS C API接口介绍
#### 功能简介
C语言应用开发代码样例中所涉及的文件操作主要包括创建文件、读写文件、追加文件、删除文件。完整和详细的接口请直接参考官网上的描述以了解其使用方法：<https://hadoop.apache.org/docs/r3.1.1/hadoop-project-dist/hadoop-hdfs/LibHdfs.html>。
#### 代码样例
下面代码片段仅为演示，具体代码请参见获取样例代码解压目录中"HDFS/hdfs-c-example/hdfs_test.c"文件。
1. 设置HDFS NameNode参数，建立HDFS文件系统连接。
   ```
   hdfsFS fs = hdfsConnect("default", 0);
   fprintf(stderr, "hdfsConnect- SUCCESS!\n");
   ```
   
2. 创建HDFS目录。
   ```
   const char* dir = "/tmp/nativeTest";
   int exitCode = hdfsCreateDirectory(fs, dir);
   if( exitCode == -1 ){
        fprintf(stderr, "Failed to create directory %s \n", dir );
        exit(-1);
   }
   fprintf(stderr, "hdfsCreateDirectory- SUCCESS! : %s\n", dir);
   ```
   
3. 写文件。
   ```
   const char* file = "/tmp/nativeTest/testfile.txt";
   hdfsFile writeFile = openFile(fs, (char*)file, O_WRONLY |O_CREAT, 0, 0, 0);
   fprintf(stderr, "hdfsOpenFile- SUCCESS! for write : %s\n", file);
   if(!hdfsFileIsOpenForWrite(writeFile)){
       fprintf(stderr, "Failed to open %s for writing.\n", file);
       exit(-1);
   }
   char* buffer = "Hadoop HDFS Native file write!";
   hdfsWrite(fs, writeFile, (void*)buffer, strlen(buffer)+1);
   fprintf(stderr, "hdfsWrite- SUCCESS! : %s\n", file);
   printf("Flushing file data ....\n");
   if (hdfsFlush(fs, writeFile)) {
        fprintf(stderr, "Failed to 'flush' %s\n", file);
        exit(-1);
   }
   hdfsCloseFile(fs, writeFile);
   fprintf(stderr, "hdfsCloseFile- SUCCESS! : %s\n", file);
   ```
   
4. 读文件。
   ```
   hdfsFile readFile = openFile(fs, (char*)file, O_RDONLY, 100, 0, 0);
   fprintf(stderr, "hdfsOpenFile- SUCCESS! for read : %s\n", file);
   if(!hdfsFileIsOpenForRead(readFile)){
       fprintf(stderr, "Failed to open %s for reading.\n", file);
       exit(-1);
   }
   buffer = (char *) malloc(100);
   tSize num_read = hdfsRead(fs, readFile, (void*)buffer, 100);
   fprintf(stderr, "hdfsRead- SUCCESS!, Byte read : %d, File contant : %s \n", num_read ,buffer);
   hdfsCloseFile(fs, readFile);
   ```
   
5. 指定位置开始读文件。
   ```
   buffer = (char *) malloc(100);
   readFile = openFile(fs, file, O_RDONLY, 100, 0, 0);
   if (hdfsSeek(fs, readFile, 10)) {
        fprintf(stderr, "Failed to 'seek' %s\n", file);
        exit(-1);
   }
   num_read = hdfsRead(fs, readFile, (void*)buffer, 100);
   fprintf(stderr, "hdfsSeek- SUCCESS!, Byte read : %d, File seek contant : %s \n", num_read ,buffer);
   hdfsCloseFile(fs, readFile);
   ```
   
6. 复制文件。
   ```
   const char* destfile = "/tmp/nativeTest/testfile1.txt";
   if (hdfsCopy(fs, file, fs, destfile)) {
       fprintf(stderr, "File copy failed, src : %s, des : %s \n", file, destfile);
       exit(-1);
   }
   fprintf(stderr, "hdfsCopy- SUCCESS!, File copied, src : %s, des : %s \n", file, destfile);
   ```
   
7. 移动文件。
   ```
   const char* mvfile = "/tmp/nativeTest/testfile2.txt";
   if (hdfsMove(fs, destfile, fs, mvfile )) {
       fprintf(stderr, "File move failed, src : %s, des : %s \n", destfile , mvfile);
       exit(-1);
   }
   fprintf(stderr, "hdfsMove- SUCCESS!, File moved, src : %s, des : %s \n", destfile , mvfile);
   ```
   
8. 重命名文件。
   ```
   const char* renamefile = "/tmp/nativeTest/testfile3.txt";
   if (hdfsRename(fs, mvfile, renamefile)) {
        fprintf(stderr, "File rename failed, Old name : %s, New name : %s \n", mvfile, renamefile);
        exit(-1);
   }
   fprintf(stderr, "hdfsRename- SUCCESS!, File renamed, Old name : %s, New name : %s \n", mvfile, renamefile);
   ```
   
9. 删除文件。
   ```
   if (hdfsDelete(fs, renamefile, 0)) {
       fprintf(stderr, "File delete failed : %s \n", renamefile);
       exit(-1);
   }
   fprintf(stderr, "hdfsDelete- SUCCESS!, File deleted : %s\n",renamefile);
   ```
   
10. 设置副本数。
    ```
    if (hdfsSetReplication(fs, file, 10)) {
        fprintf(stderr, "Failed to set replication : %s \n", file );
        exit(-1);
    }
    fprintf(stderr, "hdfsSetReplication- SUCCESS!, Set replication 10 for %s\n",file);
    ```
    
11. 设置用户、用户组。
    ```
    if (hdfsChown(fs, file, "root", "root")) {
       fprintf(stderr, "Failed to set chown : %s \n", file );
       exit(-1);
    }
    fprintf(stderr, "hdfsChown- SUCCESS!, Chown success for %s\n",file);
    ```
    
12. 设置权限。
    ```
    if (hdfsChmod(fs, file, S_IRWXU | S_IRWXG | S_IRWXO)) {
       fprintf(stderr, "Failed to set chmod: %s \n", file );
       exit(-1);
    }
    fprintf(stderr, "hdfsChmod- SUCCESS!, Chmod success for %s\n",file);
    ```
    
13. 设置文件时间。
    ```
    struct timeval now;
    gettimeofday(&now, NULL);
    if (hdfsUtime(fs, file, now.tv_sec, now.tv_sec)) {
       fprintf(stderr, "Failed to set time: %s \n", file );
       exit(-1);
    }
    fprintf(stderr, "hdfsUtime- SUCCESS!, Set time success for %s\n",file);
    ```
    
14. 获取文件信息。
    ```
    hdfsFileInfo *fileInfo = NULL;
    if((fileInfo = hdfsGetPathInfo(fs, file)) != NULL) {
       printFileInfo(fileInfo);
       hdfsFreeFileInfo(fileInfo, 1);
       fprintf(stderr, "hdfsGetPathInfo - SUCCESS!\n");
    }
    ```
    
15. 遍历目录。
    ```
    hdfsFileInfo *fileList = 0;
    int numEntries = 0;
    if((fileList = hdfsListDirectory(fs, dir, &numEntries)) != NULL) {
       int i = 0;
       for(i=0; i < numEntries; ++i) {
           printFileInfo(fileList+i);
       }
       hdfsFreeFileInfo(fileList, numEntries);
    }
    fprintf(stderr, "hdfsListDirectory- SUCCESS!, %s\n", dir);
    ```
    
16. stream builder接口。
    ```
    buffer = (char *) malloc(100);
    struct hdfsStreamBuilder *builder= hdfsStreamBuilderAlloc(fs, (char*)file, O_RDONLY);
    hdfsStreamBuilderSetBufferSize(builder,100);
    hdfsStreamBuilderSetReplication(builder,20);
    hdfsStreamBuilderSetDefaultBlockSize(builder,10485760);
    readFile = hdfsStreamBuilderBuild(builder);
    num_read = hdfsRead(fs, readFile, (void*)buffer, 100);
    fprintf(stderr, "hdfsStreamBuilderBuild- SUCCESS! File read success. Byte read : %d, File contant : %s \n", num_read ,buffer);
    struct hdfsReadStatistics *stats = NULL;
    hdfsFileGetReadStatistics(readFile, &stats);
    fprintf(stderr, "hdfsFileGetReadStatistics- SUCCESS! totalBytesRead : %" PRId64 ", totalLocalBytesRead : %" PRId64 ", totalShortCircuitBytesRead : %" PRId64 ", totalZeroCopyBytesRead : %" PRId64 "\n", stats->totalBytesRead , stats->totalLocalBytesRead, stats->totalShortCircuitBytesRead,  stats->totalZeroCopyBytesRead);
    hdfsFileFreeReadStatistics(stats);
    free(buffer);
    ```
    
17. 断开HDFS文件系统连接。
    ```
    hdfsDisconnect(fs);
    ```
    
 
#### 准备运行环境
在节点上安装客户端，例如安装到"/opt/client"目录。
#### Linux中编译并运行程序
1. 进入Linux客户端目录，运行如下命令导入公共环境变量： **cd** /*opt/client*
   **source bigdata_env**
   
2. 在该目录下用hdfs用户进行命令行认证，用户密码请咨询集群管理员。
   *kinit* *hdfs*
   ![](https://support.huaweicloud.com/devg-lts-mrs/public_sys-resources/note_3.0-zh-cn.png)
   kinit一次票据时效24小时。24小时后再次运行样例，需要重新**kinit**命令。
   
3. 进入"/opt/client/HDFS/hadoop/hdfs-c-example"目录下，运行如下命令导入客户端环境变量。 *cd* */opt/client/HDFS/hadoop/hdfs-c-example*
   *source* *component_env_C_example*
   
4. 清除之前运行生成的目标文件和可执行文件，运行如下命令。 *make clean*
   执行结果如下：
   ```
   [root@10-120-85-2 hdfs-c-example]# make clean
   rm -f hdfs_test.o
   rm -f hdfs_test
   ```
   
5. 编译生成新的目标和可执行文件，运行如下命令。 *make* （或*make all*）
   执行结果如下：
   ```
   [root@10-120-85-2 hdfs-c-example]# make all
   cc -c -I/opt/client/HDFS/hadoop/include -Wall -o hdfs_test.o hdfs_test.c
   cc -o hdfs_test hdfs_test.o -lhdfs
   ```
   
6. 运行文件以实现创建文件、读写追加文件和删除文件的功能，运行如下命令。 *make run*
   执行结果如下：
   ```
   [root@10-120-85-2 hdfs-c-example]# make run
   ./hdfs_test
   hdfsConnect- SUCCESS!
   hdfsCreateDirectory- SUCCESS! : /tmp/nativeTest
   hdfsOpenFile- SUCCESS! for write : /tmp/nativeTest/testfile.txt
   hdfsWrite- SUCCESS! : /tmp/nativeTest/testfile.txt
   Flushing file data ....
   hdfsCloseFile- SUCCESS! : /tmp/nativeTest/testfile.txt
   hdfsOpenFile- SUCCESS! for read : /tmp/nativeTest/testfile.txt
   hdfsRead- SUCCESS!, Byte read : 31, File contant : Hadoop HDFS Native file write! 
   hdfsSeek- SUCCESS!, Byte read : 21, File seek contant : S Native file write! 
   hdfsPread- SUCCESS!, Byte read : 10, File pead contant : S Native f  
   hdfsCopy- SUCCESS!, File copied, src : /tmp/nativeTest/testfile.txt, des : /tmp/nativeTest/testfile1.txt 
   hdfsMove- SUCCESS!, File moved, src : /tmp/nativeTest/testfile1.txt, des : /tmp/nativeTest/testfile2.txt 
   hdfsRename- SUCCESS!, File renamed, Old name : /tmp/nativeTest/testfile2.txt, New name : /tmp/nativeTest/testfile3.txt 
   hdfsDelete- SUCCESS!, File deleted : /tmp/nativeTest/testfile3.txt
   hdfsSetReplication- SUCCESS!, Set replication 10 for /tmp/nativeTest/testfile.txt
   hdfsChown- SUCCESS!, Chown success for /tmp/nativeTest/testfile.txt
   hdfsChmod- SUCCESS!, Chmod success for /tmp/nativeTest/testfile.txt
   hdfsUtime- SUCCESS!, Set time success for /tmp/nativeTest/testfile.txt
   Name: hdfs://hacluster/tmp/nativeTest/testfile.txt, Type: F, Replication: 10, BlockSize: 134217728, Size: 31, LastMod: 1500345260, Owner: root, Group: root, Permissions: 511 (rwxrwxrwx)
   hdfsGetPathInfo - SUCCESS!
   Name: hdfs://hacluster/tmp/nativeTest/testfile.txt, Type: F, Replication: 10, BlockSize: 134217728, Size: 31, LastMod: 1500345260, Owner: root, Group: root, Permissions: 511 (rwxrwxrwx)
   hdfsListDirectory- SUCCESS!, /tmp/nativeTest
   hdfsTruncateFile- SUCCESS!, /tmp/nativeTest/testfile.txt
   Block Size : 134217728 
   hdfsGetDefaultBlockSize- SUCCESS!
   Block Size : 134217728 for file /tmp/nativeTest/testfile.txt
   hdfsGetDefaultBlockSizeAtPath- SUCCESS!
   HDFS Capacity : 102726873909
   hdfsGetCapacity- SUCCESS!
   HDFS Used : 4767076324
   hdfsGetCapacity- SUCCESS!
   hdfsExists- SUCCESS! /tmp/nativeTest/testfile.txt
   hdfsConfGetStr- SUCCESS : hdfs://hacluster 
   hdfsStreamBuilderBuild- SUCCESS! File read success. Byte read : 31, File contant : Hadoop HDFS Native file write! 
   hdfsFileGetReadStatistics- SUCCESS! totalBytesRead : 31, totalLocalBytesRead : 0, totalShortCircuitBytesRead : 0, totalZeroCopyBytesRead : 0
   ```
   
 
