zoukankan      html  css  js  c++  java
  • 有关fgetc配合feof逐行读取文件最后一行读取两遍的错觉?

    最近在做一个wifiap设置的接口,用户首先获取到当前wifi 热点的ssid 和pwd,然后修改,保存。

    获取信息的时候是fopen对应的hostapd.conf文件,逐行读取,查找匹配的参数。

    修改的时候则是逐行读取当前hostapd.conf文件,逐行写到新的临时配置文件里面,如果匹配到ssid或者pwd则修改成新的值再写到新文件里面。

    最后将新的临时配置文件rename成hostapd.conf。

    测试的时修改完后,cat出hostapd.conf的检查发现最后一行总是重复两遍。

    虽然不影响整体功能,但是非常出乎意料,超出预期设计的效果。

    读取更新的代码逻辑大致如下

                                            while (!feof(srcF))
                                            {
                                                    //get line data
                                                    fgets(tmp, sizeof(tmp), srcF);
                                                    f = tmp;
                                                    LOGD("get %s",f);
    
                                                    //clear space in the head
                                                    while(' ' == *f || '
    ' == *f || '
    ' == *f)
                                                            f++;
                                                    if('' == *f)
                                                            continue;
                                                    //if the comments copy directly
                                                    if('#' == *f)
                                                    {
                                                            LOGD("get comments %s", f);
                                                            fputs(f, dstF);
                                                            continue;
                                                    }
                                                    p = strstr(f, WIFI_SSID);
                                                    //we must makesure it is start with my str
                                                    if(p == f)
                                                    {
                                                            //replace new ssid name
                                                            p += strlen(WIFI_SSID);
                                                            sprintf(p,"%s
    ", ssid);
                                                            LOGD("replace new ssid %s",f);
                                                            fputs(f, dstF);
                                                            continue;
                                                    }
    
                                                    p = strstr(f, WIFI_PW);
                                                    //we must makesure it is start with my str
                                                    if(p == f)
                                                    {
                                                            //replace new password
                                                            p += strlen(WIFI_PW);
                                                            sprintf(p,"%s
    ",  pw);
                                                            LOGD("replace new pwd%s",f);
                                                            fputs(f, dstF);
                                                            continue;
                                                    }
                                                    else
                                                            fputs(f, dstF);
                                                    LOGD("copy      %s",f);

    大概看一下总体的循环逻辑是没错

    【判断是否到了文件结束-->读取一行内容-->将读取的内容写到新的文件中】

    但是仔细查条件检查和返回值的判断,还是发现忽略了一些细节。

    1、读完了最后一行还没读到EOF,需要下一次读取才到EOF。

    2、没有对fgets返回值进行判断,最后一次读完再去读取的时候会返回NULL。

    3、没有对读取数据的tmp buf进行清空处理。

    事实上最后一次没读到东西,只是tmp里面的数据是上一次读取没有清空的,所以造成了重复读取的错觉。

    解决方法如下:

    1、判断fgets返回值,如果是NULL则continue返回去继续判断eof

     while (!feof(srcF))
      {
              //get line data
                if(NULL == fgets(tmp, sizeof(tmp), srcF))
                        continue;
            ...........
    }            

    2、先读取后判断eof

     while (1)
      {
              //get line data
               fgets(tmp, sizeof(tmp), srcF);
                if(feof(srcF))
                    break;
              ................         
    
    }             

    以上经过验证ok。

    另外最好在每次使用buf前都进行一次memset,清空缓存。

  • 相关阅读:
    Android Sqlite 增删改查
    Android SQLiteOpenHelper Sqlite数据库升级onUpgrade
    Android SQLiteOpenHelper Sqlite数据库的创建与打开
    Android Xml,PullParser,解析
    Android Xml文件生成,Xml数据格式写入
    Android Studio生成get,set,tostring,构造方法
    Android SharedPreference
    Android 文件模式
    Android 权限的由来
    C++ essentials 之 union
  • 原文地址:https://www.cnblogs.com/tid-think/p/9346287.html
Copyright © 2011-2022 走看看