file esp8266 nodeMCU
闲言碎语
这个系列距离上次发布文章已经过去了三周了。其实我还没有脱坑,只是没有以前勤快而已。预计这个系列估计还可以水10篇文章左右。之后开始发布一些综合性强一点的文章,或许可以开多一个系列,在这之前先完成基础(本)系列,还有就是Lua。额, 怎么感觉像是在写2017年的计划。
模块函数
这回介绍的是file模块,需要注意的是,模块不支持文件夹,也就是说全部文件都在一个目录下。nodeMCU拥有4M的内置flash,可以用来存储lua文件或者其他类型的文件。这个模块的函数还是比较多的。模块(文件系统)支持内置flash和外置SD卡的操作。斜体函数表示只支持flash,加粗函数只支持SD卡,其余的函数flash和SD卡均支持。
另外,具体涉及对文件访问的函数,操作上有两种模式:基础模式和对象模式,表格空行后面的所有函数。。简单的讲基础模式就是同一时刻只支持一个文件的操作,例如无法同时打开两个文件。对象模式则可以,所有文件为独立对象,可以使用对应的函数实现独立操作。文档中提到了,同时使用两种模式会引发不可预期的后果。
序号 | 函数名 | 参数 | 返回值 |
---|---|---|---|
1 | file.chdir() | dir | true / false |
2 | file.exists() | filename | true / false |
3 | file.format() | 空 | 空 |
4 | file.fscfg () | 空 | flash addr,size |
5 | file.fsinfo() | 空 | remaining,used,total |
6 | file.list() | 空 | table {name:size} |
7 | file.mount() | ldrv[, pin] | Volume object |
8 | file.on() | event[, function()] | 空 |
9 | file.open() | filename, mode | object / 空 |
10 | file.remove() | filename | 空 |
11 | file.rename() | oldname, newname | true / false |
12 | file.close() | 空 | 空 |
13 | file.obj:close() | 空 | 空 |
14 | file.flush() | 空 | 空 |
15 | file.obj:flush() | 空 | 空 |
16 | file.read() | number / char | string |
17 | file.obj:read() | number / char | string |
18 | file.readline() | 空 | string |
19 | file.obj:readline() | 空 | string |
20 | file.seek() | [whence [, offset]] | position / 空 |
21 | file.obj:seek() | [whence [, offset]] | position / 空 |
22 | file.write() | string | true / 空 |
23 | file.obj:write() | string | true / 空 |
24 | file.writeline() | string | true / 空 |
25 | file.obj:writeline() | string | true / 空 |
函数虽然有点多,但是对应接触过文件系统(比如fatfs)的人来说应该不会陌生。在实践之前简单说一下开头的几个和flash有关的函数,没有SD卡模块可以试,关于SD卡的不讲(以后有机会再补)。
.chdir() 改变文件目录,目录有/FLASH(内置flash对应这个目录),/SD0,/SD1。当目录设置成/FLASH时,在使用其他函数传入文件名 为init.lua,则访问的路径是/FLASH/init.lua。
.exists() 这个很简单,判断一个文件是否存在。
.format() 你懂的,格式化。注意,不支持SD卡。
.remove() 移除文件。
.rename()重命名。
实践一下
查询flash中有那些文件,可以使用.list()函数。函数返回一个table类型,包括文件名和文件大小(存在0字节)。
l = file.list()
for name, size in pairs(l) do
print("name: " ..name..", size: "..size)
end
对于文件的访问,有两种模式。区别在于前缀,一个是 file.,一个是obj:。obj对应实际的变量名。当只要访问一个文件的时候可以用前者,当想复制文件或者同时打开两个文件甚至多个的时候就只能用后者了。
对文件的访问其实也很简单。如果是要读文件,一般的流程是打开文件(open),读数据(read),最后记得要关闭文件(close)。
如果是要写文件,流程相对复杂一点。打开(或者创建)文件(open),写入数据(write),关闭文件(close)。如果写入数据内容比较多的话,则中间可能需要保存数据(flush),防止突然掉电导致数据丢失。因为使用写操作的时候,数据并没有立刻写人存储器,只有使用flush或者关闭文件的时候才会。有时候写操作是往一个存在的文件里面写,可能还需要调整写人位置,类似于移动光标。
file.open("file.txt", "w")
for i=1, 3, 1 do
ch = "string_" .. i
file.writeline(ch)
end
file.close()
if file.open("file.txt") then
result = file.readline()
while result ~= nil
do
print(result)
result = file.readline()
end
end
file.close()
这里我们以写的模式打开一个名为file.txt的文件,如果文件不存在则会先创建。具体有这3*2中模式:
- "r": 读(默认);
- "w": 写;
- "a": 追加模式;
- "r+": 更新模式,先前的内容会保留;
- "w+": 更新模式,先前的内容会被擦除;
- "a+": 追加更新模式,先前的内容被保留,但只能从末尾添加。
通常情况都是使用r和w这两种模式。然后往文件写入三行内容。.writeline()会在字符串末尾添加一个 \n,写入内容后会换行。write()函数则不会换行,需要自己换行。
写完文件后,使用readline()来读取写入的内容。这个函数会读取一行内容(以 \n 为一行,如果超过1024则读取1024个字节)。
fd = file.open("file.txt", "w")
if fd then
for i = 1, 3, 1 do
ch = "string_"..i
fd:writeline(ch)
end
fd:close()
fd = nil
end
fd = file.open("file.txt", "r")
if fd then
result = fd:read()
print(result)
end
fd:close()
这个例子本来是想用对象模式的。不过,open返回的竟然是个布尔值,回头有空再看看为什么返回一个布尔值。
这个例子使用了对象模式,如果你在运行的时候提示fd是个布尔值的话,需要重新编译最新版本的固件。
.read()函数和readline()不一样。前者可以指定读取多少字节或者读到某个字符为止。如果什么都没传入,这读取一个块,默认是1024字节。如果使用读取字符的,但是一直没有读到该字符的,则读够一个块就结束。
if file.open("file2.txt") then
file.seek("set", 2)
print(file.readline())
file.seek("cur", 4)
print(file.readline())
end
file.close()
.seek()函数很简单,不过很好用。可以移动“光标”在文件的位置,实现任意位置的读写操作。
最后来看一个文件拷贝的例子,这个例子需要用对象模式才可以实现。先读file.txt的内容,在将内容写入copy.txt里面。
fw = file.open("copy.txt", "w")
fd = file.open("file.txt", "r")
if fd then
result = fd:read()
if fw then
fw:write(result)
fw:close()
fw = file.open("copy.txt", "r")
print(fw:read())
end
end
fd:close()
fw:close()
fd = nil
fw = nil
更多内容
1、nodeMCU学习笔记–快速上手
2、nodeMCU学习笔记–tmr模块
3、nodeMCU学习笔记–gpio模块
4、nodeMCU学习笔记–pwm模块
5、nodeMCU学习笔记–uart(附透传例子)
6、nodeMCU学习笔记–wifi模块·上
7、nodeMCU学习笔记–wifi模块·中
8、nodeMCU学习笔记–wifi模块·下
9、nodeMCU学习笔记–net模块
10、nodeMCU学习笔记--ws2812模块
11、nodeMCU学习笔记--mqtt模块