浅析hadoop写入数据api

对于一般文件,都有满足随机读写的api。而hadoop中的读api很简单用FSDataInputStream类就可以满足一般要求,而hadoop中的写操作却是和普通java操作不一样。

hadoop对于写操作提供了一个类:FSDataOutputStream,这个类重载了很多write方法,用于写入很多类型的数据:比如字节数组,long,int,char等等。像FSDataInputStream一样,要获得FSDataOutputStream的实例,必须通过FileSystem该类来和HDFS建立连接,然后通过路径返回FSDataOutputStream实例。FileSystem返回FSDataOutputStream实例的方法有两组:

  • create(Path p)函数,创建一个空文件,然后可以向该文件顺序写入
  • append(Path p)函数,打开一个已有文件,并最做文件末尾追加数据

以上两组函数都有多个重载版本,可以查阅手册。FSDataOutputStream不允许在文件中定位(而FSDataInputStream可以),这是因为hadoop只允许在一个已打开文件顺序写入或在文件尾追加数据,不允许在结尾之外其他文件写入数据。

在使用append的操作时可能返回异常dfs.support.append未设置为true,只要才hdfs-site.xml中把该属性设置为true

  1. <property>  
  2.   <name>dfs.support.append</name>  
  3.   <value>false</value>  
  4.   <description>Does HDFS allow appends to files?  
  5.                This is currently set to false because there are bugs in the  
  6.                "append code" and is not supported in any prodction cluster.  
  7.   </description>  
  8. </property>  

而且0.20的早起版本也不支持append操作,官方文档的建议是如果追加数据就重新create一个文件。使用的时候应该谨慎一点。


当读取文件时若要返回文件的大小,用下列代码:

  1. FileStatus status=hdfs.getFileStatus(p);  
  2.             return status.getLen();  

但是当对文件写入时,FileStatus的getLen函数返回的不是当前的大小,因为FSDataInputStream在写入数据时,数据会缓存,只有当写入的数据满64M(块大小)时或者关闭文件时,才会把数据写入到文件中去。连续写入数据时,为了实时获取当前文件大小,如果连续关闭打开文件势必会影响效率。可以这样解决:

  1. long result;  
  2. if(outFsData!=null){//FSDataInputStream对象实例  
  3. result=writeInitSize+outFsData.size()//文件打开时的长度  
  4. }  
  5. else{  
  6. FileStatus status=hdfs.getFileStatus(p);  
  7. result=status.getLen();//这个getLen()返回的是int型,最大也就是4G,要注意  
  8. }  
  9. return result;  

FSDataInputStream该类的size函数就是返回的缓冲区写入的数据的大小。

没有更多推荐了,返回首页