请教一个FileUtils文件读取缓存的问题

有demo么,上传一个呗

//初始化filemap
 static std::map <std::string, Data> _fileMap;

//重置filemap
 static void resetFileMap() {
    std::map<std::string, Data>::iterator iter;
    for(iter =_fileMap.begin();iter!=_fileMap.end();iter++)
    {
        //清理cocos的data
        (iter->second).clear();
        _fileMap.erase(iter);
    }
    std::map<std::string, Data> empty_map1;
    _fileMap.swap(empty_map1);
    _fileMap.clear();
}
//设置filemap key值
 static void setFileMap(std::string key,Data data){
//    Data retData;
//             //retData.fastSet(l_it->second.getBytes(),l_it->second.getSize());
//           retData.copy(data.getBytes(),data.getSize());
    Data clone;
     _fileMap[key] = data;
}
//获取filemap 根据key值
 static Data getFileMap(std::string key){
//    std::map<std::string, Data>::iterator iter;
//    iter=_fileMap.find(key);
//    if(iter==_fileMap.end())
//    {
//        CCLOG("Get data from cache file null");
//       return Data::Null;
//    }
//    for(auto item =_fileMap.begin();item!=_fileMap.end();item++)
//    {
//         if(item->first==key)
//         {
//             auto value= item->second;
//             CCLOG("Get data from cache file %s", key.c_str());
//             return value;
//            //do someting.....
//         }
//    }
    
    std::map<std::string, Data >::iterator l_it;
    l_it=_fileMap.find(key);
     int count=0;
     for(auto it=_fileMap.begin();it!=_fileMap.end();it++)  {
         count++;
     }
      CCLOG("size:%s \n",std::to_string(count).c_str());
    if(l_it==_fileMap.end()){
        CCLOG("Get data from cache null");
         return Data::Null;
    }
    else{
        CCLOG("Get data from cache key333:%s \n",l_it->first.c_str());
        CCLOG("Get data from cache key:%s \n",key.c_str());
         //CCLOG("Get data from cache key:%s \n content:%s",key.c_str(),l_it->second.getBytes() );
          Data retData;
////          //retData.fastSet(l_it->second.getBytes(),l_it->second.getSize());
         retData.copy(l_it->second.getBytes(),l_it->second.getSize());
         return retData;
          //return l_it->second;
    }
//    CCLOG("Get data from cache null");
//    return Data::Null;
}
//设置filemap key值
 static void setFileMapIsNull(std::string key){
    Data assignData = getFileMap(key);
    if(!assignData.isNull()){
        assignData.clear();
    }
}
static Data getData(const std::string& filename, bool forString)
{
    if (filename.empty())
    {
        return Data::Null;
    }
    const char* mode = nullptr;
    if (forString)
    {
        mode = "rt";
    }
    else{
        mode = "rb";
    }
          
    std::string fileName2=filename.c_str();
    replace(fileName2.begin(),fileName2.end(),'/','_');
    replace(fileName2.begin(),fileName2.end(),'.','_');
    fileName2=fileName2+"_"+mode;
    Data tmp = getFileMap(fileName2);
    if(!tmp.isNull()){
       // CCLOG("first getCahceData %s", filename.c_str());
        return tmp;
    }
    Data ret;
    unsigned char* buffer = nullptr;
    size_t size = 0;
    size_t readsize;

   

  //std::string  bufferC = NULL;
    auto fileutils = FileUtils::getInstance();
    do
    {
        // Read the file from hardware
        std::string fullPath = fileutils->fullPathForFilename(filename);
        FILE *fp = fopen(fileutils->getSuitableFOpen(fullPath).c_str(), mode);
        CC_BREAK_IF(!fp);
        fseek(fp,0,SEEK_END);
        size = ftell(fp);
        fseek(fp,0,SEEK_SET);

        if (forString&&false)
        {
            buffer = (unsigned char*)malloc(sizeof(unsigned char) * (size + 1));
            buffer[size] = '\0';
        }
        else
        {
            buffer = (unsigned char*)malloc(sizeof(unsigned char) * size);
        }

        readsize = fread(buffer, sizeof(unsigned char), size, fp);
        fclose(fp);

        if (forString && readsize < size)
        {
            CCLOG("为什么进到这里");
            buffer[readsize] = '\0';
        }
       // bufferC= ((const char*)buffer);
    } while (0);

    if (nullptr == buffer || 0 == readsize)
    {
        CCLOG("Get data from file %s failed", filename.c_str());
    }
    else
    {
        ret.fastSet(buffer, readsize);
        CCLOG("第一次设置数据%s:", fileName2.c_str());
//        unsigned char* readSizeOut=( (unsigned char *) &readsize);
//        CCLOG("readsize%s:", readSizeOut);
//        unsigned char* sizeOut=( (unsigned char *) &size);
//        CCLOG("size%s:",  sizeOut);
//        Data retData;
//        retData.copy(buffer,readsize);
        setFileMap(fileName2.c_str(), ret);
    }

    return getFileMap(fileName2);
}

std::string FileUtils::getStringFromFile(const std::string& filename)
{
    Data data = getData(filename, true);
    if (data.isNull())
        return "";

    std::string ret((const char*)data.getBytes());
    return ret;
}

表现为这个按照key读取的data getBytes 会在之前的数据基础上加一些莫名其妙的data,导致读取后解析失败,
比如:
正确为{“KEY1”:“123456”}
有时就会变成{“KEY1”:“123456”}+ 或者{“KEY1”:“123456”}[ 3 这种后面会加一些乱起八早的东西,但有时是对的,能读到正确值

哪个大佬能看下 c++ 不是很懂

我的demo的意思是你上传一下我能调试的工程

然后你的文件缓存准备做在引擎的FileUtils中?

工程太大了,基本就改了这个文件,然后 get出来的数据有时莫名其妙多出一些奇怪字符

ddddddddddddd33333bbbbb

反正我是不建议做在FileUtils中的因为图片也从这走,然后图片还有TextureCache和SpriteFrameCache到时候你的内存可能会不够用,都是缓存

可以做判断 只缓存.json结尾的

:smile:额,只要你喜欢就好

再定个水自费

std::string ret((const char*)data.getBytes()); 这句改为
std::string ret((const char*)data.getBytes(), data.getSize());

为什么的话,string如果你直接只传数据的头指针将一直读到结束符为止组装string

1赞

帮人还得自己写demo:sweat:调试

感谢大佬真的是这个原因,感谢 :heart_eyes:
还有个疑问 ,我注掉了缓存,我在这里static Data getData(const std::string& filename, bool forString) 方法前后打了时间戳,除了第一次加载,发现之后并没有时间消耗

迷惑了,io不是应该有消耗的吗,我读取的是一个260kb的json文件
打印如下:
4:16 PM 在c++中读取 getData1 asdd.json, 1592208968618

4:16 PM 在c++中读取 getData2 asdd.json, 1592208968618
为什么只第一次是有延迟,之后的读取 一个200多kb的文件读取不应该多少有点耗时吗?如果没有耗时,file的缓存好像没什么意义?:sweat_smile:

你怎么输出时间戳我不知道没法说,但是你之间macllo的内存要注意啥时候free,不然就是内存泄漏

io 是从硬盘读到内存,理论上这个getData每次应该会有时间消耗,但好像读了一次 下次没有任何时间消耗,时间戳打印到了毫秒,前后没消耗,怪异

没找到缓存代码,是不是读到硬盘缓存去了,给自动缓存了?~

这个你自己研究研究吧,搞懂了也能知道点底层的知识

再次感谢大佬帮忙~