您的位置:首页 > 编程语言 > C语言/C++

C/C++从文件开头按行读取内容==并无需新建文件,获取前部分内容

2016-03-02 10:23 627 查看
需求分析:

按行获取文件内容,达到行数要求或者其他要求(时间)后,停止读取,并将剩余内容删除。

文件格式:(按时间排序)

=========红色为所需内容,剩余内容删除=============

2016030115031110F9FDC6521100020000000000000000

2016030115021110F9FDC6521100020000000000000000

2016030115011110F9FDC6521100020000000000000000

2016030115001110F9FDC6521100020000000000000000

2016030115001110F9FDC6521100020000000000000000

2016030115001110F9FDC6521100020000000000000000

2016030115001110F9FDC6521100020000000000000000

2016030115001110F9FDC6521100020000000000000000

2016030115001110F9FDC6521100020000000000000000

2016030115001110F9FDC6521100020000000000000000

2016030115001110F9FDC6521100020000000000000000

2016030114001110F9FDC6521100020000000000000000

2016030114001110F9FDC6521100020000000000000000

2016030114201110F9FDC6521100020000000000000000

实现:

方法1:按行循环读取文件内容,并将符合要求的内容写入缓存,新建文件,将缓存写入新建文件中,删除旧文件,新文件重命名

优点:使用广泛

缺点:效率低,大数据时不适应

方法2:因为文件内容按规律(时间)有序排序,获取符合要求内容所在位置tellg(),使用chFileSize()函数修改文件大小,将不需要的内容删掉。

优点:效率较高

缺点:使用场景有局限性,待完善

方法1代码:

int nPushBack = 0;//符合要求的记录条数
vector<string>vecFileList;//缓存
int maxMinute = nMaxMinute;//需要查询的最大时间
int maxRec = nMaxRecord;//需要查询的最大记录条数

string strFileName = AFC_DATA_PATH + "trandata.filelist";
string strFileNamenew = AFC_DATA_PATH + "trandata.filelist.new";
int nLen = sizeofFile(strFileName.c_str());//文件大小
if (nLen <=0)
return;
fstream fs_tranfilelst(strFileName.c_str());
if (!fs_tranfilelst.good())//文件打开失败
return;
CAfcStringTools afcStringTools;
char bufLine[MAX_CHAR_IN_LINE], bufTemp[MAX_CHAR_IN_LINE];
//按行获取文件内容
while (fs_tranfilelst.getline(bufLine, MAX_CHAR_IN_LINE))  {
if (afcStringTools.AfcConfTrimLine(bufLine, bufTemp, MAX_CHAR_IN_LINE, AfcConfCharNOChangeMode) == 0)//剔除空行
continue; // if is blank line, continue
//time1 提取出YYYYMMDDHHMM201612201530
char chTimeBuf[16]; memset(chTimeBuf, 0, sizeof(chTimeBuf));
char* pTemp = bufTemp;
memcpy(chTimeBuf, pTemp, 12);
//time2 本地时间转换为妙数 - maxMinute*60 = 再转换为本地时间样式
char chTmpBuf[128]; memset(chTmpBuf, 0, sizeof(chTmpBuf));
time_t t_MaxTime;
t_MaxTime = time(NULL);//获取当前时间的秒数
t_MaxTime = t_MaxTime - maxMinute * 60;
tm *tm_MaxTime = localtime(&t_MaxTime);//将妙数转换为标准时间格式
strftime(chTmpBuf, 64, "%Y%m%d%H%M", tm_MaxTime);//标准时间格式20151220123025
//差异:
//比较time1 和 time2
//时间要求满足并且记录条数未到
if ((memcmp(chTmpBuf, chTimeBuf, 12) <= 0) && (nPushBack <= maxRec)){
string strTmp = bufTemp;
vecFileList.push_back(strTmp);
continue;
}
fs_tranfilelst.close();
break;
}
fileExist(strFileName.c_str());//新建文件
fstream fs_tranfilelstnew(strFileName.c_str());
do{
if (vecFileList.size() <= 0)
break;

vector<string>::iterator iter = vecFileList.end() - 1;
if (iter == vecFileList.end())
break;

strName = *iter ;
fs_tranfilelstnew.write(strName.c_str(),strName.length() );
vecFileList.erase(iter );
} while (true);
fs_tranfilelstnew.close();


方法2代码:

int nPushBack = 0;//符合要求的记录条数
long longFileSize = 0;//文件大小
int maxMinute = nMaxMinute;//需要查询的最大时间
int maxRec = nMaxRecord;//需要查询的最大记录条数

string strFileName = AFC_DATA_PATH + "trandata.filelist";
int nLen = sizeofFile(strFileName.c_str());//文件大小
if (nLen <=0)
return;
fstream fs_tranfilelst(strFileName.c_str());
if (!fs_tranfilelst.good())//文件打开失败
return;
CAfcStringTools afcStringTools;
char bufLine[MAX_CHAR_IN_LINE], bufTemp[MAX_CHAR_IN_LINE];
//按行获取文件内容
while (fs_tranfilelst.getline(bufLine, MAX_CHAR_IN_LINE))  {
if (afcStringTools.AfcConfTrimLine(bufLine, bufTemp, MAX_CHAR_IN_LINE, AfcConfCharNOChangeMode) == 0)//剔除空行
continue; // if is blank line, continue
//time1 提取出YYYYMMDDHHMM201612201530
char chTimeBuf[16]; memset(chTimeBuf, 0, sizeof(chTimeBuf));
char* pTemp = bufTemp;
memcpy(chTimeBuf, pTemp, 12);
//time2 本地时间转换为妙数 - maxMinute*60 = 再转换为本地时间样式
char chTmpBuf[128]; memset(chTmpBuf, 0, sizeof(chTmpBuf));
time_t t_MaxTime;
t_MaxTime = time(NULL);//获取当前时间的秒数
t_MaxTime = t_MaxTime - maxMinute * 60;
tm *tm_MaxTime = localtime(&t_MaxTime);//将妙数转换为标准时间格式
strftime(chTmpBuf, 64, "%Y%m%d%H%M", tm_MaxTime);//标准时间格式20151220123020
//差异:
//比较time1 和 time2
//时间要求满足并且记录条数未到
if ((memcmp(chTmpBuf, chTimeBuf, 12) <= 0) && (nPushBack <= maxRec)){
nPushBack++;
longFileSize = (long)fs_tranfilelst.tellg();//获取到此位置文件数据大小
printf("nPushBack =%d ,need save the filelist = %s \n", nPushBack, bufTemp);
continue;
}
fs_tranfilelst.close();
break;
}

//读写模式
int fd = open(strFileName.c_str(), O_RDWR);
if (fd <= 0)
return;
//更改文件大小
chFileSize(fd, longFileSize);
close(fd);

方法2使用到的函数:(基于POCO库)
#include "Poco/File.h"
#include "Poco/FileStream.h"
#include "Poco/Exception.h"
#include "Poco/BinaryReader.h"
#include "Poco/BinaryWriter.h"
#include "Poco/DirectoryIterator.h"
/**
* 改变文件大小
*   如果指定的长度小于文件长度, 则文件被截短;
*   如果指定的长度大于文件长度, 则在文件后面补0;
*   如果指定文件不存在, 则创建指定大小的文件(内容全为0)
* pFilename - 文件名称(完整路径)
* size - 需要改变的文件新的长度
* 返回值: 成功返回0,否则返回-1
*/
int chFileSize( const char *pFileName, long size )
{
int nFd;
nFd = open( pFileName, O_RDWR | O_CREAT, 0666 );
if ( nFd >= 0 ) {
int nReturn = chFileSize( nFd, size );
close( nFd );
return nReturn;
} else
return -1;
}
/**
* 改变文件大小
*   如果指定的长度小于文件长度, 则文件被截短;
*   如果指定的长度大于文件长度, 则在文件后面补0;
* fd - 使用open打开的文件句柄
* size - 需要改变的文件新的长度
* 返回值: 成功返回0,否则返回-1
*/
int chFileSize( const int fd, long size )
{
#ifdef POCO_OS_FAMILY_WINDOWS
return chsize( fd, size );
#else
return ftruncate( fd, size );
#endif
}

bool fileExists(const char* pFileName, bool bAutoCreate)
{
try {
Poco::File file( pFileName );
if ( !file.exists() && bAutoCreate ) {
Poco::Path pathTmp( pFileName );
if ( pathTmp.isDirectory() )
file.createDirectories();
else if ( pathTmp.isFile() ) {
File( basedir( string( pFileName ) ) ).createDirectories();
chFileSize( pFileName, 0 );
}
}
return ( file.exists() && file.canRead() );
} catch ( Poco::Exception& ex ) {
logprintf("Warn: fileExists( %s ) %s\n", pFileName, ex.message().c_str() );
} catch ( ... ) {
logprintf("Warn: fileExists( %s )\n", pFileName );
}
return false;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: