Lua的文件操作
先简单介绍一下被迫使用Lua的IO的情境:
游戏支持玩家自定义上传头像,在排行榜中会显示玩家列表(包括本服、跨服),原有的做法是先检测CCUserDefault中是否存在指定图片的key以及它的状态。然后在下载头像、下载完成后设置对应的状态。这样导致的一个问题就是CCUserDefault的读写完全失效了。整个游戏下载的补丁包判断和其它判断就完全失效了,不得卸载游戏后重装。个人目前的推测是由于多线程引起的,暂时没有有效的依据
下载头像使用的是libcurl,嗯,又是它,在做项目这么久的过程中,发现它其实有很多地方比较坑。其中有一点我一直没搞明白,同样的一样地址,系统自带的浏览器(IOS、Android均支持)就能正常返回,而游戏中使用libcurl去下载就是死活返回errcode 28 (CURLE_OPERATION_TIMEDOUT),libcurl我设置的是60秒超时,绝对足够了
之后我做了优化,在设置自定义头像的时候,先检测本地是否有该文件,如果有直接就设置了,如果没有就放置在加载队列中,等下载完成后再设置头像,只开一条线程去下载图片。(同一张头像的url只请求一次,也避免对CCUserDefault的读写操作)。
通过libcurl下载一个“头像id.jpg.partial”的文件,然后下载完成重新写一个“头像id.jpg”的文件。在下载完成的时候,只做了简单的一个文件大小判断,如果文件小于300B就认为它是有问题的,直接删除相应的文件
-- filePath为当前下载完成的临时头像文件路径
local targetIconUrl = string.gsub(filePath, ".partial", "")
local inpFile = io.open(filePath, "rb")
local outFile = io.open(targetIconUrl, "wb")
if inpFile ~= nil then
-- 最大8KB的内存
local buffSize = 2^13
while true do
local bytes = inpFile:read(buffSize)
if not bytes then
break
end outFile:write(bytes)
end inpFile:close()
end -- 获取下载icon的大小
if outFile ~= nil then
local current = outFile:seek()
local fileSize = outFile:seek("end")
outFile:seek("set", current) cclog("==> targetIconUrl : "..tostring(targetIconUrl)..", fileSize : "..tostring(fileSize)) outFile:close() -- 小于300字节均认为不正常的数据
if fileSize < 300 then
FileUtil:DeleteFile_(filePath)
FileUtil:DeleteFile_(targetIconUrl) self:DownloadNextIconHandler()
do return end
end
end
本来,直接调用对应的FileUtil中的FileRename方法就可以实现文件的重命名,但是线上的版本没有导出相应的方法,导致目前只能通过Lua的IO来实现。
最近再看lua的源码时,才真正意识到luaconf.h中定义的 LUAI_MAXCSTACK 是 cclosure的upvalue上限,而lua内存上限似乎没有找到明确的代码。
而file:read调用的是liolib.c

底层通过调用fread方法来获得文件的内容,默认每次最多读取512(LUAL_BUFFERSIZE的值)
然后调用file:seek(“end”)来获取文件大小

底层调用feek方法来实现
本以为到这里就结束了,实际上我遇到另外一个问题。如果头像因审核问题被删除了,导致404,结果底层libcurl方法没有判断http status code,直接判断CURLcode的值是否为CURLE_OK,导致将得到的文件直接写入了。但我从崩溃的日志上得到的信息是,小米4这台设备上获得的文件大小为18378

之后就直接报
invalid address or address of corrupt block 0x7c0eaa40 passed to dlfree
之后我修改了libcurl下载文件的代码,但要等下次打整包的时候才能用上

把不是jpeg的图片直接对CCSprite进行路径赋值的时候就over了,所以需要一个检测文件是否为jpeg的方法
-- 判断资源是否为jpg
function PCUtils:CheckIsJpeg(filePath)
local isJpeg = false if FileUtil:CheckFileExistWithFullPath(filePath) then
local inpFile = io.open(filePath, "rb")
-- 读取前三位
local bytes = inpFile:read(3)
if bytes then
local fileHeadIden = ""
for _, b in ipairs{string.byte(bytes, 1, -1)} do
local val = string.format("%02X", b)
fileHeadIden = fileHeadIden..val
end if string.upper(fileHeadIden) == "FFD8FF" then
isJpeg = true
else
cclog("==> filePath : "..tostring(filePath)..", fileHeadIden : "..tostring(fileHeadIden))
end
end inpFile:close()
end return isJpeg
end
读取文件的前三位,转换为16进制,然后对比JPEG的头部,判断是否为JPEG格式的文件,这个是我想起自己之前写过的一篇文章《node.js获取图片文件的真实类型》
文件一些方法和代码,比如为何是r + b,以及2^13(8KB内存)这种技巧,都是参考《Lua程序设计 第二版》第21章 I/O库,网上应该有中文版的PDF下载,自行搜索吧…
本文参考:
Lua的文件操作的更多相关文章
- lua向文件中写入数据,进行记录
function readfile(path) local file = io.open(path, "r") if file then local content = file: ...
- 【.NET深呼吸】Zip文件操作(1):创建和读取zip文档
.net的IO操作支持对zip文件的创建.读写和更新.使用起来也比较简单,.net的一向作风,东西都准备好了,至于如何使用,请看着办. 要对zip文件进行操作,主要用到以下三个类: 1.ZipFile ...
- 野路子出身PowerShell 文件操作实用功能
本文出处:http://www.cnblogs.com/wy123/p/6129498.html 因工作需要,处理一批文件,本想写C#来处理的,后来想想这个是PowerShell的天职,索性就网上各种 ...
- Node基础篇(文件操作)
文件操作 相关模块 Node内核提供了很多与文件操作相关的模块,每个模块都提供了一些最基本的操作API,在NPM中也有社区提供的功能包 fs: 基础的文件操作 API path: 提供和路径相关的操作 ...
- 归档NSKeyedArchiver解归档NSKeyedUnarchiver与文件管理类NSFileManager (文件操作)
========================== 文件操作 ========================== 一.归档NSKeyedArchiver 1.第一种方式:存储一种数据. // 归档 ...
- SQL Server附加数据库报错:无法打开物理文件,操作系统错误5
问题描述: 附加数据时,提示无法打开物理文件,操作系统错误5.如下图: 问题原因:可能是文件访问权限方面的问题. 解决方案:找到数据库的mdf和ldf文件,赋予权限即可.如下图: 找到mdf ...
- 通过cmd完成FTP上传文件操作
一直使用 FileZilla 这个工具进行相关的 FTP 操作,而在某一次版本升级之后,发现不太好用了,连接老是掉,再后来完全连接不上去. 改用了一段时间的 Web 版的 FTP 工具,后来那个页面也 ...
- Linux文件操作的主要接口API及相关细节
操作系统API: 1.API是一些函数,这些函数是由linux系统提供支持的,由应用层程序来使用,应用层程序通过调用API来调用操作系统中的各种功能,来干活 文件操作的一般步骤: 1.在linux系统 ...
- C语言的fopen函数(文件操作/读写)
头文件:#include <stdio.h> fopen()是一个常用的函数,用来以指定的方式打开文件,其原型为: FILE * fopen(const char * path, c ...
随机推荐
- Windows 10安装pip方法
pip是一款非常方便的python包管理工具,本文主要介绍在windows 10下安装pip方法. 1. 下载pip 地址:https://pypi.python.org/pypi/pip#downl ...
- bnu 10809 聚餐
Lolilu大牛又要请客了~~有些同学呢,是果断要去的,而有些同学呢,只有确定心中的大牛会参加,他才会参加.Lolilu决定请大家去吃金钱豹,因此希望你告诉他一共会有多少人参加,他才知道带多少钱比较合 ...
- #CSS margin-top父元素下落
[我的解决方法] 给该父元素添加如下代码 border-top: 1px solid rgba(0,0,0,0); box-sizing:border-box; [原因] css2.1盒模型中规定的内 ...
- 【LOJ】#2118. 「HEOI2015」兔子与樱花
题解 怎么觉得都像树dp,不像贪心 但是树dp确实做不了 把每个节点的值设置为樱花+儿子数 把儿子合并到父亲上就是父亲的剩余容量加上儿子的值-1 每次在父亲的时候将儿子的值排序然后能加就加上 因为儿子 ...
- 2018年长沙理工大学程序设计竞赛 J - 杯子
题意: 链接:https://www.nowcoder.com/acm/contest/96/J一天durong同学买了一个无限长的杯子,同时买了n个球,并且标号为1,2,3......n,duron ...
- java学习之租车系统
背景:有三种类型的车供给用户来租用 要求:控制台用户交互界面,根据用户需求输出租车价格,结果如下: 创建租车类主要设计过程: 创建租车类 创建Car父类,包含四种属性成员,重写构造方法 创建三种 ...
- hdu 5407(LCM好题+逆元)
CRB and Candies Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)T ...
- HTML5 LocalStorage 本地存储(转)
原文:http://www.cnblogs.com/xiaowei0705/archive/2011/04/19/2021372.html HTML5 LocalStorage 本地存储 说到本地存储 ...
- html (第四本书第七章浮动参考)
课上1 <!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8 ...
- 系统的Drawable(一)
系统的Drawable(一) 学习自 <Android 开发艺术探索> <官方文档> https://www.cnblogs.com/popfisher/p/6238119.h ...