Vollständige API-Lese - Schreib-Dateien: Lesen von txt / csv / bin, Schreiben von Dateien, Durchreisen von Verzeichnissen, Kopieren / Löschen. Die Kernidee ist eine -Streaming, niemals mehr als 2 KB gleichzeitig im Speicher。Der HMI-Speicher ist sehr klein, und die Verletzung dieses Watchdogs wird direkt zurückgesetzt, und das Gerät wird ohne Vorwarnung neu gestartet.
1. Identifikation des Speichergeräts (M-Serie vs DH-Serie)
| Gerät | M-Serie | DH-Serie |
|---|---|---|
| SD-Karte | 1:/1.txt | /sdcard/1.txt |
| USB-Laufwerk | 2:/1.txt | /udisk/1.txt |
| Der interne Flash | 3:/1.txt | /data/1.txt |
Der Pfadtrennzeichen muss / verwendet werden.
2. API-Dokumentationsübersicht
| Funktion | Parameter | Beschreibung |
|---|---|---|
dofile(name) | lua Dateipfade | Lade ausführende. lua-Module, große Entfernung von Modulen |
list_dir(path) | Verzeichnispfad | asynchron durchsucht das Verzeichnis, das Ergebnis ruft auf_list_dir |
on_list_dir(path,filename,type,fsize) | type 0 = Ordner / 1 = Datei; fsize Byte | Einmal wiederholt, wenn man einen Eintrag findet. |
file_open(path,mode) | mode 0 = FA_READ read only / 1 = FA_WRITE overwrite write / 2 = FA_WRITE _ ADD Add-on write | Öffnen Sie die Datei, zurückgeben Boolean |
file_close() | - | Schließen Sie die Datei, nach dem Schreiben muss wiederholen, Datenverlust-Schutz |
file_size() | - | Gesamtzahl der Bytes der aktuell geöffneten Datei |
file_seek(offset) | Byte Offset, 0 = Dateianfang | Lese - und Schreibort |
file_read(count) | 1 ≤ count ≤ 2048 | Lesen von Bytearray (table, Unterzeichnis von 1), fehlgeschlagen zurückgegeben nil |
file_write(data) | Bytetabelle, 1 ≤ #data ≤ 2048 | Schreiben von Bytearray, zurückgegeben Boolean |
file_delete(path) | Vollständiger Pfad | Dateien gelöscht, nicht wiederhergestellt |
file_copy(src,dst) | Quell / Ziel Vollständiger Pfad | Datei repliziert, Fortschrittsrufback on_copy_file_process |
on_copy_file_process(status,filesize,transfersize) | status 0 fehlgeschlagen / 1 in Gang / 2 erfolgreich | Kopieren Fortschrittsrufback, transfersize kopiert Bytes |
mkdir(dir) | Vollständiger Verzeichnispfad | Ordner synchronisiert |
3.🔴 Sicherheitseinsatz (nicht zu sehen)
Es ist streng verboten, mehrfach gelesenen Daten in globalen Variablen oder in Puffern mit langem Lebenszyklus zu sammeln.Typischer Fehler: Das erste Lesen von 2 KB Speicherung der globalen Tabelle, später jedes Mal Lesen und hinzufügen - Speicher wächst kontinuierlich bei der Verarbeitung großer Dateien, direkt auslösen die Reset-Wachhund.
Die richtige Haltung:StreamingJedes Mal, wenn file_read (2048) sofort analysiert / verifiziert / schreibt / zeigt, und die Verarbeitung ist abgeschlossen, freigegeben, nur ein temporärer Puffer von ≤ 2 KB im Speicher zu jedem Zeitpunkt. Das gleiche gilt für das Schreiben von Dateien: Vorbereiten Sie nur einen Block von ≤ 2048 Bytes sofort file_write, nicht zuerst eine große Tabelle von mehreren MB schreiben und dann in Segmenten schreiben (Datenvorbereitungsphase ist der Speicher überflutet).
4. Lesen von Dateien: Streaming-Blocking + Rückruf
Offizielle Kapselungfile.read_stream(filepath, on_chunk): Öffnen → Größe nehmen → Schleife seek + read (≤ 2048) → auf _ chunk (chunk, offset, is _ last) pro Block → Schließen der Datei. Der Rückruf gibt false zurück, um vorzeitig zu beenden, und die große Datei-Schleife nutzt feed _ dog (), um den Hund zu füttern.
4.1 Lesen Sie das txt Zeile für Zeile
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") -- 按行分割
g_line_buffer = lines[#lines] -- 保留不完整行(可能跨块)
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
endBeachten Sie, dass die Zeilenpuffer zwischen den Blöcken liegen: Zeilenwechsel können genau zwischen zwei Blöcken liegen, also halten Sie g _ line _ buffer auf, um unvollständige Zeilen für den nächsten Block zu überlassen.
4.2 Lesen Sie Bin in 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 字节提交一行
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 字节补 0
while #g_byte_buffer < 16 do table.insert(g_byte_buffer, 0) end
record_write_data(1, g_byte_buffer)
end5. Schreiben von Dateien
Kapselfile.write_chunk(filepath, data, mode)Modus 1 = Überschreiben, 2 = Zusatzschreiben, data unterstützt String oder Byte 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
-- 场景1:新建写
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)
-- 场景2:追加写
file.write_chunk("1:/"..name..".txt", msg.."n", 2)und️ Das Nachschreiben muss explizit file_seek (file_size()) sein.HMI-file _ open (mode = 2) ist nicht gleich POSIX-O _ APPEND und wird nicht automatisch am Ende gezeigt - ohne seek schreiben Sie mit Offset 0 und überschreiben Sie den Anfang der ursprünglichen Datei.
6.Überholen + Kopieren löschen
6.1 Durchschreiten Sie das SD-Root - Verzeichnis, um das Datenaufzeichnungssteuerelement anzuzeigen
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, "未知"
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
-- 刷新按钮 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
end6.2 Kopieren + Löschen (mit Fortschrittsleiste)
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) -- 进度条
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 -- 复制
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 -- 删除
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
endAus dem VisualHMI-Entwicklungsdokument von Guangzhou Dacai Technology (hmi-doc.gz-dc.com) LUA-Tutorial "Dateien lesen und schreiben", das Urheberrecht liegt bei Dacai Technology.
Antwort veröffentlichen