TwinCAT如何获取文件大小?动态内存分配需求求助
在Beckhoff PLC中获取CSV文件大小的几种实现方法
方法1:使用标准文件操作功能块组合(推荐)
不用依赖系统API,纯PLC标准功能块就能实现:
- 用
FB_Open以**只读模式(MODE_READ)**打开目标CSV文件 - 调用
FB_Seek,将文件指针移动到文件末尾(iMode设为SEEK_END,对应数值2,iOffset设0) - 调用
FB_Tell获取当前指针位置,这个值就是文件的总字节数 - 完成后记得用
FB_Close关闭文件
示例ST代码:
VAR hFile: DINT; bOpenSuccess: BOOL; bSeekSuccess: BOOL; bGetSizeSuccess: BOOL; nFileSize: DINT; fbOpen: FB_Open; fbSeek: FB_Seek; fbTell: FB_Tell; fbClose: FB_Close; END_VAR // 打开文件(只读模式) fbOpen( sFileName := 'C:\Data\target.csv', iMode := MODE_READ, xExecute := TRUE, xDone => bOpenSuccess, hFile => hFile, xError => ); IF bOpenSuccess THEN // 将指针移至文件末尾 fbSeek( hFile := hFile, iMode := 2, // SEEK_END iOffset := 0, xExecute := TRUE, xDone => bSeekSuccess, xError => ); IF bSeekSuccess THEN // 获取文件大小 fbTell( hFile := hFile, xExecute := TRUE, xDone => bGetSizeSuccess, iPosition => nFileSize, xError => ); IF bGetSizeSuccess THEN // nFileSize即为文件字节数,可用于动态内存分配 // 关闭文件 fbClose( hFile := hFile, xExecute := TRUE ); END_IF; END_IF; END_IF;
方法2:通过ADS调用Windows CE系统API
如果PLC是Beckhoff CX系列(基于Windows CE),可以通过ADS直接调用系统API获取文件信息,推荐用FindFirstFileW函数(无需打开文件即可获取大小):
- 构造AMS地址指向本地设备(或远程目标设备)
- 用
FB_AmsCallFunction调用kernel32.dll中的FindFirstFileW,传入文件路径(宽字符格式) - 解析返回的
WIN32_FIND_DATAW结构体,其中nFileSizeLow和nFileSizeHigh组合为文件总大小 - 调用
FindClose关闭查找句柄
示例ST代码片段:
VAR stLocalAmsAddr: AMS_ADDR; hFindHandle: HANDLE; nCallResult: DINT; sTargetPath: STRING(256) := 'C:\Data\target.csv'; // 定义WIN32_FIND_DATAW结构体(宽字符版) stFileInfo: STRUCT dwFileAttributes: DWORD; ftCreationTime: FILETIME; ftLastAccessTime: FILETIME; ftLastWriteTime: FILETIME; nFileSizeHigh: DWORD; nFileSizeLow: DWORD; dwReserved0: DWORD; dwReserved1: DWORD; cFileName: ARRAY[0..259] OF WCHAR; cAlternateFileName: ARRAY[0..13] OF WCHAR; END_STRUCT; fbAmsCall: FB_AmsCallFunction; fbCloseFind: FB_AmsCallFunction; END_VAR // 获取本地AMS地址 stLocalAmsAddr := AmsGetLocalAddress(); // 调用FindFirstFileW获取文件信息 fbAmsCall( AmsAddr := stLocalAmsAddr, nPort := 851, // Windows CE的默认ADS端口 sDllName := 'kernel32.dll', sFuncName := 'FindFirstFileW', pInput := ADR(sTargetPath), cbInput := LEN(sTargetPath) * 2, // 宽字符占2字节/字符 pOutput := ADR(stFileInfo), cbOutput := SIZEOF(stFileInfo), xExecute := TRUE, nResult => hFindHandle, xDone => , xError => ); IF fbAmsCall.xDone AND (hFindHandle <> INVALID_HANDLE_VALUE) THEN // 计算文件大小:32位场景直接用nFileSizeLow,超4GB则合并高低位 nFileSize := stFileInfo.nFileSizeLow; // 64位大小计算:nFileSize64 := TO_LWORD(stFileInfo.nFileSizeHigh) * 4294967296 + stFileInfo.nFileSizeLow; // 关闭查找句柄 fbCloseFind( AmsAddr := stLocalAmsAddr, nPort := 851, sDllName := 'kernel32.dll', sFuncName := 'FindClose', pInput := ADR(hFindHandle), cbInput := SIZEOF(hFindHandle), xExecute := TRUE ); END_IF;
方法3:预记录文件大小(适合自定义生成的CSV)
如果CSV文件是由你的PLC程序生成的,可以在每次写入完成后,将当前文件大小写入一个配套的小配置文件(比如csv_size.dat):
- 写入CSV后,用方法1获取当前文件大小
- 将大小值写入同目录的配置文件
- 读取CSV前,先读取该配置文件的数值,直接用于内存分配
这种方法无需复杂操作,可靠性高,适合可控的文件生成场景。
内容的提问来源于stack exchange,提问作者Mirek
相关产品推荐
相关产品推荐

