免费注册 查看新帖 |

ChinaUnix.net

  平台 论坛 博客 文库 频道自动化运维 虚拟化 储存备份 C/C++ PHP MySQL 嵌入式 Linux系统
12下一页
最近访问板块 发新帖
查看: 3962 | 回复: 19

[C] 求日志文件最后的行输出 [复制链接]

论坛徽章:
1
数据库技术版块每日发帖之星
日期:2016-07-18 06:20:00
发表于 2013-05-04 00:27 |显示全部楼层
本帖最后由 lyl2002 于 2013-05-04 00:41 编辑

有一个日志文件,有n行,我现在要printf这个日志文件最后m行,而且需要按第1个字段顺序打印,把n>=m或m>n的情况都考虑进去,用纯C如何实现

日志文件内容:
101|101001|101236|0000|
102|101001|101236|0000|
103|101001|101236|0000|
.....
.....
.....
n-2|101001|101236|0000|
n-1|101001|101236|0000|
n|101001|101236|0000|




如果m=3,最后输出结果是
n-2|101001|101236|0000|
n-1|101001|101236|0000|
n|101001|101236|0000|

论坛徽章:
14
巨蟹座
日期:2013-11-19 14:09:4615-16赛季CBA联赛之青岛
日期:2016-07-05 12:36:0515-16赛季CBA联赛之广东
日期:2016-06-29 11:45:542015亚冠之全北现代
日期:2015-07-22 08:09:472015年辞旧岁徽章
日期:2015-03-03 16:54:15巨蟹座
日期:2014-12-29 08:22:29射手座
日期:2014-12-05 08:20:39狮子座
日期:2014-11-05 12:33:52寅虎
日期:2014-08-13 09:01:31巳蛇
日期:2014-06-16 16:29:52技术图书徽章
日期:2014-04-15 08:44:01天蝎座
日期:2014-03-11 13:06:45
发表于 2013-05-04 09:26 |显示全部楼层
就是做个循环数组,有空余时插入到空余处,无空余时替换到最先进入的数据

以下代码在gcc4.72(加编译参数-std=c99)上编译通过,但没测试过,你自己参考一下
  1. #include <stdio.h>

  2. #define LINELEN 50

  3. int main()
  4. {
  5.     FILE *fin = fopen( "lyl2002.txt", "rt" );
  6.     if( !fin )
  7.         return 1;

  8.     const size_t m = 3;
  9.     char rls[m][LINELEN];
  10.     size_t rlsnum = 0;
  11.     size_t rlsptr = 0;
  12.     for( ; fgets(rls[rlsptr],LINELEN*sizeof(char),fin); rlsptr=(rlsptr+1)%m, rlsnum<m?++rlsnum:0 );

  13.     fclose( fin );

  14.     ///

  15.     for( size_t i=rlsptr-rlsnum; i!=rlsptr; ++i )
  16.         printf( "%s", rls[(i+m)%m] );

  17.     return 0;
  18. }
复制代码

论坛徽章:
1
数据库技术版块每日发帖之星
日期:2016-07-18 06:20:00
发表于 2013-05-04 09:51 |显示全部楼层
2楼的确很高深,能不能写的再通俗一点

论坛徽章:
260
射手座
日期:2013-08-23 12:04:38射手座
日期:2013-08-23 16:18:12未羊
日期:2013-08-30 14:33:15水瓶座
日期:2013-09-02 16:44:31摩羯座
日期:2013-09-25 09:33:52双子座
日期:2013-09-26 12:21:10金牛座
日期:2013-10-14 09:08:49申猴
日期:2013-10-16 13:09:43子鼠
日期:2013-10-17 23:23:19射手座
日期:2013-10-18 13:00:27金牛座
日期:2013-10-18 15:47:57午马
日期:2013-10-18 21:43:38
发表于 2013-05-04 10:03 |显示全部楼层
参考 tail  

论坛徽章:
260
射手座
日期:2013-08-23 12:04:38射手座
日期:2013-08-23 16:18:12未羊
日期:2013-08-30 14:33:15水瓶座
日期:2013-09-02 16:44:31摩羯座
日期:2013-09-25 09:33:52双子座
日期:2013-09-26 12:21:10金牛座
日期:2013-10-14 09:08:49申猴
日期:2013-10-16 13:09:43子鼠
日期:2013-10-17 23:23:19射手座
日期:2013-10-18 13:00:27金牛座
日期:2013-10-18 15:47:57午马
日期:2013-10-18 21:43:38
发表于 2013-05-04 10:07 |显示全部楼层
n很大并且远远大于m时最好倒着读

论坛徽章:
1
数据库技术版块每日发帖之星
日期:2016-07-18 06:20:00
发表于 2013-05-04 10:11 |显示全部楼层
本帖最后由 lyl2002 于 2013-05-04 10:12 编辑

一定要倒着读,我这个日志文件很大的,每天都有很大的交易量,有没有倒着读的方法参考啊

论坛徽章:
4
水瓶座
日期:2013-09-06 12:27:30摩羯座
日期:2013-09-28 14:07:46处女座
日期:2013-10-24 14:25:01酉鸡
日期:2014-04-07 11:54:15
发表于 2013-05-04 10:40 |显示全部楼层
本帖最后由 linux_c_py_php 于 2013-05-04 10:44 编辑
lyl2002 发表于 2013-05-04 09:51
2楼的确很高深,能不能写的再通俗一点


循环数组, 一个记录front, 一个记录队列长度, 每3个就长度清零, 最后用front减去队列长度得到rear,然后打印从rear到front的数据,因为是循环队列所以(rear + m) % m保证是数组内下标.


论坛徽章:
0
发表于 2013-05-04 10:49 |显示全部楼层
本帖最后由 hbmhalley 于 2013-05-04 10:55 编辑

倒着读的
  1. #include <stdio.h>

  2. int main (int argc , char *argv[]) {
  3.         FILE *fp ;
  4.         int m ;

  5.         if (argc != 3
  6.                         || (fp = fopen (argv[1] , "r")) == NULL
  7.                         || sscanf (argv[2] , "%d" , &m) != 1
  8.                         || m <= 0) {
  9.                 fputs ("arg error\n" , stderr) ;
  10.                 return 1 ;
  11.         }

  12.         long st ;
  13.         int cnt = m ;
  14.         fseek (fp , 0 , SEEK_END) ;
  15.         for (st = 1 ; ftell (fp) != 0 ; st <<= 1) {
  16.                 if (fseek (fp , -st , SEEK_CUR) != 0) {
  17.                         st = ftell (fp) ;
  18.                         fseek (fp , 0 , SEEK_SET) ;
  19.                 }

  20.                 long i ;
  21.                 for (i = 0 ; i < st ; ++i)
  22.                         cnt -= fgetc (fp) == '\n' ;

  23.                 fseek (fp , -st , SEEK_CUR) ;
  24.                 if (cnt < 0)
  25.                         break ;
  26.         }

  27.         while (cnt < 0)
  28.                 cnt += fgetc (fp) == '\n' ;

  29.         int c ;
  30.         while ((c = fgetc (fp)) != EOF)
  31.                 putchar (c) ;

  32.         return 0 ;
  33. }
复制代码

论坛徽章:
4
水瓶座
日期:2013-09-06 12:27:30摩羯座
日期:2013-09-28 14:07:46处女座
日期:2013-10-24 14:25:01酉鸡
日期:2014-04-07 11:54:15
发表于 2013-05-04 10:54 |显示全部楼层
lyl2002 发表于 2013-05-04 10:11
一定要倒着读,我这个日志文件很大的,每天都有很大的交易量,有没有倒着读的方法参考啊


实现tail的功能, 包括tail -f的功能, 就是从末尾往前找换行的意思, 建议直接看tail源码, 给你摘了一段核心:
  1. tail_lines (const char *pretty_filename, int fd, uintmax_t n_lines,
  2.             uintmax_t *read_pos)
  3. {
  4.   struct stat stats;

  5.   if (fstat (fd, &stats))
  6.     {   
  7.       error (0, errno, _("cannot fstat %s"), quote (pretty_filename));
  8.       return false;
  9.     }   

  10.   if (from_start)
  11.     {   
  12.       int t = start_lines (pretty_filename, fd, n_lines, read_pos);
  13.       if (t)
  14.         return t < 0;
  15.       *read_pos += dump_remainder (pretty_filename, fd, COPY_TO_EOF);
  16.     }   
  17.   else
  18.     {   
  19.       off_t start_pos = -1;
  20.       off_t end_pos;

  21.       /* Use file_lines only if FD refers to a regular file for
  22.          which lseek (... SEEK_END) works.  */
  23.       if ( ! presume_input_pipe
  24.            && S_ISREG (stats.st_mode)
  25.            && (start_pos = lseek (fd, 0, SEEK_CUR)) != -1
  26.            && start_pos < (end_pos = lseek (fd, 0, SEEK_END)))
  27.         {   
  28.           *read_pos = end_pos;
  29.           if (end_pos != 0
  30.               && ! file_lines (pretty_filename, fd, n_lines,
  31.                                start_pos, end_pos, read_pos))
  32.             return false;
  33.         }   
  34.       else                    {
  35.           /* Under very unlikely circumstances, it is possible to reach
  36.              this point after positioning the file pointer to end of file
  37.              via the `lseek (...SEEK_END)' above.  In that case, reposition
  38.              the file pointer back to start_pos before calling pipe_lines.  */
  39.           if (start_pos != -1)
  40.             xlseek (fd, start_pos, SEEK_SET, pretty_filename);

  41.           return pipe_lines (pretty_filename, fd, n_lines, read_pos);
  42.         }
  43.     }
  44.   return true;
  45. }
复制代码

论坛徽章:
1
数据库技术版块每日发帖之星
日期:2016-07-18 06:20:00
发表于 2013-05-04 11:18 |显示全部楼层
@hbmhalley,能不能帮我每一行赋值到一个字符串数组的caBUf[m][1024]
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

数据风云,十年变迁
DTCC 第十届中国数据库技术大会已启航!

2019年5月8日~5月10日,由IT168旗下ITPUB企业社区平台主办的第十届中国数据库技术大会(DTCC2019),将在北京隆重召开。大会将邀请百余位行业专家,就热点技术话题进行分享,是广大数据领域从业人士的又一次年度盛会和交流平台。与SACC2018类似,本届大会将采用“3+2”模式:3天传统技术演讲+2天深度主题培训。大会不仅提供超100场的主题演讲,还会提供连续2天的深度课程培训,深化数据领域的项目落地实践方案。
DTCC2019,一场值得期待的数据技术盛会,殷切地希望您报名参与!

活动入口>>
  

北京盛拓优讯信息技术有限公司. 版权所有 16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122
中国互联网协会会员  联系我们:huangweiwei@it168.com
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP