zoukankan      html  css  js  c++  java
  • 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
    ");
    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
    ", 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.
    ");
    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
    ", strerror(errno));  // 使用異常檢查是個好習慣, 他可以幫助程序員迅速定位出錯的地方!
    39     fstat(fd, &stat);
    40     mmapcopy(fd, stat.st_size);
    41     //while(1);
    42     close(fd);
    43     exit(0);
    44 }
  • 相关阅读:
    (十五)、常见的几种RuntimeException
    (十四)、泛型中extends和super的区别
    (十三)、Java泛型
    (十二)、构造方法、静态属性和静态方法的使用要点
    (十一)、final,finally,finalize的区别
    (十)、java内部类与内部类的闭包和回调
    (九)、线程sleep和wait的区别
    (八)、java中==和equals和hashCode的区别
    sketch中做outline icon的制作技巧
    sketch Measure的安装及使用
  • 原文地址:https://www.cnblogs.com/fnlingnzb-learner/p/7040597.html
Copyright © 2011-2022 走看看