超过6G的大文件是如何读取的,附源代码。含有网上很少有论述的信息

简介: 读取大文件有如下两种方法,一是用fopen打开文件,fgetline循环读取,fclose关闭文件;二是用open打开函数,用lseek获取文件大小,用mmap大文件内存映射,用munmap关闭内存映射,用close关闭文件句柄。方式一教慢,就不再详细描述。主要描述方式二。

因为工作关系,需要从大文件中筛选数据,进行比对。文件大小一般都在6g左右。



读取大文件有如下两种方法,一是用fopen打开文件,fgetline循环读取,fclose关闭文件;二是用open打开函数,用lseek获取文件大小,用mmap大文件内存映射,用munmap关闭内存映射,用close关闭文件句柄。方式一教慢,就不再详细描述。主要描述方式二。


方式二,网上介绍也有很多,但是鲜有介绍当大于4G后,读取方法。用long型读取文件大小时,最多是4294967295个字节,也就是4G。解决方法是用long long来读取文件的大小。



样例代码如下:


#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/time.h> 
#include <sys/mman.h> 
#include <sys/types.h>
#include <errno.h>
#include <unistd.h>
using namespace std;
#include "dlist.h"
//呼叫流程数组
typedef struct s_callflow
{
   char identifier[100];
   char billingid[200];
   bool response;
   s_callflow()
   {
      strcpy(identifier,"");
      strcpy(billingid,"");
      response=false;
   }
} callflow;
callflow *call_instance(char *identifier,char *billingid ,bool response) 
{ 
    callflow *call_ptr; 
    call_ptr = (callflow *)malloc(sizeof(callflow)); 
    if( call_ptr==NULL ) 
        return NULL; 
    strcpy(call_ptr->identifier,identifier);
    strcpy(call_ptr->billingid,billingid);
    call_ptr->response = response;
    return call_ptr; 
} 
void updatecall(DList *list,char *identifier)
{
    if(list==NULL) return;
    DListElmt *new_element;
    new_element = list->tail;   
    while(new_element!=NULL)
    {
        callflow * flow = (callflow *)new_element->data;
        if(flow!=NULL)
        {
            if(strcmp(flow->identifier,identifier)==0 && flow->response==false)
            {
                flow->response=true;
                break;
            }
        }
        if( new_element == list->head )
        {
            break;
        }
        new_element = new_element->prev;
    }
}
/*destroy */ 
void destroy(void *data) 
{ 
    free(data); 
    return; 
} 
void output(DList *list,bool calling)
{
    if(list==NULL) return;
    DListElmt *new_element;
    new_element=list->head;
    int count = list->size;
    int response=0;
    FILE *out;
    if(calling==1)
    {
        out=fopen("calling.txt","w");
    }
    else
    {
        out=fopen("called.txt","w");
    }
    char buffer[255];
    while(new_element!=NULL)
    {
         callflow * flow = (callflow *)new_element->data;
         if(flow!=NULL)
         {
            if(flow->response==true)
            {
               response++;
            }
            else
            {
                 sprintf(buffer,"billingid=%s identifier=%s\n",flow->billingid,flow->identifier);
                 fwrite(buffer,strlen(buffer),1,out);
            }
         }
         new_element=new_element->next;
    }
     sprintf(buffer,"count=%d response=%d\n",count,response);
     fwrite(buffer,strlen(buffer),1,out);
     fclose(out);
}
//
int main(int argc,char * argv[])
{
   //size_t lsize=0;
   long long lsize=0;
   const char *localpc="16592304";
   DList calling_node;
   DList called_node;
   dlist_init(&calling_node, destroy);
   dlist_init(&called_node, destroy); 
   char opc[3][200];
   char dpc[3][200];
   char identifier[2][100];
   char billingID[2][200];
   //FILE * fp=NULL;
   //fp = fopen(argv[1],"r");
   char *pBuffer=NULL; 
   char *pStart=NULL,*pEnd=NULL; 
   int fd = open(argv[1],O_RDONLY);
   //size_t nFileSize=0; 
   //size_t nOffset=0; 
   //size_t nLineAmount=0; 
   //struct stat fileState; 
   //fstat(fd,&fileState); 
   //nFileSize=fileState.st_size;
   long long nFileSize=0;
   long long nOffset;
   long long nLineAmount;
   nFileSize =(long long)lseek(fd,0,SEEK_END);
   //nFileSize = (unsigned long)fileState.st_size;
   pBuffer=(char *)mmap(NULL,nFileSize,PROT_READ,MAP_SHARED,fd,0); 
   pEnd=pStart=pBuffer;
   char line[2048];
   int flag;
   flag=-1;
   int in=-1;
   printf("nFileSize=%lld\n",nFileSize);
   int load = 0;
   int preload = 0;
   while(lsize<nFileSize-4)
   {
       lsize++;
       load = (int) (((float)lsize / (float)nFileSize) * 100);
       if(preload!=load)
       {
          printf("%3d \n",load);
          preload = load;
          sleep(1);
          printf("\b");
       }
       char a = *pEnd;
       if(a==13)
       {
          char b = *(++pEnd);
          if(b==10)
          {
               int len = pEnd-pStart;
               if(len<1) break;
               if(len>2047) break;
               strncpy(line,pStart,len);
               pStart=pEnd+1;
               if(strstr(line," OPC")!=NULL)
               {
                   sscanf(line,"%s%s%s",opc[0],opc[1],opc[2]);
               }
               else if(strstr(line," DPC")!=NULL)
               {
                   sscanf(line,"%s%s%s",dpc[0],dpc[1],dpc[2]);
               }
               else if(strstr(line,"queryWithPerm")!=NULL)
               {
                  flag=0; //
               }
               else if(strstr(line,"response")!=NULL)
               {
                  flag=1; //
               }
               else if(strstr(line,"identifier")!=NULL)
               {
                   sscanf(line,"%s%s",identifier[0],identifier[1]);
                   //
                   if(strcmp(opc[1],localpc)==0)
                   {
                       //
                       if(flag==1) //response
                       {
                            //找主叫流程
                            updatecall(&calling_node,identifier[1]);
                            //找被叫流程
                            updatecall(&called_node,identifier[1]);
                            flag=-1;
                       }
                   }
               }
               else if(strstr(line,"originationRequest")!=NULL)
               {
                   //主叫流程
                   if(strstr(line,"originationRequestRes")==NULL)
                   {
                       in = 1;
                   }
               }
               else if(strstr(line,"billingID")!=NULL)
               {
                  sscanf(line,"%s%s",billingID[0],billingID[1]);
                  if(in==1)
                  {
                     callflow * calling = call_instance(identifier[1],billingID[1] ,false);
                     dlist_ins_next(&calling_node,calling_node.tail,(void *)calling);
                     in = -1;
                  }
               }
               else if(strstr(line,"initial-Termination (38)")!=NULL)
               {
                   //被叫流程
                   callflow * called = call_instance(identifier[1],billingID[1] ,false);
                   dlist_ins_next(&called_node,called_node.tail,(void *)called);
               }
          }
       }
       else
       {
          pEnd++;
       }
   }
   output(&calling_node,true);
   output(&called_node,false);
   dlist_destroy(&calling_node);
   dlist_destroy(&called_node);
   munmap(pBuffer,nFileSize);
   //fclose(fp);
   close(fd);
}
DList.h
/*
 * filename: dlist.h
 * author: zhm
 * date: 2012-12-08
 */
#ifndef _DLIST_H
#define _DLIST_H
#include <stdlib.h>
/* define a structure for the list element*/
typedef struct DListElmt_
{
    void *data;
    struct DListElmt_ *prev;
    struct DListElmt_ *next;
}DListElmt;
/* define a structure for the double linked list */
typedef struct DList_
{
    int size;
    void (*destroy)(void *data);
    DListElmt *head;
    DListElmt *tail;
}DList;
/* define public interface */
void dlist_init(DList *list, void (*destroy)(void *data));
void dlist_destroy(DList *list);
int dlist_ins_prev(DList *list, DListElmt *element, const void *data);
int dlist_ins_next(DList *list, DListElmt *element, const void *data);
int dlist_ins_next(DList *list, DListElmt *element, const void *data);
int dlist_remove(DList *list, DListElmt *element, void **data);
#define dlist_size(list) ((list)->size) //get the size of the list.
#define dlist_head(list) ((list)->head) //get the head element
#define dlist_tail(list) ((list)->tail) //get the tail element
#define dlist_is_head(element) ((element)->prev == NULL ? 1 : 0) //whether the element is head or not
#define dlist_is_tail(element) ((element)->next == NULL ? 1 : 0) //whether the element is tail or not
#define dlist_data(element) ((element)->data) //get the data of the element
#define dlist_prev(element) ((element)->prev) //get the prev element
#define dlist_next(element) ((element)->next) //get the next element
#endif


相关文章
|
存储 Linux 数据安全/隐私保护
【Linux】文件服务WebDAV(Web-based Distributed Authoring and Versioning)
【Linux】文件服务WebDAV(Web-based Distributed Authoring and Versioning)
764 0
|
安全 Linux C++
Boost库之asio io_service以及run、run_one、poll、poll_one区别
一、io_service的作用 io_servie 实现了一个任务队列,这里的任务就是void(void)的函数。Io_servie最常用的两个接口是post和run,post向任务队列中投递任务,run是执行队列中的任务,直到全部执行完毕,并且run可以被N个线程调用。
2588 0
|
存储 人工智能 机器人
工作3年,还分不清文件大小单位关系的?就看这篇吧!
工作3年,还分不清文件大小单位关系的?就看这篇吧!
818 2
|
存储 缓存 监控
Linux缓存管理:如何安全地清理系统缓存
在Linux系统中,内存管理至关重要。本文详细介绍了如何安全地清理系统缓存,特别是通过使用`/proc/sys/vm/drop_caches`接口。内容包括清理缓存的原因、步骤、注意事项和最佳实践,帮助你在必要时优化系统性能。
1408 78
|
Android开发
Android Stadio Build 窗口字符串乱码问题
在使用Android Studio过程中,如果遇到Build窗口字符串乱码问题,可以通过编辑`studio.vmoptions`文件添加`-Dfile.encoding=UTF-8`配置并重启Android Studio来解决。
839 2
Android Stadio Build 窗口字符串乱码问题
|
17天前
|
Shell API
最新,通过GACCode配置Codex桌面客户端使用方案!
本指南详解Codex桌面端配置流程:①安装客户端;②获取gaccode.com的API Key(无订阅可邮件申请);③创建并编辑~/.codex/config.toml文件,配置gac模型提供方与gpt-5.4模型;④导出CODEX_API_KEY环境变量;⑤重启应用即可开始智能对话。
最新,通过GACCode配置Codex桌面客户端使用方案!
|
Linux API 开发工具
Juce-强大的开源类库
介绍 Juce是一个完全围绕C++语言的类库,用来开发跨平台的应用程序。 完整的用doxgen生成的html形式的API手册可以在这里下到。或者可以从下载页面下载预编译的windows帮助文件。   想获取更多的帮助或信息,请访问JUCE的网站。
2465 0
|
Linux 安全 关系型数据库
linux设置ulimit值永久生效
小知识的积累,转自 http://hi.baidu.com/moonelf9989/blog/item/1deadf12780fa0c5c2fd789d.html linux 默认打开文件数linux 默认打开文件数为1024个,通过ulimit -a 可以查看open files 修改这个限制可以使用ulimt -SHn 65536 永久生效需要进行下面设置: 1.
12849 0
|
SQL 存储 关系型数据库
mysql集群搭建部署
应用场景 数据存储在mysql中,单节点存储如果数据量十分大,数据就很可能存不下。因此我们需要搭建部署mysql的集群模式,增加数据的存储量,而且提到数据库访问的并发。
2951 0