tt99166 发表于 2023-4-12 22:39:38

CODESYS开发教程10-文件读写(SysFile库)


今天继续我们的小白教程,老鸟就不要在这浪费时间了:loveliness:。

前面一期我们介绍了CODESYS的文件操作库CAA File。这一期主要介绍CODESYS的SysFile库所包含的文件读写功能块,主要包括文件路径、名称、大小的获取以及文件的创建、打开、读、写、拷贝和删除功能等。

一、SysFile库简介

与上一期介绍的目录和文件操作库CAA File不同,SysFile属于CODESYS比较底层的库,其中结构和功能块的定义与C语言非常接近。使用该库需要在“库管理器”中添加SysFile库,这里使用的是3.5.15版本。



需要注意的是,SysFile库中所有功能均为函数(FUNCTION),与CAA File库中的功能块(FUNCTION_BLOCK)是不同。函数可以直接使用,而功能块需要先声明后使用。因为CODESYS的函数内部的变量在运行后是不会保留的,这个与功能块是不同。使用的时候要分清楚,避免因为初始状态不同导致的问题。

二、SysFile库的主要功能块

提供对运行时系统的文件功能的访问。仅能进行文件相关的操作。

1.基本定义

(1)文件访问模式ACCESS_MODE

定义文件打开的模式。



注意:对于所有*_PLUS模式,读取文件后,只能在调用SysFileGetPos或SysFileSetPos后才能进行写入!如果在SysFileRead之后立即调用SysFileWrite,则文件指针可能位于无效位置!正确的使用方式如下:

SysFileRead();

SysFileGetPos();

SysFileWrite();

(2)文件的时间戳SYS_FILETIME

定义文件的时间戳结构。

tCreation:文件创建时间。

tLastAccess:访问文件的时间。

tLastModification:上次修改的时间。

(3)文件状态SYS_FILE_STATUS

定义指定文件的实际文件状态。



(4)错误码定义Errors

此错误码定义位于CmpErrors库中,文件读写中常用的如下表所示:



由于错误定义较多,这里只列了比较常用的几个,上表中没有列出的可以参考官方文档。

2.文件操作函数

文件操作函数如下表:



3.常用的函数介绍

SysFile库文件操作函数的参数比较类似,下面对几个常用的函数进行介绍。

(1)SysFileOpen

szFile:文件名称。可以包含绝对或相对路径,注意路径需要用斜杠“/”表示,不能用反斜杠“\”。

am:打开模式,类型为SysFile.ACCESS_MODE。

pResult:返回运行系统错误代码,类型为POINTER TO RTS_IEC_RESULT,含义在CMPErrors库中定义,见第一部分介绍。

返回值:成功则返回文件句柄,类型为SysFile.RTS_IEC_HANDLE,失败则返回RTS_INVALID_HANDLE。

(2)SysFileClose、SysFileFlush

hFile:文件句柄,类型为SysFile.RTS_IEC_HANDLE。

返回值:返回运行系统错误代码,类型为RTS_IEC_RESULT。

(3)SysFileRead和SysFileWrite

hFile:文件句柄。

pbyBuffer:指向读或者写缓冲区首地址,类型为POINTER TO BYTE。

ulSize:需要读取或写入的字节数。注意必须小于等于缓冲区尺寸。

pResult:返回运行系统错误代码。

返回值:成功则返回读取或写入的字节,失败则返回0。数据类型为_XWORD,实际与DWORD等价。

(4)SysFileGetSize

szFileName:文件名称

pResult:返回运行系统错误代码。

返回值:文件尺寸。

(5)SysFileGetTime

szFileName:文件名称

ptFileTime:文件时间,类型为POINTER TO SYS_FILETIME。

返回值:返回运行系统错误代码,类型为SysFile.RTS_IEC_RESULT。

注意:以上函数中凡是类型为RTS_IEC_RESULT的返回值,如果是在函数中作为输入,则需要定义为指针POINTER TO RTS_IEC_RESULT或者使用ADR()来获取错误码;如果作为函数返回值,则为SysFile.RTS_IEC_RESULT。

三、SysFile库使用示例

SysFile库的函数可以直接一起顺序使用,也可以像CAA File库中的功能块一样按状态机的方式进行操作。以下示例为文件写入的分步操作。本次测试使用的控制器是禾川的Q0,使用其它控制器时需要正确指定可进行读写操作的目录位置。

程序变量定义如下:

PROGRAM testSysFile

VAR

       bExecute : BOOL;

       szFileName    : STRING:='/testfile.txt';

       pbyBuffer      : POINTER TO BYTE;

       ulSize            : DWORD;

       ErrorCode      : INT;

       Done             : BOOL;

       stContent      : STRING:='hello everyone!';

       Mode            : SysFile.ACCESS_MODE := 1;      //0-AM_READ; 1-AM_WRITE; 2-AM_APPEND; 3-AM_READ_PLUS; 4-AM_WRITE_PLUS; 5-AM_APPEND_PLUS

       iStep      : INT := 0;      //运转流程

       OP_TRIG : R_TRIG;

       bError            : BOOL;

       hFile       : SysFile.RTS_IEC_HANDLE;

       pRes            : SysFile.RTS_IEC_RESULT;

       iRet      : DWORD;

END_VAR

程序如下:

bExecute:=TRUE;

OP_TRIG(CLK := bExecute);

pbyBuffer:=ADR(stContent);

ulSize:=SIZEOF(stContent);

IF OP_TRIG.Q AND iStep=0 THEN

       iStep := 1;

END_IF

CASE iStep OF

0:

       IF bExecute=FALSE THEN

            Done := FALSE;

            ErrorCode := 0;

            bError := FALSE;

       END_IF

1:

       hFile := SysFileOpen(szFileName, Mode, ADR(pRes)); //打开文件

       IF (pRes<>0 OR hFile=SysFile.RTS_INVALID_HANDLE) THEN

            bError := TRUE;

       ELSE

            iStep := 2;

       END_IF

2:

       iRet:=SysFileWrite(hFile, pbyBuffer, ulSize, ADR(pRes)); //内容写入文件

       IF (iRet=0) THEN

            SysFileClose(hFile);

            bError := TRUE;

       ELSE

            iStep := 3;

       END_IF

3:

       pRes:=SysFileFlush(hFile); //缓存内容写入文件

       IF (pRes=0) THEN

            iStep := 4;

       ELSE

            SysFileClose(hFile);

            bError := TRUE;

       END_IF

4:

       pRes:=SysFileClose(hFile); //关闭文件

       IF pRes=0 THEN

            Done := TRUE;

            iStep := 0;

       ELSE

            bError := TRUE;

       END_IF

END_CASE

//错误检查

IF bError THEN

       iStep := 0;

       ErrorCode := 1;

END_IF

注意:SysFile库的文件读写操作是不能被其它周期任务中断的。当需要读写的文件较大时,需要的时间会比较长。这时候需要把运行读写程序的任务周期调长,保证读写操作能够顺利完成。如果任务时间不够,可能会出现文件没有读完或者写完的情况。

四、结论

SysFile库实际上属于运行系统的文件操作函数,不管是操作方式还是参数定义都与C语言的对应函数类似,对C语言比较熟悉的朋友应该很容易上手。另外需要注意的是底层操作函数与平台相关性较大,比如读写时间与所使用的的控制器平台关系很大,最好是在自己使用的平台上做一些读写测试后设置合理的任务周期,避免出现文件读写不完整问题。

关于SysFile库读写大文件的问题,还有一种思路是把以上代码封装成功能块,在读或者写过程中把大文件拆分成尺寸较小的块,通过分步多次读写,每次进入读写流程时读或者写一块,直至所有内容读写完成。当然这个流程会复杂一些,嫌麻烦的还是直接用CAA File库来实现吧~~~^-^。
————————————————
版权声明:本文为CSDN博主「--莫名--」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/halps/article/details/128974489
页: [1]
查看完整版本: CODESYS开发教程10-文件读写(SysFile库)