文件I/O操作(2)

lseek函数原型为int lseek(int fd,int offset, int whence),fd为定位文件的描述符,offset为偏移量,如果是正数,则向文件末尾偏移,负数时,则向文件头偏移,但是不能超出文件的范围,whence为参考点,

SEEK_SET为文件头,SEEK_END为文件末尾,SEEK_CUR为文件当前操作位置返回值为操作后文件操作位置对文件头的偏移量,如果需要计算文件大小时,可以把文件操作位置移动到文件末尾,返回值即为文件的大小(字节数)

需要注意,求文件长度时把文件的操作位置移动到文件末尾,这时要在进行操作,需要把文件操作位置移回到文件头

现在可以来做一题目:解析/etc/passwd这个文件,把ect下面的用户名解析出来,并且写入另外一个文件中

这里涉及一个算法,观察每一行,会发现,我们需要的东西是冒号前面的字符,所以可以调用strchr这个函数来进行查找,strchr()这个函数的函数原型是char * strchr(const char *s,int c);返回值是函数操作的指针,这里要注意,int c是四个字节,足够容纳一个字符串,这里是继承unix的函数的接口,所以这个(笔者想,这也许可以用来制造计算机病毒,因为char是一个字节,还有三个字节可以用,如果调用strchr()函数时设计一个后门,是程序运行到strchr函数,查找其他三个字节,进而跳转到自己写的汇编代码~~笔者功力不足,但自觉告诉我这种方法可行)

回到正题,利用strchr查找到之后,指针指向冒号,将冒号改为'\0',再用printf("%s")进行打印即可

代码示例代码

include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/stat.h>
#include<sys/types.h>
#include<unistd.h>
#include<fcntl.h>

int main(void)
{
        int fd1,fd2,size,f1,f2,len;
        char *buf,*tem,*con;

        fd1 = open("/etc/passwd",O_RDONLY);

        if(fd1<0)
        {
                printf("openfile fail\n");
                return -1;
        }

        fd2 = open("test2",O_WRONLY|O_CREAT|O_APPEND,777);
        if(fd2<0)
        {
                printf("create test2 fail\n");
                return -1;
        }

        len = lseek(fd1,0,SEEK_END);
        lseek(fd1,0,SEEK_SET);

        buf = (char *)malloc(len);
        if(buf==NULL)
        {
                printf("malloc fail\n");
                return -1;
        }

        memset(buf,0,len);

        size = read(fd1,buf,len);
        if(size <0)
        {
                printf("read fail\n");
                return -1;
        }

        tem = buf;
        while(1)
        {
                con = strchr(tem,':');//查找字符串
                if(con!=NULL)  //字符串找到了
                {
                        *con = '\n';  //将该处设为回车    
                        *(con+1)='\0';//将该处设为打印时的断点


                        f1 = write(fd2,tem,strlen(tem));//写入文件
                        if(f1 <0)
                        {
                                printf("write fail\n");  
                                return -1;
                        }


                        tem = con+2;
                        con = strchr(tem,'\n');
                        if(con !=NULL)
                        {
                                tem = con +1;

                        }
                        else
                        {
                                break;
                        }
                }
                else
                {
                        break;
                }
        }
        close(fd1);
        close(fd2);
        free(buf);
        
        return 0;
}
             

注意这里写入文件test2编译可以执行,但是不能执行第二次,原因是没有权限,所以要调用命令chmod 777 text2将文件的权限全部打开,才能重复执行代码,这里调用的lseek函数用来计算文件的总长度,返回值即是文件的长度,在调用malloc()分配相应的字节数,这样就可以一次性读完了文件,而不用重复读写,这种方法虽然能够提高代码运行的速度,但是在大文件的时候,文件可能太大,会占用过多的系统资源,所以,读取文件要进行适当的选择,但是一般是都一次性读取

例2:读取该文件中间五十个字节:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>

int main(void)
{
        int fd1,fd2,size,mid,slen;
        char *buf;

        fd1 = open("/etc/passwd",O_RDONLY);
        if(fd1 < 0)
        {
                printf("open fail\n");
                return -1;
        }

        fd2 = open("chazao",O_CREAT|O_RDWR,777);
        if(fd2 < 0)
        {
                printf("open fail\n");
                return -1;
        }

        fd2 = open("chazao",O_CREAT|O_RDWR,777);
        if(fd2 < 0)
        {
                printf("create chazao fail\n");
                return  -1;
        }

        size = lseek(fd1,0,SEEK_END);
        mid = size/2;
        lseek(fd1,-(mid+25),SEEK_END);//这里负号表示向文件头偏注意一定是负号

        buf = (char *)malloc(50);
        if(buf ==NULL)
        {
                printf("malloc fail\n");
                return -1;
        }
                             

 

 

版权所有,转载请注明链接地址:http://www.cnblogs.com/fengdashen/p/3304046.html

posted @ 2013-09-07 10:40  跨七海的风  阅读(373)  评论(0编辑  收藏  举报