linux下C++修改文件內容


 C fwrite在任意位置寫入文件,並可修改文件內容 

想實現類似迅雷那樣下載時可以從文件半中間寫入的功能

 1 #include<stdio.h>
 2     int main()
 3     {
 4         FILE *fp;
 5         fp=fopen("overwrite.bin","rb+"); //使用rb+模式,可以往半中間插入數據,而且是覆蓋插入,若使用"ab+"每次都插入到最后面,調用fseek也沒用
 6         if(NULL != fp)
 7         {
 8             if(-1 == (fseek(fp,9, SEEK_SET)))
 9                     printf("seek error\n");
10             fwrite("abcde",1, 5, fp);
11             fclose(fp);
12         }
13         else
14         {
15             printf("fopen error");
16             return 0;
17         }
18         return 0;
19     }

 

剛開始用ab+模式打開, 每次都寫入到最后面. 用rb+就可以定位到任意位置寫入了.
在linux下已測試,因為用"rb+"打開要保證文件已存在. 使用命令  #touch overwrite.bin  新建文件
將上述代碼 編譯運行.
用vi 打開overwrite.bin 看到內容為第9字節開始abcde
然后再將fseek(fp,9,SEEK_SET)中的9改成11:fseek(fp,11,SEEK_SET), 編譯運行. 再用vi打開overwrite.bin可以看到在第9字節開始的內容為"ababcde".
之前寫入的cde被覆蓋了

 

mmap---關於讀寫文件

mmap函數是unix/Linux下的系統調用,來看《Unix Netword programming》卷二12.2節有詳細介紹。

mmap系統調用並不是完全為了用於共享內存而設計的。它本身提供了不同於一般對普通文件的訪問方式,進程可以像讀寫內存一樣對普通文件的操作。而Posix或系統V的共享內存IPC則純粹用於共享目的,當然mmap()實現共享內存也是其主要應用之一。
          mmap系統調用使得進程之間通過映射同一個普通文件實現共享內存。普通文件被映射到進程地址空間后,進程可以像訪問普通內存一樣對文件進行訪問,不必再調用read(),write()等操作。mmap並不分配空間, 只是將文件映射到調用進程的地址空間里, 然后你就可以用memcpy等操作寫文件, 而不用write()了.寫完后用msync()同步一下, 你所寫的內容就保存到文件里了. 不過這種方式沒辦法增加文件的長度, 因為要映射的長度在調用mmap()的時候就決定了.

簡單說就是把一個文件的內容在內存里面做一個映像,內存比磁盤快些。
基本上它是把一個檔案對應到你的virtual memory 中的一段,並傳回一個指針。

以后對這段 memory 做存取時,其實就是對那個檔做存取。
它就是一種快速 file I/O 的東東,而且使用上和存取 memory 一樣方便,只不過會占掉你的 virutal memory。
#include <sys/types.h>
#include <sys/stat.h> //文件狀態結構
#include <unistd.h>
#include <sys/mman.h> //mmap頭文件

void * mmap(void *start, size_t length, int prot , int flags, int fd, off_t offset);

mmap開啟記憶體對映。 
start指定記憶體位置,通常都是用NULL。offset指定檔案要在那里開始對映,通常都是用0。 

int munmap(void *start, size_t length);

int msync(const void *start, size_t length, int flags); 
如果開啟記憶體對映是希望寫入檔案中,那麽修改過的記憶體會在一段時間內與檔案稍稍有點不同。如果您希望立即將資料寫入檔案中,可使用msync。 

start為記憶體開始位置,length為長度。 

flags則有三個: 
MS_ASYNC : 請Kernel快將資料寫入。 
MS_SYNC : 在msync結束返回前,將資料寫入。 
MS_INVALIDATE : 讓核心自行決定是否寫入,僅在特殊狀況下使用

 

 1 #include <sys/mman.h>
 2 #include <unistd.h>
 3 #include <stdio.h>
 4 #include <fcntl.h>
 5 //#include "csapp.h"
 6 #include <sys/stat.h>
 7 #include <stdlib.h>
 8 #include <string.h>
 9 #include <errno.h>
10 
11 void mmapcopy(int fd, int size)
12 {
13     char *bufp;
14     //void * start_addr = 0;
15     //start_addr = (void *)0x80000;
16     bufp = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
17     if (bufp == (void *)-1)
18     fprintf(stderr, "mmap: %s\n", strerror(errno));
19     
20     memcpy(bufp, "Linuxdd", 7);
21     
22     write(1, bufp, size);
23     munmap(bufp, size);
24     return;
25 }
26 int main(int argc, char **argv)
27 {
28     struct stat stat;
29     if (argc != 2)
30         {
31             printf("error.\n");
32             exit(0);
33         }
34         //int fd = atoi(*argv[1]);
35     //mmap()
36     int fd = open(argv[1], O_RDWR, 0);  // O_RDWR 才能被讀寫。
37     if (fd < 0)
38     fprintf(stderr, "open: %s\n", strerror(errno));  // 使用異常檢查是個好習慣, 他可以幫助程序員迅速定位出錯的地方!
39     fstat(fd, &stat);
40     mmapcopy(fd, stat.st_size);
41     //while(1);
42     close(fd);
43     exit(0);
44 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM