Feb 7

整理后的JS讀取文件類

Lrdcq , 2015/02/07 22:36 , 程序 , 閱讀(2184) , Via 本站原創
用JS讀取文件這個命題似乎感覺很奇怪
事實上指的在HTML5相關的API中,文件類->Blob->Buffer
讀取文件則是用DataView類讀取ArrayBuffer的過程

好的,回頭看看DataView類讀取ArrayBuffer的相關教程,沒接觸過JS的程序員一定會大罵:這TMD什麽破玩意兒
是的,我也是這麼認為的,習慣用文件指針引導文件順序閱讀和跳躍offset閱讀的人看到DataView一定會非常不爽
於是,我整理的一個我自己會覺得非常好用的JS文件閱讀類。

事實上,這個類在之前的博客文章裏面已經用到了,這個FSH文件與DXT解碼的示範代碼裏面就有用到一個Reader類,就是它
之前發的時候忘記提出來了,仔細想想這還是挺重要的東西,所以單獨發出來看看

這個類主要函數是read,並且入參為喜聞樂見的數據格式,同時支持讀取定長和不定長(遇到\0結束)的字符串,當然,也有move和seek這種東西
反正是非常符合我的胃口就是。
之前入參也有考慮用數據長度的(但是JS裏面沒有sizeof這種東西),似乎會讓代碼語義變得像C一樣頭疼,好歹發揚一下JS的優勢嘛,所以算了

好的,代碼如下
JSReader=function(file){//入參的file是個ArrayBuffer對象
  this.file=file?file:null;
  this.point=0;//模擬文件指針
  this.view=null;
}
JSReader.prototype.bindfile=function(file){
  this.file=file;
}
JSReader.prototype.seek=function(n){
  if(n){this.point=n;}
  else{return this.point;}
}
JSReader.prototype.move=function(n){
  if(n){this.point+=n;}
}
JSReader.prototype.read=function(type,length,dontmove){
//事實上的入參是[ 讀取數據類型 不要移動指針 ] 或者如果是String是 [ String 長度 不要移動指針 ]
  if(!this.file){
    return false;
  }
  if(!this.view){
    this.view=new DataView(this.file);
  }
  type=type?type:'Ulong';
  var num=0,type2='';;
  switch(type){
    case 'Char':type2='Uint';num=8;break;
    case 'Ushort':type2='Uint';num=8;break;
    case 'Short':type2='Int';num=8;break;
    case 'Uint':type2='Uint';num=16;break;
    case 'Int':type2='Int';num=16;break;
    case 'Ulong':type2='Uint';num=32;break;
    case 'Long':type2='Int';num=32;break;
    case 'Float':type2='Float';num=32;break;
    case 'Double':type2='Float';num=64;break;
  }
  try{
    if(type!='String'){
      if(this.view['get'+type2+num]){
        var o=this.view['get'+type2+num](this.point,1);
        if(!length){this.point+=num/8;}
        return type=='Char'?String.fromCharCode(o):o;
      }
    }else{
      var str='',o='a',sp=this.point;
      length=length?length:1024*1024;
      while(length){
        var o=this.view.getUint8(this.point,1);
        this.point++;
        length--;
        if(!o){break;}
        str+=String.fromCharCode(o);
      }
      if(dontmove){this.point=sp;}
      return str;
    }
  }catch(e){      
    //alert('read:文件越界!');
    return 0;
  }
}
logo