我的家園

          我的家園
            GridFSFile 類表示 GridFS 中的文件的信息,它是一個抽象類,分別被 GridFSDBFile (表示從數(shù)據(jù)庫中讀取的文件) 和 GridFSInputFile(表示將要保存到數(shù)據(jù)庫中的文件 ) 繼承。

            GridFSFile 類包含下列屬性(相應(yīng)地有一系列的  get 方法)
              Object _id;                // 文件的唯一標(biāo)識
              String _filename;          // 文件的名稱
              String _contentType;       // 文件內(nèi)容類型
              long _length;              // 文件長度
              long _chunkSize;           // 文件分塊大小
              Date _uploadDate;          // 更新時間
              List<String> _aliases;     // 別名
              DBObject _extradata = new BasicDBObject();  //額外信息
              String _md5;               // md5 值
          

            此外它還提供保存文件信息的 save 方法:
              // 保存文件
              public void save(){
                  if ( _fs == null )
                      throw new MongoException( "need _fs" );
                  _fs._filesCollection.save( this );
              }
          

          GridFSDBFile (從數(shù)據(jù)庫中讀取的文件)

            【將文件寫入輸出流】

            GridFSDBFile 的 writeTo 方法可以將文件寫入輸出流,以達到讀取文件數(shù)據(jù)的目的。
              // 將文件寫入輸出流
              public long writeTo( OutputStream out )
                  throws IOException {
                  final int nc = numChunks();
          
                  // 遍歷文件塊,一次寫入到輸出流中
                  for ( int i=0; i<nc; i++ ){
                      out.write( getChunk( i ) );
                  }
                  return _length;
              }
          
              // 獲取特定的文件塊
              byte[] getChunk( int i ){
                  if ( _fs == null )
                      throw new RuntimeException( "no gridfs!" );
                  
                  // 調(diào)用 GridFS 的 _chunkCollection 的 findOne 方法
                  // _chunkCollection 中存放了文件數(shù)據(jù)
                  // 查詢時指定了參數(shù) files_id (文件的唯一標(biāo)識) 和 n (序號)
                  DBObject chunk = _fs._chunkCollection.findOne( BasicDBObjectBuilder.start( "files_id" , _id ).add( "n" , i ).get() );
                  if ( chunk == null )
                      throw new MongoException( "can't find a chunk!  file id: " + _id + " chunk: " + i );
          
                  // 獲取文件塊數(shù)據(jù)
                  return (byte[])chunk.get( "data" );
              }
          


            【獲取輸入流】

            另一種讀取數(shù)據(jù)的方式是直接獲取輸入流。

              // 獲取輸入流,用于讀取數(shù)據(jù)
              public InputStream getInputStream(){
                  return new MyInputStream();
              }
          

              GridFSFile.MyInputStream 的 read 方法實現(xiàn)如下:
                  // 讀取數(shù)據(jù)
                  // b 存放數(shù)據(jù)的字節(jié)數(shù)組
                  // off 偏移量
                  // len 長度
                  public int read(byte[] b, int off, int len){
                      // 偏移量超過文件大小
                      if ( _data == null || _offset >= _data.length ){
                          // 已經(jīng)讀完
                          if ( _nextChunk >= _numChunks )
                              return -1;
                          
                          // 讀取一塊數(shù)據(jù),以備使用
                          _data = getChunk( _nextChunk );
                          _offset = 0;
                          _nextChunk++;
                      }
          
                      // r:將要讀取的數(shù)據(jù)的長度
                      int r = Math.min( len , _data.length - _offset );
          
                      // 將 _data 中指定偏移量和長度的數(shù)據(jù)復(fù)制到 b 中
                      System.arraycopy( _data , _offset , b , off , r );
          
                      // 增加偏移量
                      // 在 MyInputStream 內(nèi)部記錄當(dāng)前的數(shù)據(jù)塊讀取到哪里了
                      // 下次再從這里開始讀取
                      _offset += r;
          
                      // 返回讀取的長度
                      return r;
                  }
          


            【刪除操作】

            GridFSDBFile 還提供從 GridFS 中刪除文件的方法,實際上相當(dāng)于調(diào)用  GridFS 的 remove 方法。
              // 從 GridFS 的 _filesCollection 和 _chunkCollection 中刪除文件
              // 與 GridFS.remove 方法的實現(xiàn)相似, 實際上相當(dāng)于調(diào)用  _fs.remove(_id)
              void remove(){ 
                  _fs._filesCollection.remove( new BasicDBObject( "_id" , _id ) );
                  _fs._chunkCollection.remove( new BasicDBObject( "files_id" , _id ) );
              }
          

          GridFSInputFile 準(zhǔn)備寫入數(shù)據(jù)庫的文件

            GridFSInputFile 可以獲得輸出流,從而寫入需要保存的數(shù)據(jù),寫入完畢后通過 close 方法提交修改。
              // 獲取輸出流
              public OutputStream getOutputStream() {
                  if ( _outputStream == null ) {
                      _outputStream = new MyOutputStream();
                  }
                  return _outputStream;
              }
          


            GridFSInputFile.MyOutputStream 的 write 方法的實現(xiàn)如下:
                  public void write( byte[] b , int off , int len ) throws IOException {
                      int offset = off;
                      int length = len;
                      int toCopy = 0;
                      while ( length > 0 ) {
                          // 計算每次需要寫入的長度
                          toCopy = length;
                          if ( toCopy > _chunkSize - _currentBufferPosition ) {
                              toCopy = (int) _chunkSize - _currentBufferPosition;
                          }
          
                          // 復(fù)制數(shù)據(jù)
                          System.arraycopy( b, offset, _buffer, _currentBufferPosition, toCopy );
          
                          // 修改偏移量
                          _currentBufferPosition += toCopy;
                          offset += toCopy;
                          length -= toCopy;
          
                          // 已經(jīng)到達文件塊的結(jié)尾,寫入數(shù)據(jù)庫
                          if ( _currentBufferPosition == _chunkSize ) {
                              _dumpBuffer( false );
                          }
                      }
                  }
          
              // 將緩沖區(qū)中的數(shù)據(jù)寫入數(shù)據(jù)庫中
              // writePartial 為 true 表示不寫入整塊的數(shù)據(jù),這通常用于寫入文件數(shù)據(jù)的結(jié)尾部分。
              private void _dumpBuffer( boolean writePartial ) {
                  if ( ( _currentBufferPosition < _chunkSize ) && !writePartial ) {
                      // 文件塊不完整,返回
                      return;
                  }
                  if (_currentBufferPosition == 0) {
                      // 塊為空,返回
                      return;
                  }
          
                  // 復(fù)制數(shù)據(jù)
                  byte[] writeBuffer = _buffer;
                  if ( _currentBufferPosition != _chunkSize ) {
                      writeBuffer = new byte[_currentBufferPosition];
                      System.arraycopy( _buffer, 0, writeBuffer, 0, _currentBufferPosition );
                  }
          
                  // 保存文件數(shù)據(jù)到數(shù)據(jù)庫
                  DBObject chunk = BasicDBObjectBuilder.start()
                          .add( "files_id", _id )
                          .add( "n", _currentChunkNumber )
                          .add( "data", writeBuffer ).get();
                  _fs._chunkCollection.save( chunk );
          
                  // 改變偏移量等收尾工作
                  _currentChunkNumber++;
                  _totalBytes += writeBuffer.length;
                  _messageDigester.update( writeBuffer );
                  _currentBufferPosition = 0;
              }
          

            需要特別注意的是以下語句:
                  // 保存文件數(shù)據(jù)到數(shù)據(jù)庫
                  DBObject chunk = BasicDBObjectBuilder.start()
                          .add( "files_id", _id )
                          .add( "n", _currentChunkNumber )
                          .add( "data", writeBuffer ).get();
                  _fs._chunkCollection.save( chunk );
          

            借助 DBCollection.save 保存了數(shù)據(jù)。構(gòu)造的 DBObject 包含三個屬性:files_id (文件標(biāo)識)、n(文件塊序號)和 data(文件數(shù)據(jù))




          只有注冊用戶登錄后才能發(fā)表評論。


          網(wǎng)站導(dǎo)航:
           
          主站蜘蛛池模板: 中牟县| 交城县| 南和县| 如东县| 仪征市| 广宁县| 海城市| 连州市| 江口县| 波密县| 水城县| 丁青县| 张家界市| 称多县| 汉源县| 宜宾市| 通山县| 广州市| 招远市| 乡宁县| 西宁市| 邹平县| 汪清县| 简阳市| 建德市| 花莲县| 百色市| 扎赉特旗| 和平区| 宁津县| 视频| 宾阳县| 饶阳县| 肇源县| 旬阳县| 旅游| 尼勒克县| 务川| 图们市| 尤溪县| 虞城县|