linux下的RandomAccessFile類

來源:互聯網
上載者:User

linux下的RandomAccessFile類

備忘:以下寫得基本上是胡說八道,(但是不想刪除)請閱讀此頁面的朋友換個頁面或者換個部落格瀏覽,謝謝-----飛羽飛之豬

當遇到以下情況
1 當讀寫大於記憶體大小的檔案
2 當不想載入整個檔案而需要讀寫檔案某部分

Java的RandomAccessFile可能非常實用和方便
此類的執行個體支援對隨機訪問檔案的讀取和寫入。隨機訪問檔案的行為類似儲存在檔案系統中的一個大型 byte 數組。存在指向該隱含數組的游標或索引,稱為檔案指標;輸入操作從檔案指標開始讀取位元組,並隨著對位元組的讀取而前移此檔案指標。如果隨機訪問檔案以讀取/寫入模式建立,則輸出操作也可用;輸出操作從檔案指標開始寫入位元組,並隨著對位元組的寫入而前移此檔案指標。寫入隱含數組的當前末尾之後的輸出操作導致該數組擴充。該檔案指標可以通過 getFilePointer 方法讀取,並通過 seek 方法設定。

如果在linux下面要實現這樣的功能,可以使用mmap(系統調用)

下面首先介紹下mmap的使用,並寫出一個簡單的用mmap實現的RandomAccessFile的C++類,以滿足用C++解決一開始提到的兩種情況的需要。

mmap介紹
mmap例子
RandomAccessFile的C++實現

#######################################################################################
mmap介紹
mmap的定義:
void *mmap(void *addr, size_t len, int prot, int flags, int fd, off_t offset);

函數參數解析:
參數fd為即將映射到進程空間的檔案描述字,一般由open()返回.

len是映射到調用進程地址空間的位元組數,它從被對應檔開頭offset個位元組開始算起。

prot參數指定共用記憶體的存取權限。可取如下幾個值的或:PROT_READ(可讀),PROT_WRITE(可寫),PROT_EXEC(可執行),PROT_NONE(不可訪問)。

 flags由以下幾個常值指定:MAP_SHARED, MAP_PRIVATE, MAP_FIXED。其中,MAP_SHARED,MAP_PRIVATE必選其一,而MAP_FIXED則不推薦使用。

 offset參數一般設為0,表示從檔案頭開始映射。

參數addr指定檔案應被映射到進程空間的起始地址,一般被指定一個null 指標,此時選擇起始地址的任務留給核心來完成。函數的傳回值為最後檔案對應到進程空間的地址,進程可直接操作起始地址為該值的有效地址。

########################################################################################

mmap例子

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/mman.h>

int main()
{

//mmap第五個參數fd就是調用open()獲得的,如果為-1則開啟檔案失敗
 int fd;
 if ( (fd = open("./file", O_RDWR|O_CREAT, S_IRWXU)) < 0){
  printf("open file wrong!");
  return 1;
 }
 
 //mmap第二個參數len就是調用fstat()獲得的,正常情況下不應該返回-1
 struct stat file_stat;
 if ( fstat( fd, &file_stat) < 0 )
 {
  printf(" fstat wrong");
  return 1;
 }

//mmap第一個參數一般為NULL,詳情見上面的mmap參數說明
//mmap最六個參數為檔案起始映射處,一般為0表示檔案開始
 void *start_fp;
 if( ( start_fp = mmap(NULL, file_stat.st_size, PROT_READ, MAP_SHARED, fd, 0 )) == MAP_FAILED)
 {
  printf("mmap wrong");
  return 1;
 }

 //
  snprintf( (char *)start_fp, 4, "test");
  msync( start_fp, file_stat.st_size, MS_ASYNC);

 //munmap類似與Java的RandomAccessFile的close()函數,關閉檔案對應功能。參數為映射返回的void*指標和對應檔長度,可以把它當成一般IO功能的關閉功能。
  if ( munmap( start_fp, file_stat.st_size ) < 0 )
  {
  printf("munmap wrong");
  return 1;
  }
}

記憶體映射的一般步驟:

用open系統調用開啟檔案, 並返回描述符fd.
用mmap建立記憶體映射, 並返回映射首地址指標start.
對映射(檔案)進行各種操作, 顯示(printf), 修改(sprintf).
用munmap(void *start, size_t lenght)關閉記憶體映射.
用close系統調用關閉檔案fd.

############################################################################
RandomAccessFile的C++實現

下面是用mmap的一個RandomAccessFile的C++類實現,封裝一些看上去"不怎麼友好"的代碼.
這個類只實現了讀取char的功能,沒有實作類別似Java的RandomAccessFile可以讀取任意類型的資料的功能。
在centos5,g++ 4.1.2 環境下測試可用

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/mman.h>

//081125 snail
class RandomAccessFile
{
public:
 RandomAccessFile(const char* filePath);
 ~RandomAccessFile();
 bool isOpen()
 {
  return open_ok;
 }

 long length()
 {
  long size = 0;
  if (open_ok)
  {
   size = m_file_stat.st_size;
  }
  return size;
 }

 void seek(long pos)
 {
  if (pos > m_file_stat.st_size)
  {
   pos = m_file_stat.st_size;
  }
  m_offset = pos;
 }

 char readChar()
 {
  return m_file[m_offset];
 }

 const char* getError()
 {
  return m_error;
 }

private:
 bool open_ok;//RamomAccessFile is prepared ok
 char* m_file;//if is prepared ok,m_file stands for handle of RandomAccessFile
 char* m_error;//if is not prepared ok,m_error stands for error message
 struct stat m_file_stat;//stands for info of file which to be RandomAccess
 long m_offset;//offset to start of file
};

RandomAccessFile::RandomAccessFile(const char* filePath) :
 m_offset(0), open_ok(true)
{
 int fd;
 if ((fd = open("./file", O_RDWR | O_CREAT, S_IRWXU)) < 0)
 {
  m_error = "open file wrong!";
  open_ok = false;;
 }

 if (open_ok)
 {
  if (fstat(fd, &m_file_stat) < 0)
  {
   m_error = "fstat wrong";
   open_ok = false;
  }
 }

 if (open_ok)
 {
  if ((m_file = (char*) mmap(NULL, m_file_stat.st_size, PROT_READ,
    MAP_SHARED, fd, m_offset)) == MAP_FAILED)
  {
   m_error = "mmap wrong";
   open_ok = false;
  }
 }
}

RandomAccessFile::~RandomAccessFile()
{
 if (open_ok)
 {
  if (munmap(m_file, m_file_stat.st_size) < 0)
  {
   printf("munmap wrong");
  }
 }
}

int main()
{
 RandomAccessFile* raf = new RandomAccessFile("./file");
 if (raf->isOpen())
 {
  //printf("randomaccess file is prepared!/n");
  printf("raf length()-->%d/n", raf->length());
  raf->seek(0);
  printf("%c/n", raf->readChar());
 }
 else
 {
  printf(raf->getError());
 }

 delete raf;
}

#############################################################################
參考:
http://blog.csdn.net/dai_weitao/archive/2007/07/25/1707559.aspx
http://blog.csdn.net/eroswang/archive/2007/11/30/1908842.aspx
http://blog.csai.cn/user1/16820/archives/2008/25456.html

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.