免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 3080 | 回复: 10
打印 上一主题 下一主题

关于一文件操作 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2008-03-10 18:21 |只看该作者 |倒序浏览
用PHP或C或Perl或Python

一个文件,里面的数据大概有10万行,每行数据的格式相同,都是“val1,val2,val3,val4”这样,就是以“,”隔开的一行数据

我怎么删除其中某一行数据?我觉得,读入内存中一结构或变量,然后操作该结构或变量,然后再写入文件,不行,因为数据量太大

论坛徽章:
0
2 [报告]
发表于 2008-03-10 19:00 |只看该作者
一行一行读,不是那行的就写入另一文件,处理完删掉原文件,再改名...

论坛徽章:
0
3 [报告]
发表于 2008-03-10 21:38 |只看该作者
while(<>)
{
   print [split(/,/,$_)]->[0], [split(/,/,$_)]->[1], [split(/,/,$_)]->[3];
}
这样就删除了第三行,噢,上面是perl写的

论坛徽章:
0
4 [报告]
发表于 2008-03-11 09:07 |只看该作者
to 3227049:
谢谢。但你的方法不可行,我就是想避免在内存中同时载入两个文件,或者一个文件同时一个大的变量或数据结构。我描述的操作比较频繁,而且有几十个这样的文件,这样频繁删除和新建文件,除了我刚刚是说的缺点外,还易造成大量碎片。

to alexru:
谢谢。我知道是Perl写的,但你的方法除了上面的缺点外,代码的语义本身就错了,你去掉的是每一行行的第三列(就是第二个“,”和第三个“,”之间的数据)。

论坛徽章:
0
5 [报告]
发表于 2008-03-11 14:43 |只看该作者

解决

//PHP版本,很容易改写为C版本

//更新文件中的某一行
function update_fline($fp, $mid, $points, $point_time)
{
        $buff = $c = '';
        $offset_head = $offset_tail = 0;        //相应行的开始位置和结束位置(距文件开始位置的字节数)
        $is_head = $is_tail = 0;        //是否到达了要求的行的开始位置和结束位置
        $comma = 0;        //逗号的位置标志

        rewind($fp);

        //查找相应行
        while(($c = fgetc($fp)) !== false) {
                $is_head || $offset_head++;
                $offset_tail++;

                //$buff中只存储每行第一个,前的数据,即MISC_MID
                if($c != ',' && !$comma)
                        $buff .= $c;
                else {
                        if(!$is_head && $c == ',')
                                (++$comma == 1) && (strcmp($buff, $mid)) || ($is_head = 1);
                        else if($c == '\n') {        //开始读新的一行
                                $comma = 0;
                                if(!$is_head)
                                        ($buff) && ($buff = '');
                                else        $is_tail = 1;
                        }
                }

                $is_tail && break;        //读到相应行的结尾,停止继续读
        }

        fseek($fp, $offset_head);        //定位文件指针到相应行的开始位置

        list(, , $points_old,) = fgetcsv($fp, $offset_tail-$offset_head);        //读取原来的积分
        $points += $points_old;
        fwrite($fp, "$mid,1,$points,$point_tmp");
}

论坛徽章:
0
6 [报告]
发表于 2008-03-12 09:07 |只看该作者
shell 版本

sed -i '/reg/{d;q}'  yourfile

论坛徽章:
0
7 [报告]
发表于 2008-03-12 09:12 |只看该作者
to sunceenjoy:

谢谢。但不可行。
zhangzhangg 该用户已被删除
8 [报告]
发表于 2008-03-12 12:08 |只看该作者
提示: 作者被禁止或删除 内容自动屏蔽

论坛徽章:
0
9 [报告]
发表于 2008-03-14 14:14 |只看该作者
基本上有2种方式,
第一种就是一行行读,然后判断找到 你要找的那行,再输出出去。
   这种方法的问题就是文件IO 次数多,频繁的IO 会比较消耗资源效率低,但实现容易

第二种是用C语言实现,把整个文件映射到内存中,再操作,这样效率最高,但要求机器内存比较大

文本文件处理常用perl,我不会,呵呵

如果能调用shell 命令 也好,交给操作系统来做,shell的代码执行效率应该比较高

论坛徽章:
0
10 [报告]
发表于 2008-03-17 00:24 |只看该作者
程序架够设计合理吗,十万行数据改1行数据是不是应该把常改动的用缓存文件
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP