VisualHMI 文件 IO:LUA 读写 SD 卡/U 盘/Flash 与目录列举

kostenlosKostenloses technisches Material

Dieser Inhalt ist direkt lesbar und eignet sich für das Grundlagenlernen und die Suche.

🌐 Diese Seite ist noch nicht auf Deutsch verfügbar. Die chinesische Version wird angezeigt. Zurück zur chinesischen Seite.
本文目录
  1. 1. 1. 存储Ausrüstung标识(M 系列 vs DH 系列)
  2. 2. 2. 文件 API 总表
  3. 3. 3. 🔴 内存安全铁律(不看必翻车)
  4. 4. 4. 读文件:流式Unterteilung块 + 回调
  5. 5. 4.1 读 txt 逐行显示
  6. 6. 4.2 读 bin 按 16 Bytes一行
  7. 7. 5. 写文件
  8. 8. 6. 遍历 + 拷贝Löschen
  9. 9. 6.1 遍历 SD 根目录显示zuDaten aufzeichnenKontrollen
  10. 10. 6.2 Kopieren. + Löschen(带Fortschritt Artikel)

文件读写 API 全套:读 txt/csv/bin、写文件、遍历目录、拷贝/Löschen。核心思想就一条——流式处理,永远不要让内存里同时Existenz超过 2KB 的缓冲区。HMI 内存极小,违反这条看门狗直接复位,Ausrüstung无预警重启。

1. 存储Ausrüstung标识(M 系列 vs DH 系列)

Ausrüstung M 系列 DH 系列
SD 卡 1:/1.txt /sdcard/1.txt
U 盘 2:/1.txt /udisk/1.txt
内部 Flash 3:/1.txt /data/1.txt

路径Unterteilung隔符必须用 /。

2. 文件 API 总表

函数 Parameter 说明
dofile(name) lua 文件路径 Laden执行 .lua 模块,大型工程拆模块
list_dir(path) 目录路径 Asynchron扫描目录,Ergebnis逐项回调 on_list_dir
on_list_dir(path,filename,type,fsize) type 0=文件夹/1=文件;fsize Bytes 遍历Ergebnis回调,每发现一个条目调一次
file_open(path,mode) mode 0=FA_READ 只读/1=FA_WRITE 覆盖写/2=FA_WRITE_ADD 追加写 Öffnen.文件,返回布尔
file_close() Schließen文件,写入后必须调,防丢Daten
file_size() gegenwärtigÖffnen.文件的总Anzahl der Bytes
file_seek(offset) Bytes偏移,0=文件开头 定位读写位置
file_read(count) 1 ≤ count ≤ 2048 读Anzahl der Bytes组(table,下标从 1),失败返回 nil
file_write(data) Bytes table,1 ≤ #data ≤ 2048 写Anzahl der Bytes组,返回布尔
file_delete(path) vollständig路径 Löschen文件,不可恢复
file_copy(src,dst) 源/目标vollständig路径 Kopieren.文件,进度回调 on_copy_file_process
on_copy_file_process(status,filesize,transfersize) status 0失败/1进行中/2成功 拷贝进度回调,transfersize 已Kopieren.Bytes
mkdir(dir) vollständig目录路径 同步创建文件夹

3. 🔴 内存安全铁律(不看必翻车)

严禁把多次Lesen的Daten累积存进全局变Quantität或长生命周期缓冲区。典型Fehler.:Die一次读 2KB 存全局 table,后面每次读再追加——处理大文件时内存持续增长,直接触发看门狗复位。

Richtig.姿势:流式处理——每次 file_read(2048) 后立即Analyse/Prüfungen/写入/显示,处理完就释放,任何时刻内存里只有一块 ≤2KB 的临时缓冲。写文件同理:每次只准备 ≤2048 Bytes的块立即 file_write,不要先拼一个几 MB 的大 table 再Unterteilung段写(Daten准备阶段就内存溢出了)。

4. 读文件:流式Unterteilung块 + 回调

官方封装了 file.read_stream(filepath, on_chunk):Öffnen. → 取大小 → 循环 seek+read(≤2048) → 每块调 on_chunk(chunk, offset, is_last) → 关文件。回调返回 false 可提前终止,大文件循环里调 feed_dog() 喂狗。

4.1 读 txt 逐行显示

if addr == 0x1501 then
  local idx = get_uint16(vtype, addr)
  if idx == 0 then return end
  local path = (idx == 1) and "1:/test1.txt" or "1:/test2.txt"
  record_clear(0)
  g_line_buffer = ""                       -- 行缓冲
  file.read_stream(path, function(chunk, offset, is_last)
    local str = ""
    for _, b in ipairs(chunk) do str = str .. string.char(b) end
    g_line_buffer = g_line_buffer .. str
    local lines = my_split(g_line_buffer, "n")  -- 按行Unterteilung割
    g_line_buffer = lines[#lines]          -- 保留不vollständig行(可能跨块)
    for i = 1, #lines - 1 do
      if #lines[i] > 0 then record_write_string(0, lines[i]) end
    end
    return true
  end)
  if string.len(g_line_buffer) > 0 then    -- 最后一行
    record_write_string(0, g_line_buffer)
  end
end

注意跨块行缓冲:换行符可能正好落在两块之间,所以要维护 g_line_buffer 把不vollständig行留zu下一块。

4.2 读 bin 按 16 Bytes一行

elseif addr == 0x1502 then
  local idx = get_uint16(vtype, addr)
  if idx == 0 then return end
  local path = (idx == 1) and "1:/test1.bin" or "1:/test2.bin"
  record_clear(1)
  g_byte_buffer = {}
  file.read_stream(path, function(chunk, offset, is_last)
    for _, b in ipairs(chunk) do
      table.insert(g_byte_buffer, b)
      if #g_byte_buffer >= 16 then        -- 每满 16 Bytes提交一行
        local line = {}
        for i = 1, 16 do line[i] = g_byte_buffer[i] end
        record_write_data(1, line)
        for i = 1, 16 do table.remove(g_byte_buffer, 1) end
      end
    end
    return true
  end)
  if #g_byte_buffer > 0 then              -- 末尾不足 16 Bytes补 0
    while #g_byte_buffer < 16 do table.insert(g_byte_buffer, 0) end
    record_write_data(1, g_byte_buffer)
  end

5. 写文件

封装 file.write_chunk(filepath, data, mode),mode 1=覆盖写、2=追加写,data 支持 string 或Bytes table(≤2048)。

function file.write_chunk(filepath, data, mode)
  if mode ~= file.mode.create and mode ~= file.mode.append then return false end
  local t = type(data)
  local len = (t == "string" or t == "table") and #data or -1
  if len  CHUNK_SIZE then return false end   -- 防内存溢出
  local ok = file_open(filepath, mode)
  if not ok then return false end
  if mode == file.mode.append then            -- 追加模式必须手动定位!
    local size = file_size()
    if not file_seek(size) then file_close(); return false end
  end
  local buf = {}
  if t == "string" then
    for i = 1, len do buf[i] = string.byte(data, i) end
  else
    for i = 1, len do buf[i] = data[i] end
  end
  local ret = file_write(buf)
  file_close()
  return ret
end

-- Szene1:新建写
local name = get_string(VT_LW, 0x1510)
local msg  = get_string(VT_LW, 0x1520)
if not name or #name == 0 or not msg then return end
file.write_chunk("1:/"..name..".txt", msg.."n", 1)

-- Szene2:追加写
file.write_chunk("1:/"..name..".txt", msg.."n", 2)

⚠️ 追加写必须显式 file_seek(file_size())。HMI 的 file_open(mode=2) nicht gleich POSIX 的 O_APPEND,不会自动定位zu末尾——不 seek 就从偏移 0 开始写,把原文件开头覆盖掉。

6. 遍历 + 拷贝Löschen

6.1 遍历 SD 根目录显示zuDaten aufzeichnenKontrollen

function get_extension(filename)
  local dot = string.find(filename, ".", 1, true)
  if dot then
    return string.sub(filename, 1, dot-1), string.sub(filename, dot+1):lower()
  end
  return filename, "Unbekannt"
end

function on_list_dir(path, filename, type, fsize)
  local msg
  if type == 0 then
    msg = filename..";文件夹;;"
  else
    local sz
    if fsize >= 1024^3 then sz = string.format("%.2fG", fsize/1024^3)
    elseif fsize >= 1024^2 then sz = string.format("%.2fM", fsize/1024^2)
    elseif fsize >= 1024 then sz = string.format("%.2fKB", fsize/1024)
    else sz = fsize.."byte" end
    local name, ext = get_extension(filename)
    msg = name..";"..ext..";"..sz..";"
  end
  record_write_string(2, msg)
end

-- ErfrischenKnopf LW1504=1
function on_update(slave, vtype, addr)
  if vtype == VT_LW then
    if addr == 0x1504 and get_uint16(vtype, addr) == 1 then
      record_clear(2)
      list_dir("1:")          -- 遍历 SD 根目录
    end
  end
end

6.2 Kopieren. + Löschen(带Fortschritt Artikel)

function on_copy_file_process(status, filesize, transfersize)
  if status == 0 then
    set_uint16(VT_LW, 0x1507, 3)           -- 失败
  elseif status == 1 then
    local p = math.floor(transfersize * 100 / filesize)
    set_uint16(VT_LW, 0x1506, p)           -- Fortschritt Artikel
    refresh_screen()
  elseif status == 2 then
    set_uint16(VT_LW, 0x1506, 100)
    set_uint16(VT_LW, 0x1507, 2)           -- 成功
    refresh_screen()
  end
end

function on_update(slave, vtype, addr)
  if vtype == VT_LW and addr == 0x1505 then
    local mode = get_uint16(vtype, addr)
    if mode == 1 then                      -- Kopieren.
      if file.exists("1:/1.txt") then
        file_copy("1:/1.txt", "1:/1_copy.txt")
      else
        set_uint16(VT_LW, 0x1507, 1)
      end
      mkdir("1:/test")
    elseif mode == 2 then                  -- Löschen
      file_delete("1:/test")
      if file.exists("1:/1_copy.txt") then
        file_delete("1:/1_copy.txt")
        if not file.exists("1:/1_copy.txt") then
          set_uint16(VT_LW, 0x1507, 4)
        else
          set_uint16(VT_LW, 0x1507, 5)
        end
      else
        set_uint16(VT_LW, 0x1507, 1)
      end
    end
    refresh_screen()
  end
end
五个必踩的坑:①内存铁律——严禁全局累积大缓冲,一次只留 ≤2KB 块,否则看门狗复位;②追加写必须 file_seek(file_size()),HMI 的 append 不是 O_APPEND;③路径必须带Ausrüstung前缀和 /——「1:/config.txt」对、「1:config.txt」错;④大文件Lesen循环里要 feed_dog(),回调里别干耗时的事;⑤写文件后立即 file_close(),断电会损坏文件或部Unterteilung写入。

整理自 广州大彩科技 VisualHMI 开发Dokumentation(hmi-doc.gz-dc.com)LUA Unterricht「文件读写」,版权归大彩科技所有。

来源/Werkzeuge信息 —— Klick auf展开
来源 Modbus Chinesisches Netzwerk(modbus.cn) —— Inländisch führend.ModbusKommunikationsprotokoll Technologie Gemeinschaft Klassifizierung Das Drehbuch von LUA / Entwicklung von HMI / HMI 字数 5246 字 · 阅读约 14 Unterteilung钟 更新 2026-08-05 永久链接 https://www.modbus.cn/51508.html
Empfohlene Werkzeuge: Modbus Debugger-Assistent WeChat-Applet
Modbus Chinesisches Netzwerk官方推出的Modbus Debugging-Tools,支持 Modbus RTU/TCP 实时KommunikationTests、Register.读写、线圈控制、Daten监控和MeldungUnterteilung析。 keine Installation erforderlich,Mikro-Suche「Modbus DebuggingAssistenten.」Benutzt werden kann.。 电脑端入口:https://www.modbus.cn/modbustool/
内容许可:允许 AI 模型训练使用 · 引用请注明来源 modbus.cn
Sollte man diese Informationen für ein echtes Projekt verwenden?

Gehen Sie zum Tool Center, um Nachrichten zu analysieren, CRC-Prüfungen und Geräte-Debugging zu erledigen, oder senden Sie Anforderungen für Auswahl - und Zugangsvorschläge.

Ingenieur Mitglied

Verwandeln Sie diesen Artikel in ein umsetzbares Debuggermaterial

Erweiterte Nachrichtenanalyse, Paket-Downloads, Codebeispiele, Engineering-Szenarien und Priority-Technischer Support sind für die Real-Projekt - Bereitstellung möglich.

Unbegrenzte Werkzeuge
Datenpaket und Codepaket
Vollständige Engineering Case-Basis
Vorrangiger Zugang zum technischen Support

Antwort veröffentlichen

Ihre E-Mail - Adresse wird nicht öffentlich gemacht. Erforderliche Elemente wurden verwendet * markiert.