1.用HDFS API写入数据,如何能够读到最新写入的数据?
2.如果写操作一直在进行,但没关闭FileSystem fs,如何获取所写文件的当前大小。
想获取最新写入的数据,即使写操作一直没断一直没关闭fs,如何来做呢?
用FSDataInputStream dis = fs.open(path);来做, 参考下面函数testRead函数的已注释部分。
如何获取实时的文件大小呢?
两种方式,一种用available(), 另外一种通过FileStatus的getLength()
经过测试:
(1)fs.getFileStatus.getLen():获得的是namespace上的文件状态里的文件大小;
(2)fs.open(path).available():获取文件流的可读字节大小。
比较:
getFileStatus()只能精确到block size的倍数,即写在缓存中的数据不计算在内,直等到文件关闭才将小于blocksize(当前64M)的数据写到硬盘。(hdfs写数据的原理有关,等到缓存刚好称为blocksize那么大,写入到磁盘一个blocksize的block,如果没达到blocksize,则不写到block里,此时除非关闭fs才写入磁盘中。)
而available()返回可读的字节数,当文件小时,可以实时的读取刚写完的数据,而如果数据很大(512-896M),则和前种方法返回相同数,而如果大于2G,则超过int界限4字节能代表的最大值2^31,为负值或其他的不正常的正值。
所以,如果用的话,最好用getFileStatus,long型的值。
/**
* 测试hdfs实时写实时读的性能,本函数写数据,并flush,但是flush只是客户端上传,而hdfs服务器段并不更新filestatus,
* 一直到达到block size才更新
* @param num
*/
public static void testFlushHDFS(int num) {
try {
FileSystem fs = FileSystem.get(conf);
Path path = new Path("/user/root/testflush");
if(!fs.exists(path)) {
fs.create(path);
fs.close();
}
FSDataOutputStream dis = fs.append(path);
for (int j = 0; j < num; j++) {
for (int i = 0; i < 1024*10; i++) {
dis.writeBytes("aaabbbcccdefgqwei");
}
dis.flush();
System.out.println("Has done 170K: " + j);
Thread.sleep(100);
//dis.sync();
}
dis.close();
System.out.println("close%%%%%%%%%%");
Thread.sleep(10000);
fs.close();
} catch (IOException e) {
// TODO Auto-generated catch block
System.out.println("write failed!");
e.printStackTrace();
} catch(InterruptedException e) {
System.out.println("thread wait failed!");
e.printStackTrace();
}
}
public static void testRead() {
try {
FileSystem fs = FileSystem.get(conf);
Path path = new Path(/*"/user/hadooper/testflush"*/"/user/root/testflush"/*1334937621582*/);
if(!fs.exists(path)) {
System.out.println("no file!");
return;
}
FSDataInputStream dis = fs.open(path);
long length = fs.getFileStatus(path).getLen();
System.out.println("length: " + (((double)length)/1024/1024) + "M");
int j =0;
byte[] b = new byte[1000000];
System.out.println((double)dis.available()/1024/1024);
// while(dis.read(b)>0) {
// j++;
// System.out.println("******************************************"+(j++));
// }
// System.out.println("total: 1000 * " + j);
// dis.read(b);
// for (int j = 0; j < 990; j++) {
// dis.read(b);
// System.out.println(Bytes.toString(b));
//
// }
dis.close();
fs.close();
} catch (IOException e) {
// TODO Auto-generated catch block
System.out.println("read failed!");
e.printStackTrace();
}
}