在执行hadoop fs -copyToLocal命令时,本地文件系统中的文件不能存在,不能进行覆写。在某些情况下,比如:使用命名管道时,由于本地管道文件不能存在,这使得应用通过命名管道与HDFS集成时造成问题。
在这篇博文中,将介绍使用hadoop libdfs(C API)编写的一个解决这个问题的示例程序。这个示例程序只是起到抛砖引玉的作业,在实际使用时还需要加入错误处理,参数校验等代码。
1. C程序示例代码(copy_to_local.c)
#include
#include "hdfs.h"
#define BSIZE 8192
int main(int argc, char **argv)
{
char iobuf [BSIZE];
int fTo;
int count=0;
int count1=0;
int offset=0;
hdfsFS fs = hdfsConnectAsUserNewInstance("HAIQ-DB-01", 8020,"sybiq");
if (!fs) {
fprintf(stderr, "connect fail\n");
return -1;
}
hdfsFile readFile = hdfsOpenFile(fs, argv[1], O_RDONLY, BSIZE, 0, 0);
if (!readFile) {
fprintf(stderr, "open hdfs file fali\n");
return -1;
}
if((fTo=open(argv[2],O_WRONLY|O_CREAT,S_IRUSR|S_IWUSR))
fprintf(stderr, "open local file fali errorno:%d\n",errno);
return -1;
}
while((count=hdfsRead(fs,readFile,iobuf,BSIZE))) {
offset+=count;
if(count
fprintf(stderr,"read hdfs file error.\n");
hdfsCloseFile(fs, readFile);
hdfsDisconnect(fs);
close(fTo);
return (1);
}
else if ((count1=write(fTo,iobuf,count))) {
if(count1!=count) {
fprintf(stderr,"write local file error at offset %d. error:%d count1:%d\n",offset,errno,count1);
hdfsCloseFile(fs, readFile);
hdfsDisconnect(fs);
close(fTo);
return (1);
}
}
memset(iobuf,0,BSIZE);
}
hdfsCloseFile(fs, readFile);
hdfsDisconnect(fs);
close(fTo);
return (0);
}
2. 编译C程序
编译示例如下:
--build.sh
gcc $1.c -I$HADOOP_HOME/include -L$HADOOP_HOME/lib/native -L$JAVA_HOME/jre/lib/amd64/server -lhdfs -ljvm -o $1
执行 ./build.sh copy_to_local 编译c程序。
3. 设置执行环境
Hadoop libhdfs(C API)是对java api的C语言封装,在程序执行时需要通过设置相应的环境变量,装载需要的java类库。在Linux操作系统下,在用户的.profile(或 .bash_profile)文件中增加如下内容:
CLASSPATH=${JAVA_HOME}/lib:${JAVA_HOME}/jre/lib
CLASSPATH=${CLASSPATH}`find ${HADOOP_HOME}/share/hadoop | grep -i ".jar" | awk '{path=path":"$0}END{print path}'`
4. 使用示例
使用示例,参见如下博文: