Lua5.4.2常用API整理记录

news2025/5/30 13:27:54

一、基础函数

1.type(value)​​

返回值的类型(如 "nil", "number", "string", "table", "function" 等)。
代码测试:

a = 0
print(type(a))
a = nil
print(type(a))
a = "aaaaaaaa"
print(type(a))
a = {2,3,54}
print(type(a))
a = function() print("hello") end
print(type(a))

 结果:

​​2.tostring(value) / tonumber(value)​​

类型转换:将值转为字符串或数字。
代码测试:

a = "123"
b = tonumber(a)
print("原来的类型为"..type(a).."转换后的类型为"..type(b))
a = 122321312
b = tostring(a)
print("原来的类型为"..type(a).."转换后的类型为"..type(b))

结果:
 

 注:lua输出到控制台乱码时,需要将lua文件的编码格式设置为GBK格式

3.​​assert(condition, message)​​

断言:若条件为假,抛出错误并附带消息。
代码测试:

a = false
assert(a,"这是一个错误消息")

结果:

4.​​rawequal(a, b)​​

严格比较两个值是否相等(忽略元表的 __eq 方法)。
代码测试:

a = 10
b = 10
c = 11
d = "cccc"
print(rawequal(a,b))
print(rawequal(c,a))
print(rawequal(d,a))

结果:

5.rawget​​(table,key)

​​作用​​:直接获取表中指定键的值,(忽略元表的 __index 方法)​。
代码测试:

local t = {}
local mt = {
  __index = function() 
    print("调用 __index 元方法")
    return "默认值"
  end
}
setmetatable(t, mt)

print(t["不存在键"])      --> 输出:"调用 __index 元方法" → "默认值"
print(rawget(t, "不存在键")) --> 输出:nil(直接获取表中的值,不触发元方法)

结果: 

6.rawset​​(table,key,value)​​

作用​​:直接设置表中指定键的值,​​(忽略元表的 __newindex方法)。
代码测试:

local t = {}
local mt = {
  __newindex = function() 
    print("调用 __newindex 元方法,拒绝写入!")
    return -- 阻止写入
  end
}
setmetatable(t, mt)

t["新键"] = 10            --> 输出:"调用 __newindex 元方法,拒绝写入!"
print(t["新键"])          --> 输出:nil

rawset(t, "新键", 10)     --> 绕过 __newindex,直接写入表的底层存储
print(t["新键"])          --> 输出:10

 结果:

7.​​_G​​

全局变量表(直接读写全局变量)
测试代码:

print(_G.myvalue)
_G.myvalue = 1000
print(_G.myvalue)

print("------------------------------------")   

for key, value in pairs(_G) do
  print(key, value)
end

结果:
 

二、字符串处理

1.​​string.sub(s, start, end)​​

截取子字符串(支持负数索引)。
代码测试:

s = "hello world"
print(string.sub(s,1,5))
print(string.sub(s,-3,-1))

结果:

注意:

使用负索引时,开始索引要设置为较小的负索引,结束索引使用较大的负索引

2.string.find(s, pattern)​​

查找匹配模式的子串,返回位置。
代码测试:

s = "hello world"
print(string.find(s,"world"))

结果:

3.string.match(s, pattern)​​

返回第一个匹配模式的子串(支持捕获组)。
代码测试:

s = "hello world"
print(string.match(s,"world1"))
print(string.match(s,"world"))
print(string.match(s,"llo wor"))

结果:

4.​​string.gsub(s, pattern, replace)​​

全局替换匹配的子串(返回新字符串替换次数)。
代码测试:

s = "hello world"
print(string.gsub(s,"ll",2))

结果:

5.string.format(format, ...)​​

格式化字符串(类似 C 的 printf)。
代码测试:

print(math.pi)
print(string.format("PI: %.2f", math.pi))

结果:

三、表操作

1.​​table.insert(t, [pos,] value)​​

插入元素到数组末尾或指定位置。
代码测试:

local t = {1, 2}
table.insert(t, 3)       --> {1, 2, 3}
table.insert(t, 2, 99)   --> {1, 99, 2, 3}

for key, value in pairs(t) do
  print(key, value)
end

结果:

2.table.remove(t, [pos])​​

删除并返回数组末尾或指定位置的元素。
代码测试:

local t = {1, 2, 3}
table.remove(t) --> 3,t 变为 {1, 2}

for key, value in pairs(t) do
  print(key, value)
end

结果: 

3.table.concat(t, [sep], [i], [j])​​

将数组元素连接为字符串(默认分隔符为空)。
代码测试:

local t = {"a", "b", "c"}
print(table.concat(t, "-")) --> "a-b-c"

结果:

4.table.sort(t, [comp_func])​​

对数组排序(可自定义比较函数)。
代码测试:

local t = {3, 1, 4}
table.sort(t) --> {1, 3, 4}
for key, value in pairs(t) do
  print(key, value)
end

结果:

5.​​#t 操作符​​

返回数组的连续部分长度(如果索引不连续则停止)。
代码测试:

local t = {1, 2, [5] = 3,[6] = 4}
print("t len = "..#t) 

local t1 = {1, 2, ["3"] = 3,[7] = 4}
print("t1 len = "..#t1) 

local t2 = {1, 2, nil,3,[6] = 4}
print("t2 len = "..#t2) 

local t3 = {1, 2, nil,nil,4}
print("t3 len = "..#t3) 

local t4 = {["1"] = 1, ["xxx"] = 2, nil,nil,["ccc"] = 4}
print("t4 len = "..#t4) 

local t5 = {["1"] = 1, ["xxx"] = 2, nil,nil,["ccc"] = 4,1,2,3}
print("t5 len = "..#t5) 

local t6 = {["1"] = 1, ["xxx"] = 2, ["ccc"] = 4,1,2,3}
print("t6 len = "..#t6) 

结果:
 

注:如果table中有显示声明为nil的元素还有索引连续的元素,则#t会将显示声明为nil的元素数量也加会到返回的长度中,如果只有显示声明为nil的元素没有索引连续的元素,则#t返回0

四、模块与包管理

1.require(modname)​​

加载模块(优先从 package.loaded 缓存中读取)。
新建一个lua文件
添加代码: 

local M = {}
function M.say_hello()
    print("Hello from mymodule!")
end
return M

测试代码: 

print(require("testlua2"))

结果: 

​​2.package.loaded[modname]

已加载模块的缓存表。
测试代码:

require("testlua2")
print(package.loaded["testlua2"])

结果: 

五、数学库

1.math.floor(x) / math.ceil(x)​​

向下/向上取整。
测试代码:

print(math.floor(3.9)) --> 3
print(math.ceil(3.1))  --> 4

结果:

2.math.random([m [, n]])​​

生成随机数(需先调用 math.randomseed)。
测试代码:

math.randomseed(os.time())
print("生成的随机数为:"math.random(1, 6)) -- 1~6 的随机整数

结果: 

3.math.abs(x) / math.max(x, ...) / math.min(x, ...)​​

绝对值、最大值、最小值。
测试代码:

print(math.abs(-10))
print(math.max(10, 20,-11,20,32))
print(math.min(10, 20,-11,20,32))

结果:
 

​​4.math.pi / math.sin(x) / math.cos(x)​​ / math.tan(x)

数学常量及三角函数。
测试代码:

print(math.pi)
print(math.sin(math.pi/2))
print(math.cos(math.pi/2))
print(math.tan(math.pi/2))

结果:

六、操作系统库

​​1.os.time([table])​​

返回当前时间戳或根据表生成时间戳。
测试代码:

print(os.time())
print(os.time(os.date("*t", os.time())))

结果:

2.​​os.date([format [, time]])​​

格式化时间戳为字符串(如 os.date("%Y-%m-%d"))。
测试代码:

local time_table = os.date("*t", os.time())  -- 返回table格式时间
print(string.format("当前时间: %d年%d月%d日", time_table.year, time_table.month, time_table.day))

​​​​结果:

3.​​os.execute(command)​​

执行系统命令(如 os.execute("ls"))。
测试代码:

--os.execute("sleep 1")  -- Linux/macOS
os.execute("timeout 1")  -- Windows
print("执行完成")

结果:

4.​​os.getenv(varname)​​

获取环境变量。
测试代码:

local path = os.getenv("PATH")
print("系统PATH变量:", path)

结果:

七、文件 I/O

1.io.open(filename, mode)​​

打开文件,返回文件句柄(模式如 "r", "w", "a")。
测试代码:

local file = io.open("data.txt", "r")
print(file)

​​​​结果:

注:
“r”:读取模式(默认);
“w”:写入模式;
“a”:附加模式;
“r+”: 更新模式,保留所有之前的数据;
“w+”:更新模式,之前的所有数据都被擦除;
“a+”:追加更新模式,保留之前的数据, 只允许在 file 末尾写入。

2.​file:read(format)​​

读取文件内容(如 "*a" 读取全部内容)。
新建一个data.txt文本文件,并在其中写入一点文字

测试代码:

local file = io.open("data.txt", "r")

if file then
  local data = file:read("*a")
  print(data)
  file:close()
end

结果:

3.​​file:write(...)​​

写入文件。
测试代码:

io.write("Hello", " ", "World\n")

结果:

4.​​io.stdin / io.stdout / io.stderr​​

标准输入/输出/错误流。
测试代码:

-- 示例:读取一行输入
io.stdout:write("请输入你的名字: ")
io.stdout:flush()  -- 确保提示信息立即显示
local name = io.stdin:read("*l")  -- 读取一行
if #name <= 3 then
    io.stderr:write("错误:名字必须大于3个字符!\n")
    io.stderr:flush()
    return
end
print("你好," .. name)

​​​​​​结果:

八、协程

1.coroutine.create(func)​​

创建协程,返回线程对象。

2.​​coroutine.resume(co, ...)​​

启动或恢复协程。

3.​​coroutine.yield(...)​​

挂起协程,返回参数给 resume。

测试代码:

local co = coroutine.create(function()
    print("Start")
    coroutine.yield("Paused")
    print("End")
end)

coroutine.resume(co) --> 输出 "Start",返回 true, "Paused"
coroutine.resume(co) --> 输出 "End",返回 true

​​​​​​​结果:

九、调试

1.debug.traceback ([thread,] [message [, level]])

获取当前调用栈信息(常用于错误处理)。
测试代码:

function risky_operation()
    error("模拟错误发生")
end

-- 使用pcall包裹可能出错的代码
local success, err = pcall(risky_operation)
if not success then
    print("捕获到错误:", err)
    print("错误堆栈:\n", debug.traceback())
end
-- 输出包含错误信息和堆栈跟踪

​​​​​​​结果:

2.​​debug.getinfo ([thread,] f [, what])

获取函数信息(如源码位置、参数等)。
测试代码:

function funcA()
    funcB()
end

function funcB()
    print("调用堆栈:")
    -- 打印堆栈信息(层级从0开始)
    local level = 2  -- 跳过当前函数和debug.getinfo自身
    while true do
        local info = debug.getinfo(level, "nSl")
        if not info then break end
        print(string.format("层级%d: 函数 %s (文件 %s 第%d行)", 
            level-1, info.name or "匿名", info.short_src, info.currentline))
        level = level + 1
    end
end

funcA()

​​​​​​​结果:

十、元表与元方法

1.setmetatable(t, metatable)​​

为表设置元表。
测试代码:

local t = {}
setmetatable(t, { __index = { default = 42 } })
print(t.default) --> 42(通过元表 __index 获取)

​​​​​​​结果:

2.​​getmetatable(t)​​

获取表的元表。
测试代码:

local t = {}
local mt = { __index = { default = 42 } }
setmetatable(t, mt)
print(getmetatable(t))
print(mt)

​​​​​​​结果:

​​3.__index / __newindex / __call 等元方法​​

Lua元表和元方法的使用_lua元方法有哪些-CSDN博客

十一、迭代器与遍历

1.​​pairs(t)​​

遍历表的键值对(包括非连续键),触发 __pairs 元方法。
测试代码:

local t = {1,2,3,4,["cccc"] = 5 ,nil,5,6,7,8,9,10}

for key, value in pairs(t) do
    print(key, value)
end

结果:
 

2.​​ipairs(t)​​

遍历数组部分的连续整数键(如 t[1], t[2],遇到 nil 停止)。
测试代码:

local t = {1,2,3,4,["cccc"] = 5 ,nil,5,6,7,8,9,10}
for key, value in ipairs(t) do
    print(key, value)
end
print("----------------------")
local t1 = {1,2,3,4,["cccc"] = 5,5,6,7,8,9,10}
for key, value in ipairs(t1) do
    print(key, value)
end

结果:
​​​​​​​

3.​​next(t, [key])​​

直接调用底层迭代函数,返回下一个键值对。
测试代码:

local t = {1,2,3,4,["cccc"] = 5 ,nil,5,6,7,8,9,10}

print(next(t))
print(next(t, 5))
print(next(t, 11))
print(next(t, "cccc"))

结果:

十二、垃圾回收

1.collectgarbage("collect")​​

手动触发一次完整的垃圾回收。
测试例子可看弱表例子。

2.​​collectgarbage("count")​​

返回当前内存占用量(以 KB 为单位)。
测试代码:

t = {["dddd"] = 123,1,2,3}
print(collectgarbage("count")) 

​​​​​​​结果:

3.​​collectgarbage("step")​​

分步执行垃圾回收(适合实时性要求高的场景)。

十三、弱表

1.​​设置元表的 __mode 字段​​

控制表键/值的弱引用(如 {__mode = "k"} 表示键是弱引用)。
测试代码:

local weak_cache = setmetatable({}, { __mode = "v" })
weak_cache["data"] = true -- 当 data 无其他引用时自动清除

for key, value in pairs(weak_cache) do
  print(key, value)
end
print("-----------------------")
weak_cache["data"] = nil -- 手动清除 data

collectgarbage("collect") -- 强制垃圾回收

for key, value in pairs(weak_cache) do
  print(key, value)
end

​​​​​​​结果:

十四、错误处理

1.pcall(func, ...)​​

安全调用函数,返回是否成功及结果/错误消息。
代码测试:

function pcallTest(msg)
    print("错误消息为:"..msg)
end

local ok, result = pcall(pcallTest, "Oops!")
print(ok) 
print(result) 

结果: 

代码测试:

function pcallTest(msg)
    print1("错误消息为:"..msg)
end

local ok, result = pcall(pcallTest, "Oops!")
print(ok) 
print(result) 

结果:

2.xpcall(func, error_handler)​​

类似 pcall,但可指定自定义错误处理函数。
代码测试:

xpcall(function() print("xpcall测试") end, function(err) print("ERROR:", err) end)

结果: 

代码测试: 

xpcall(function() print1("xpcall测试") end, function(err) print("ERROR:", err) end)

结果: 

4.​​error(message)​​

抛出错误。
代码测试:

error("错误消息")

结果: 

十五、二进制数据处理 

1.​位运算​​

&, |, ~, <<, >> 等运算符(需整数类型)
测试代码:

local a = 1 << 3;
local b = 1 << 4;
local c = 1 << 3;
print(a)    
print(b)
print(c)
print("------------------")
print(a & b)
print(a | b)
print(a ~ b)
print("------------------")
print(a & c)
print(a | c)
print(a ~ c)

​​​​​​​结果:

2.​​string.pack(fmt, ...) / string.unpack(fmt, s)​​

打包或解包二进制数据(类似 C 的结构体)。
测试代码:

local packed = string.pack(">i4", 10234593) -- 大端序 4 字节整数
local num, offset = string.unpack(">i4", packed)
print(packed)
print(num) --> 12345
print(offset) --> 5 (跳过了 4 字节整数)

​​​​​​​结果:

十六、常用工具函数

1.select(index, ...)​​

获取可变参数的特定部分(select('#', ...) 返回参数数量)。
测试代码:

local count = select("#", 1, "a", true) --> 3
print(count)
local second = select(2, 1, 2, 3) --> 1
print(second)

​​​​​​​结果:

2.​​load(code) / loadfile(filename)​​

动态加载代码块或文件(返回函数或错误)。

新建一个calc.lua文件

return function(a, b) return a + b end

测试代码:

--加载字符串代码
local code = "return 1 + 2"
local func, err = load(code)
if func then
    local result = func()
    print(result) -- 输出: 3
else
    print("加载失败:", err)
end

-- 加载并执行文件中的代码
local func, err = loadfile("testlua2.lua")
if func then
    local m = func() -- 执行文件代码,返回函数
    print(m.say_hello())   
else
    print("加载失败:", err)
end

-- 加载并执行文件中的代码
local func, err = loadfile("calc.lua")
if func then
    local add = func() -- 执行文件代码,返回函数
    print(add(2, 3))   -- 输出: 5
else
    print("加载失败:", err)
end

​​​​​​​结果:

十七、与C语言交互

在VS2022中使用Lua与c交互(二)_vs2022 lua d-CSDN博客

参考链接:

Lua 5.4 参考手册

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2386121.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Python打卡训练营学习记录Day36

仔细回顾一下神经网络到目前的内容&#xff0c;没跟上进度的同学补一下进度。 作业&#xff1a;对之前的信贷项目&#xff0c;利用神经网络训练下&#xff0c;尝试用到目前的知识点让代码更加规范和美观。 import pandas as pd #用于数据处理和分析&#xff0c;可处理表格数…

什么是智能体agent?

文章目录 什么是智能体agent&#xff1f;最基本的核心思想我们是如何走到今天以及为什么是现在如何从思维上剖析“一个智能体系统”痛苦的教训结论 什么是智能体agent&#xff1f; 原文链接&#xff1a;https://windsurf.com/blog/what-is-an-agent 本文探讨了AI智能体的核心概…

Obsidian 数据可视化深度实践:用 DataviewJS 与 Charts 插件构建智能日报系统

Obsidian 数据可视化深度实践&#xff1a;用 DataviewJS 与 Charts 插件构建智能日报系统 一、核心架构解析 本系统基于 Obsidian 的 DataviewJS 和 Charts 插件&#xff0c;实现日报数据的自动采集、可视化分析及智能回溯功能&#xff08;系统架构原理见&#xff09;。其技术…

6.4.3_有向无环图描述表达式

有向无环图&#xff1a; 有向图中不存在环即为有向无环图DAG图&#xff0c;即如下V0->V4->v3->V0或者V4->V1->v4就存在环不是有向无环图&#xff0c;即在一个路径中一个顶点不能出现2次&#xff1f; DAG描述表达式&#xff1a; 算术表达式用树来表示&#xff0…

【HarmonyOS Next之旅】DevEco Studio使用指南(二十五) -> 端云一体化开发 -> 业务介绍(二)

目录 1 -> 工作原理 2 -> 约束与限制 2.1 -> 支持的设备 2.2 -> 支持的国家/地区 2.3 -> 支持的签名方式 3 -> 总结 3.1 -> 关键功能与工具 3.2 -> 开发流程 3.3 -> 典型场景与优化 3.4 -> 常见问题与解决 3.5 -> 总结 1 -> 工…

Spring Boot AI 之 Chat Client API 使用大全

ChatClient提供了一套流畅的API用于与AI模型交互,同时支持同步和流式两种编程模型。 流畅API包含构建Prompt组成元素的方法,这些Prompt将作为输入传递给AI模型。从API角度来看,Prompt由一系列消息组成,其中包含指导AI模型输出和行为的指令文本。 AI模型主要处理两类消息: …

分身空间:手机分身多开工具,轻松实现多账号登录

分身空间是一款功能强大的手机分身多开工具APP&#xff0c;专为需要同时登录多个账号的用户设计。它支持多开各种游戏和软件&#xff0c;让用户可以轻松实现多账号同时在线&#xff0c;提升使用效率和体验。无论是社交软件、游戏还是办公应用&#xff0c;分身空间都能帮助你轻松…

音视频之视频压缩及数字视频基础概念

系列文章&#xff1a; 1、音视频之视频压缩技术及数字视频综述 一、视频压缩编码技术综述&#xff1a; 1、信息化与视频通信&#xff1a; 什么是信息&#xff1a; 众所周知&#xff0c;人类社会的三大支柱是物质、能量和信息。具体而言&#xff0c;农业现代化的支柱是物质&…

Ubuntu 24.04部署安装Honeyd蜜罐

&#x1f334; 前言 最近有个大作业&#xff0c;里面要求我们部署Hoenyd蜜罐&#xff0c;在网上搜了一通&#xff0c;发现相关的教程竟然少的可怜&#xff0c;即使有比较详细的教程&#xff0c;也是好几年前的了&#xff0c;跟着做一遍报一堆错&#xff0c;无奈之下&#xff0…

MCP技术体系介绍

MCP,全称时Model Context Protocol,模型上下文协议,由Claude母公司Anthropic于2014年11月正式提出。 MCP的核心作用是统一了Agent开发过程中大模型调用外部工具的技术实现流程,从而大幅提高Agent的开发效率。在MCP诞生之前,不同外部工具各有不同的调用方法。 要连接这些…

我的第1个爬虫程序——豆瓣Top250爬虫的详细步骤指南

我的第1个爬虫程序——豆瓣Top250爬虫的详细步骤指南 一、创建隔离开发环境 1. 使用虚拟环境&#xff08;推荐venv&#xff09; # 在项目目录打开终端执行 python -m venv douban_env # 创建虚拟环境 source douban_env/bin/activate # Linux/macOS激活 douban_env\Scri…

Selenium 测试框架 - C#

🚀Selenium C# 自动化测试实战:以百度搜索为例 本文将通过一个简单示例,手把手教你如何使用 Selenium + C# 实现百度搜索自动化测试。适合初学者快速上手,也适合作为企业 UI 自动化测试模板参考。 🧩 一、安装必要 NuGet 包 在 Visual Studio 的 NuGet 管理器中安装以下…

JavaWeb:SpringBoot工作原理详解

一、SpringBoot优点 1.为所有Spring开发者更快的入门 2.开箱即用&#xff0c;提供各种默认配置来简化项目配置 3.内嵌式容器简化Web项目 4.没有冗余代码生成和XML配置的要求 二、SpringBoot 运行原理 2.1. pom.xml spring-boot-dependencies: 核心依赖在父工程中&#xff1b;…

dify_plugin数据库中的表总结

本文使用dify-plugin-daemon v0.1.0版本&#xff0c;主要对dify_plugin数据库中的数据表进行了总结。 一.agent_strategy_installations 源码位置&#xff1a;dify-plugin-daemon\internal\types\models\agent.go type AgentStrategyInstallation struct {ModelTenantID …

HarmonyOS学习——UIAbility组件(上)

UIAbility组件概述 应用程序有几种界面交互形式 UIAbility&#xff1a;应用程序的入口 概述 UIAbility组件是一种包含UI的应用组件&#xff0c;主要用于和用户交互。 UIAbility的设计理念&#xff1a; 原生支持应用组件级的跨端迁移和多端协同。 支持多设备和多窗口形态。…

【Linux】磁盘空间不足

错误提示: no space left on device 经典版&#xff08;block占用&#xff09; 模拟 dd if/dev/zero of/var/log/nginx.log bs1M count2000排查 #1. df -h 查看哪里空间不足,哪个分区#2. du -sh详细查看目录所占空间 du -sh /* 排查占用空间大的目录 du -sh /var/* du…

持续更新 ,GPT-4o 风格提示词案例大全!附使用方式

本文汇集了各类4o风格提示词的精选案例&#xff0c;从基础指令到复杂任务&#xff0c;从创意写作到专业领域&#xff0c;为您提供全方位的参考和灵感。我们将持续更新这份案例集&#xff0c;确保您始终能够获取最新、最有效的提示词技巧。 让我们一起探索如何通过精心设计的提…

QStandardItemModel的函数和信号介绍

前言 Qt版本:6.8.0 QStandardItem函数介绍 函数 部分函数有不同的重载来适应不同的模型,例如appendrow 构造函数与析构函数 1. QStandardItemModel(QObject *parent nullptr) 说明&#xff1a;创建一个空的模型&#xff08;0行0列&#xff09;。参数&#xff1a; parent&…

Python 内存管理机制详解:从分配到回收的全流程剖析

在 Python 编程中&#xff0c;开发者无需像 C/C 那样手动分配和释放内存&#xff0c;但这并不意味着内存管理与我们无关。了解 Python 内存管理机制&#xff0c;能帮助我们编写出更高效、稳定的代码。接下来&#xff0c;我们将深入剖析 Python 内存管理的各个环节&#xff0c;并…

【报错】Error attempting to get column ‘created_time‘ from result set.解决方法

postman报错以下内容 {"code": "500","msg": "查询失败&#xff1a;Error attempting to get column created_time from result set. Cause: java.sql.SQLFeatureNotSupportedException\n; null; nested exception is java.sql.SQLFeatur…