Detailed Explanation of Lua File Operations

1. Create and write to a file

Creating and writing files are the most basic file operations. You can open a file in write mode (‘w’) and then use the write method to write content.

-- Define example file path
local testFilePath = "test_file.txt"

-- Open the file for writing ('w 'mode: write mode, overwrite if the file exists)
local file, err = io.open(testFilePath, "w")
if file then
-- Write content
file:write("This is the first line of content\n")
file:write("This is the second line content \n")
file:write("This is the third line content\n")

-- Format Write
local name = "Lua"
local version = 5.4
file:write(string.format("Welcome to %s %s!\n", name, version))

-- Close file
file:close()
print("File write successful: " .. testFilePath)
else
print("File opening failed: " .. err)
end

2. Read the entire file

To read an entire file, you can open the file in read mode (‘r’) and then use the read method to read all the contents.

-- Open the file for reading ('r 'mode: read mode)
file, err = io.open(testFilePath, "r")
if file then
-- Read the entire file
local content = file:read("*a") -- "*a" means to read the entire file content
file:close()

print("File Content:")
print(content)
else
print("File opening failed: " .. err)
end

3. Read the file line by line.

When the file is large, reading line by line is a more efficient method, which can be achieved using the lines() iterator.

file, err = io.open(testFilePath, "r")
if file then
print("Read line by line:")
local lineNumber = 1

-- Read line by line until the end of the file
for line in file:lines() do -- using lines() iterators
print("line " .. lineNumber .. ": " .. line)
lineNumber = lineNumber + 1
end

file:close()
else
print("File opening failed: " .. err)
end

4. Append content to the file

The append mode (‘a’) allows new content to be added to the end of a file without overwriting existing content.

-- Open the file for append ('a 'mode: append mode, create if the file does not exist)
file, err = io.open(testFilePath, "a")
if file then
file:write("\nThis is the first line appended\n")
file:write("This is the second line appended\n")
file:close()
print("Content appended successfully")
else
print("File opening failed: " .. err)
end

-- Verify the additional results
print("\nAddited file content:")
file = io.open(testFilePath, "r")
print(file:read("*a"))
file:close()

5. Binary file operations

Binary mode (‘b’) is used to process non-text files and can be used in combination with write or read modes.

-- Write binary data
file, err = io.open("binary_test.dat", "wb") -- 'wb' mode: binary write
if file then
-- Write a string as binary data
file:write("Hello Binary\n")

-- Write numbers (note: Lua does not automatically convert, here it is still written in string form)
for i = 1, 5 do
file:write(i .. "\n")
end

file:close()
print("Binary file successfully written")
end

-- Read binary files
file, err = io.open("binary_test.dat", "rb")
if file then
print("Binary file read:")
print(file:read("*a"))
file:close()
end

6. File copying operation

File copying requires reading the source file in chunks and writing it to the target file, which is especially efficient for large files.

function copyFile(source, destination)
local sourceFile, sourceErr = io.open(source, "rb")
if not sourceFile then
return false, "Failed to open source file: " .. sourceErr
end

local destFile, destErr = io.open(destination, "wb")
if not destFile then
sourceFile:close()
return false, "Target file failed to open: " .. destErr
end

-- Read and write in blocks to avoid large files occupying too much memory
local blockSize = 4096 -- 4KB block
while true do
local data = sourceFile:read(blockSize)
if not data then
break -- file read completed
end
destFile:write(data)
end

-- Close file
sourceFile:close()
destFile:close()

return true
end

-- Execute file copying
local copyFilePath = "test_file_copy.txt"
local success, msg = copyFile(testFilePath, copyFilePath)
if success then
print("File copied successfully: " .. testFilePath .. " -> " .. copyFilePath)

-- Verify replication results
print("\nCopy file contents:")
file = io.open(copyFilePath, "r")
print(file:read("*a"))
file:close()
else
print(msg)
end

7. Obtain file information

Obtaining file information typically requires using the LuaFileSystem (lfs) library, which provides a rich set of file and directory operation functions.

-- Use the LFS library to obtain file information (note: LuaFileSystem library needs to be installed)
print([[Obtaining file information usually requires the use of LuaFileSystem (lfs) library, and the usage method is as follows:

local lfs = require "lfs"

-- Retrieve file properties
local attr = lfs.attributes(testFilePath)
if attr then
print("file size: " .. attr.size .. " Bytes")
print("file type: " .. attr.mode)
print("Creation time: " .. os.date("%Y-%m-%d %H:%M:%S", attr.ctime))
print("Modified time: " .. os.date("%Y-%m-%d %H:%M:%S", attr.mtime))
print("Access time: " .. os.date("%Y-%m-%d %H:%M:%S", attr.atime))
end

-- Check if the file exists
function fileExists(path)
local attr = lfs.attributes(path)
return attr and attr.mode == "file"
end

-- Check if the directory exists
function directoryExists(path)
local attr = lfs.attributes(path)
return attr and attr.mode == "directory"
end
]])

8. Shortcut functions in the io library

Lua’s io library provides some convenient functions to simplify common I/O operations.

-- io.write() directly writes to standard output
print("Use io.write() to output:")
io.write("This is the content written using io.write()\n")
io.write("io.write() can be called multiple times\n")

-- io.read() reads from standard input
print("\nTip: In actual runtime, you can use io.read() to read input from the keyboard, for example:")
print([[print("Please enter your name:")
local name = io.read()
print("Hello," .. name .. "!")
]])

-- io.tmpfile() creates a temporary file
print("\nCreate temporary file demo:")
local tempFile = io.tmpfile()
if tempFile then
tempFile:write("This is temporary file content\n")
tempFile:seek("set") -- Move to the beginning of the file
print("Temporary file content:", tempFile:read("*a"))
tempFile:close() -- Temporary files will be automatically deleted when closed
print("Temporary file closed and automatically deleted")
end

9. File pointer operations

File pointer operations allow reading and writing at specific locations within a file, providing a more flexible way to access files.

file = io.open(testFilePath, "r")
if file then
-- Read the first 10 characters
local first10 = file:read(10)
print("First 10 characters: " .. first10)

-- Get current position
local currentPos = file:seek()
print("current file pointer position: " .. currentPos)

-- Move to the beginning of the file
file:seek("set", 0)
print("Read the first line after moving to the beginning: " .. file:read("*l")) -- "*l" read one line

-- Move to the end of the file
local fileSize = file:seek("end")
print("file size: " .. fileSize .. " Bytes")

-- Move to the middle position of the file
file:seek("set", fileSize / 2)
print("Content read from middle position: " .. file:read("*l"))

file:close()
end

10. Clean up the sample files

It is good practice to clean up the temporary files created after the operation is completed.

-- Delete files using os.remove
local function deleteFile(filePath)
local success, err = os.remove(filePath)
if success then
print("File deleted: " .. filePath)
else
print("File deletion failed: " .. filePath .. " - " .. err)
end
end

deleteFile(testFilePath)
deleteFile(copyFilePath)
deleteFile("binary_test.dat")

11. Summary of File Operations

11.1 File Opening Mode

Write mode ('w '): Create a file or overwrite an existing file
Read mode ('r '): Read existing files
Add mode ('a '): Add content at the end of the file
Binary mode ('b '): used in conjunction with' w 'or' r '
Read write mode ('r+'): Open files for reading and writing

11.2 Best Practices for File Operations

  1. Always close files : After using a file, be sure to call the close() method to close the file to avoid resource leaks.
  2. Error handling : Always check for possible errors when opening and manipulating files.
  3. Large file processing : For large files, use block reading and writing to avoid loading the entire file into memory at once.
  4. Binary files : When processing binary files, use binary mode (‘b’).
  5. File pointer : Use the seek() method for precise file positioning.
  6. Temporary files : Temporary files are created using io.tmpfile() and are automatically cleaned up when the program ends or is explicitly closed.