如何将现有文件中的数据放入 Table
How to Put Data Into a Table From an Existing File
我在 ComputerCraft 中有一个海龟程序,它是一个存储单元。我输入了一个项目,它应该读取一个文件来找到放置该项目的位置。如果有新项目,它会将信息添加到文件中。
当我这样做时
blockTypes = {}
local file = fs.open(blockTable","r")
line = file.readAll()
table.insert(blockTypes,line)
file.close()
信息以字符串形式输入。这意味着我做不到
print(blockTypes[1][1])
并接收通常位于该位置的值。
这是我的代码:
blockAmount = 3
highestVal = {2,0,5}
blockTypes = {}
function addBlock()
local file = fs.open("blockTable", "a")
file.write(name)
file.write(" = {")
file.write(highestVal[1])
file.write(",")
file.write(highestVal[2])
file.write(",")
file.write(highestVal[3])
file.writeLine("};")
file.close()
end
function getBlock()
local file = fs.open("blockTable","r")
line = file.readAll()
table.insert(blockTypes,line)
file.close()
end
--This was used to test before implementing the new file system that I am trying to get to work
blockTypesOld = {
log = {2.0,0,1};
dirt = {2,0,2};
cobblestone = {2,0,3};
iron_ingot = {2,0,4};
planks = {2,0,5};
}
pos = {0,0,0}
looking = 0
function fuel()
if turtle.getFuelLevel() < 20 then
turtle.select(16)
turtle.refuel(1)
end
end
function left()
turtle.turnLeft()
looking = looking - 1
if looking < 0 then
looking = 3
end
end
function right()
turtle.turnRight()
looking = looking + 1
if looking > 3 then
looking = 0
end
end
function forward()
fuel()
if turtle.forward() then
if looking == 0 then
pos[1] = pos[1] - 1
elseif looking == 1 then
pos[3] = pos[3] - 1
elseif looking == 2 then
pos[1] = pos[1] + 1
elseif looking == 3 then
pos[3] = pos[3] + 1
else
end
end
end
function up()
fuel()
turtle.up()
pos[2] = pos[2] + 1
end
function down()
fuel()
turtle.down()
pos[2] = pos[2] - 1
end
function goHome()
while pos[3] > 0 do
while looking > 1 do
left()
end
forward()
end
while pos[2] > 0 do
down()
end
while pos[1] > 0 do
while looking > 0 do
left()
end
forward()
end
end
function goTo(a,b,c)
goHome()
while looking < 2 or looking > 2 do
right()
end
for i = pos[1],a do
forward()
end
while looking > 3 or looking < 3 do
right()
end
for i = pos[3],c do
forward()
end
for i = pos[2],b do
up()
end
while looking < 2 or looking > 2 do
left()
end
end
while true do
turtle.select(15)
while not turtle.suck() do
sleep(1)
end
itemDetails = turtle.getItemDetail()
--Finding what mod item is from and removing corresponding labels--
--EX: "minecraft:log" becomes "log"
if itemDetails.name:match("^ae2stuff:(.+)$") then
name = itemDetails.name:match("^ae2stuff:(.+)$")
elseif itemDetails.name:match("^minecraft:(.+)$") then
name = itemDetails.name:match("^minecraft:(.+)$")
elseif itemDetails.name:match("^appliedenergistics2:(.+)$") then
name = itemDetails.name:match("^appliedenergistics2:(.+)$")
elseif itemDetails.name:match("^buildcraftbuilders:(.+)$") then
name = itemDetails.name:match("^buildcraftbuilders:(.+)$")
elseif itemDetails.name:match("^forge:(.+)$") then
name = itemDetails.name:match("^forge:(.+)$")
elseif itemDetails.name:match("^buildcraftenergy:(.+)$") then
name = itemDetails.name:match("^buildcraftenergy:(.+)$")
elseif itemDetails.name:match("^buildcraftfactory:(.+)$") then
name = itemDetails.name:match("^buildcraftfactory:(.+)$")
elseif itemDetails.name:match("^buildcraftsilicon:(.+)$") then
name = itemDetails.name:match("^buildcraftsilicon:(.+)$")
elseif itemDetails.name:match("^buildcrafttransport:(.+)$") then
name = itemDetails.name:match("^buildcrafttransport:(.+)$")
elseif itemDetails.name:match("^buildcraftcore:(.+)$") then
name = itemDetails.name:match("^buildcraftcore:(.+)$")
elseif itemDetails.name:match("^buildcraftlib:(.+)$") then
name = itemDetails.name:match("^buildcraftlib:(.+)$")
elseif itemDetails.name:match("^computercraft:(.+)$") then
name = itemDetails.name:match("^computercraft:(.+)$")
elseif itemDetails.name:match("^enderstorage:(.+)$") then
name = itemDetails.name:match("^enderstorage:(.+)$")
elseif itemDetails.name:match("^extracells:(.+)$") then
name = itemDetails.name:match("^extracells:(.+)$")
elseif itemDetails.name:match("^thermaldynamics:(.+)$") then
name = itemDetails.name:match("^thermaldynamics:(.+)$")
elseif itemDetails.name:match("^thermalexpansion:(.+)$") then
name = itemDetails.name:match("^thermalexpansion:(.+)$")
elseif itemDetails.name:match("^thermalfoundation:(.+)$") then
name = itemDetails.name:match("^thermalfoundation:(.+)$")
elseif itemDetails.name:match("^tconstruct:(.+)$") then
name = itemDetails.name:match("^tconstruct:(.+)$")
elseif itemDetails.name:match("^webdisplays:(.+)$") then
name = itemDetails.name:match("^webdisplays:(.+)$")
elseif itemDetails.name:match("^ironchest:(.+)$") then
name = itemDetails.name:match("^ironchest:(.+)$")
else
print("ERROR MOD NOT FOUND")
end
getBlock()
local elem = blockTypes[name]
--Gets fuel from fuel chest
right()
turtle.select(16)
turtle.suck(5)
turtle.select(15)
if elem then
--If the item does exist, the turtle goes to it's chest and places it in the chest
goTo(elem[1]-1, elem[2]-1, elem[3]-1)
turtle.select(15)
turtle.drop()
goHome()
right()
turtle.select(16)
turtle.drop()
turtle.select(15)
left()
else
--Creates information for new item--
addBlock()
blockAmount = blockAmount + 1
highestVal[3] = highestVal[3] + 1
if highestVal[3] > 5 then
highestVal[3] = 1
highestVal[2] = highestVal[2] + 1
end
if highestVal[2] > 4 then
highestVal[2] = 0
highestVal[1] = highestVal[1] + 2
end
blockTypes[blockAmount] = name
blockTypes[name] = {highestVal[1],highestVal[2],highestVal[3]}
local elem = blockTypes[name]
left()
turtle.select(15)
turtle.drop()
right()
turtle.select(16)
turtle.suck(2)
fuel()
turtle.drop()
goTo(1,-1,4)
--Crafts an Iron Chest for the New Item
for i = 1,3 do
turtle.select(i)
turtle.suck(1)
end
turtle.select(5)
turtle.suck(1)
turtle.select(7)
turtle.suck(1)
for i = 9,11 do
turtle.select(i)
turtle.suck(1)
end
turtle.select(6)
turtle.craft()
goTo(1,-1,3)
for i = 1,3 do
turtle.select(i)
turtle.suck(1)
end
turtle.select(5)
turtle.suck(1)
turtle.select(7)
turtle.suck(1)
for i = 9,11 do
turtle.select(i)
turtle.suck(1)
end
turtle.select(1)
turtle.craft()
goHome()
right()
turtle.select(16)
turtle.suck(5)
goTo(elem[1]-1, elem[2]-1, elem[3]-1)
turtle.select(1)
turtle.place()
goHome()
end
end
包含项目坐标的文件称为 blockTable,由以下内容组成:
--blockName = {xCoord,yCoord,zCoord};--
oak_stairs = {2.0,0.0,5.0};
iron_ingot = {2.0,0.0,4.0};
turtle = {2.0,0.0,5.0};
当我放入一个新物品时,它会注册该物品,制作一个箱子,然后放入。当我放入相同的物品时,它会直接进入箱子,而无需制作新物品。但是,当我重新启动乌龟并将相同的物品放入其中时,它会创建另一个新箱子并尝试将其放置在新物品中。我希望它即使在重新启动后也能保留其信息。我已经为这个程序苦苦挣扎了一段时间,我们将不胜感激。谢谢!
每次添加新块时读取/写入整个文件似乎有点混乱,特别是如果您考虑到您可能会在写入新文件的过程中重新启动 turtle 并最终丢失一半数据.
您确实有一个文件系统,那么为什么不用它呢?创建一个目录并为每个块名称写入一个新文件,然后将坐标保存在其中。这也允许您为每种块类型存储多个箱子,以防您在使用海龟挖掘地图的大块时比您预期的更早发财。
我刚刚意识到我实际上并没有回答这个问题,所以这里是:
当你有一个文件 file
时,你可以使用 file.readLine()
轻松阅读一行。这 returns 它读取为字符串的行,或者 nil
如果您在文件末尾。假设你只是在块名后面写了三个用空格分隔的坐标,你就可以将它们解析成一个 table 像这样:
local file = fs.open('chests')
local chests = {}
while true do
local line = file.readLine()
if line then
local name, x, y, z = line:match("(%a+) ([%d.+-]+) ([%d.+-]+) ([%d.+-]+)")
chests[name] = {
tonumber(x),
tonumber(y),
tonumber(z)
}
else
break
end
end
将这一切封装在一个函数中以更加整洁。
旁注:
Computercraft处理文件有些不方便。在常规 Lua 中,我会这样做:
local function map(f, elem, ...)
if elem then return f(elem), map(f, ...) end
end
local function readchests(file)
local res = {}
for line in io.open(file):lines() do
local name, x, y, z = line:match("(%a+)"..(" [%d.-+]+"):rep(3))
res[name]={map(tonumber, x, y, z)}
end
return res
end
如果你想保持存储数据的格式为有效的Lua代码,你可以用file.readAll()
读取整个文件,在开头添加"return {"
和"}"
最后加载并执行该字符串。总的来说,我不建议这样做。如果整个文件只是您可以阅读的有效 Lua 代码和 运行.
就更好了
尽管如 DarkWiiPlayer 所述,不建议每次添加到新块时都读取文件。
要回答您的问题,您可以阅读 table 并使用 loadstring
从字符串中执行代码。
要使用您提供的文件中的现有字符串执行此操作,需要做一些额外的工作。
可以通过调整文件中的字符串来删除这些额外的工作。
blockTypes = {}
line = "oak_stairs = {2.0,0.0,5.0};"
table_name = line:match("[%a_]+%s")
do_line = assert(loadstring('local ' .. line .. ' return ' .. table_name))
table = do_line();
table.insert(blockTypes,table)
这里我们使用 match
获取正在加载的 table 的名称。
为 loadstring
创建一个字符串,构建 returns 和 table。
执行加载的字符串,并将其插入到 blockTypes
.
或者,您可以将要保存的文件调整为一个模块。
local blocktypes = {
oak_stairs = {2.0,0.0,5.0},
iron_ingot = {2.0,0.0,4.0},
turtle = {2.0,0.0,5.0},
}
return blockTypes
然后你会这样加载数据:
blockTypes = require("blockTable")
我在 ComputerCraft 中有一个海龟程序,它是一个存储单元。我输入了一个项目,它应该读取一个文件来找到放置该项目的位置。如果有新项目,它会将信息添加到文件中。 当我这样做时
blockTypes = {}
local file = fs.open(blockTable","r")
line = file.readAll()
table.insert(blockTypes,line)
file.close()
信息以字符串形式输入。这意味着我做不到
print(blockTypes[1][1])
并接收通常位于该位置的值。
这是我的代码:
blockAmount = 3
highestVal = {2,0,5}
blockTypes = {}
function addBlock()
local file = fs.open("blockTable", "a")
file.write(name)
file.write(" = {")
file.write(highestVal[1])
file.write(",")
file.write(highestVal[2])
file.write(",")
file.write(highestVal[3])
file.writeLine("};")
file.close()
end
function getBlock()
local file = fs.open("blockTable","r")
line = file.readAll()
table.insert(blockTypes,line)
file.close()
end
--This was used to test before implementing the new file system that I am trying to get to work
blockTypesOld = {
log = {2.0,0,1};
dirt = {2,0,2};
cobblestone = {2,0,3};
iron_ingot = {2,0,4};
planks = {2,0,5};
}
pos = {0,0,0}
looking = 0
function fuel()
if turtle.getFuelLevel() < 20 then
turtle.select(16)
turtle.refuel(1)
end
end
function left()
turtle.turnLeft()
looking = looking - 1
if looking < 0 then
looking = 3
end
end
function right()
turtle.turnRight()
looking = looking + 1
if looking > 3 then
looking = 0
end
end
function forward()
fuel()
if turtle.forward() then
if looking == 0 then
pos[1] = pos[1] - 1
elseif looking == 1 then
pos[3] = pos[3] - 1
elseif looking == 2 then
pos[1] = pos[1] + 1
elseif looking == 3 then
pos[3] = pos[3] + 1
else
end
end
end
function up()
fuel()
turtle.up()
pos[2] = pos[2] + 1
end
function down()
fuel()
turtle.down()
pos[2] = pos[2] - 1
end
function goHome()
while pos[3] > 0 do
while looking > 1 do
left()
end
forward()
end
while pos[2] > 0 do
down()
end
while pos[1] > 0 do
while looking > 0 do
left()
end
forward()
end
end
function goTo(a,b,c)
goHome()
while looking < 2 or looking > 2 do
right()
end
for i = pos[1],a do
forward()
end
while looking > 3 or looking < 3 do
right()
end
for i = pos[3],c do
forward()
end
for i = pos[2],b do
up()
end
while looking < 2 or looking > 2 do
left()
end
end
while true do
turtle.select(15)
while not turtle.suck() do
sleep(1)
end
itemDetails = turtle.getItemDetail()
--Finding what mod item is from and removing corresponding labels--
--EX: "minecraft:log" becomes "log"
if itemDetails.name:match("^ae2stuff:(.+)$") then
name = itemDetails.name:match("^ae2stuff:(.+)$")
elseif itemDetails.name:match("^minecraft:(.+)$") then
name = itemDetails.name:match("^minecraft:(.+)$")
elseif itemDetails.name:match("^appliedenergistics2:(.+)$") then
name = itemDetails.name:match("^appliedenergistics2:(.+)$")
elseif itemDetails.name:match("^buildcraftbuilders:(.+)$") then
name = itemDetails.name:match("^buildcraftbuilders:(.+)$")
elseif itemDetails.name:match("^forge:(.+)$") then
name = itemDetails.name:match("^forge:(.+)$")
elseif itemDetails.name:match("^buildcraftenergy:(.+)$") then
name = itemDetails.name:match("^buildcraftenergy:(.+)$")
elseif itemDetails.name:match("^buildcraftfactory:(.+)$") then
name = itemDetails.name:match("^buildcraftfactory:(.+)$")
elseif itemDetails.name:match("^buildcraftsilicon:(.+)$") then
name = itemDetails.name:match("^buildcraftsilicon:(.+)$")
elseif itemDetails.name:match("^buildcrafttransport:(.+)$") then
name = itemDetails.name:match("^buildcrafttransport:(.+)$")
elseif itemDetails.name:match("^buildcraftcore:(.+)$") then
name = itemDetails.name:match("^buildcraftcore:(.+)$")
elseif itemDetails.name:match("^buildcraftlib:(.+)$") then
name = itemDetails.name:match("^buildcraftlib:(.+)$")
elseif itemDetails.name:match("^computercraft:(.+)$") then
name = itemDetails.name:match("^computercraft:(.+)$")
elseif itemDetails.name:match("^enderstorage:(.+)$") then
name = itemDetails.name:match("^enderstorage:(.+)$")
elseif itemDetails.name:match("^extracells:(.+)$") then
name = itemDetails.name:match("^extracells:(.+)$")
elseif itemDetails.name:match("^thermaldynamics:(.+)$") then
name = itemDetails.name:match("^thermaldynamics:(.+)$")
elseif itemDetails.name:match("^thermalexpansion:(.+)$") then
name = itemDetails.name:match("^thermalexpansion:(.+)$")
elseif itemDetails.name:match("^thermalfoundation:(.+)$") then
name = itemDetails.name:match("^thermalfoundation:(.+)$")
elseif itemDetails.name:match("^tconstruct:(.+)$") then
name = itemDetails.name:match("^tconstruct:(.+)$")
elseif itemDetails.name:match("^webdisplays:(.+)$") then
name = itemDetails.name:match("^webdisplays:(.+)$")
elseif itemDetails.name:match("^ironchest:(.+)$") then
name = itemDetails.name:match("^ironchest:(.+)$")
else
print("ERROR MOD NOT FOUND")
end
getBlock()
local elem = blockTypes[name]
--Gets fuel from fuel chest
right()
turtle.select(16)
turtle.suck(5)
turtle.select(15)
if elem then
--If the item does exist, the turtle goes to it's chest and places it in the chest
goTo(elem[1]-1, elem[2]-1, elem[3]-1)
turtle.select(15)
turtle.drop()
goHome()
right()
turtle.select(16)
turtle.drop()
turtle.select(15)
left()
else
--Creates information for new item--
addBlock()
blockAmount = blockAmount + 1
highestVal[3] = highestVal[3] + 1
if highestVal[3] > 5 then
highestVal[3] = 1
highestVal[2] = highestVal[2] + 1
end
if highestVal[2] > 4 then
highestVal[2] = 0
highestVal[1] = highestVal[1] + 2
end
blockTypes[blockAmount] = name
blockTypes[name] = {highestVal[1],highestVal[2],highestVal[3]}
local elem = blockTypes[name]
left()
turtle.select(15)
turtle.drop()
right()
turtle.select(16)
turtle.suck(2)
fuel()
turtle.drop()
goTo(1,-1,4)
--Crafts an Iron Chest for the New Item
for i = 1,3 do
turtle.select(i)
turtle.suck(1)
end
turtle.select(5)
turtle.suck(1)
turtle.select(7)
turtle.suck(1)
for i = 9,11 do
turtle.select(i)
turtle.suck(1)
end
turtle.select(6)
turtle.craft()
goTo(1,-1,3)
for i = 1,3 do
turtle.select(i)
turtle.suck(1)
end
turtle.select(5)
turtle.suck(1)
turtle.select(7)
turtle.suck(1)
for i = 9,11 do
turtle.select(i)
turtle.suck(1)
end
turtle.select(1)
turtle.craft()
goHome()
right()
turtle.select(16)
turtle.suck(5)
goTo(elem[1]-1, elem[2]-1, elem[3]-1)
turtle.select(1)
turtle.place()
goHome()
end
end
包含项目坐标的文件称为 blockTable,由以下内容组成:
--blockName = {xCoord,yCoord,zCoord};--
oak_stairs = {2.0,0.0,5.0};
iron_ingot = {2.0,0.0,4.0};
turtle = {2.0,0.0,5.0};
当我放入一个新物品时,它会注册该物品,制作一个箱子,然后放入。当我放入相同的物品时,它会直接进入箱子,而无需制作新物品。但是,当我重新启动乌龟并将相同的物品放入其中时,它会创建另一个新箱子并尝试将其放置在新物品中。我希望它即使在重新启动后也能保留其信息。我已经为这个程序苦苦挣扎了一段时间,我们将不胜感激。谢谢!
每次添加新块时读取/写入整个文件似乎有点混乱,特别是如果您考虑到您可能会在写入新文件的过程中重新启动 turtle 并最终丢失一半数据.
您确实有一个文件系统,那么为什么不用它呢?创建一个目录并为每个块名称写入一个新文件,然后将坐标保存在其中。这也允许您为每种块类型存储多个箱子,以防您在使用海龟挖掘地图的大块时比您预期的更早发财。
我刚刚意识到我实际上并没有回答这个问题,所以这里是:
当你有一个文件 file
时,你可以使用 file.readLine()
轻松阅读一行。这 returns 它读取为字符串的行,或者 nil
如果您在文件末尾。假设你只是在块名后面写了三个用空格分隔的坐标,你就可以将它们解析成一个 table 像这样:
local file = fs.open('chests')
local chests = {}
while true do
local line = file.readLine()
if line then
local name, x, y, z = line:match("(%a+) ([%d.+-]+) ([%d.+-]+) ([%d.+-]+)")
chests[name] = {
tonumber(x),
tonumber(y),
tonumber(z)
}
else
break
end
end
将这一切封装在一个函数中以更加整洁。
旁注:
Computercraft处理文件有些不方便。在常规 Lua 中,我会这样做:
local function map(f, elem, ...)
if elem then return f(elem), map(f, ...) end
end
local function readchests(file)
local res = {}
for line in io.open(file):lines() do
local name, x, y, z = line:match("(%a+)"..(" [%d.-+]+"):rep(3))
res[name]={map(tonumber, x, y, z)}
end
return res
end
如果你想保持存储数据的格式为有效的Lua代码,你可以用file.readAll()
读取整个文件,在开头添加"return {"
和"}"
最后加载并执行该字符串。总的来说,我不建议这样做。如果整个文件只是您可以阅读的有效 Lua 代码和 运行.
尽管如 DarkWiiPlayer 所述,不建议每次添加到新块时都读取文件。
要回答您的问题,您可以阅读 table 并使用 loadstring
从字符串中执行代码。
要使用您提供的文件中的现有字符串执行此操作,需要做一些额外的工作。 可以通过调整文件中的字符串来删除这些额外的工作。
blockTypes = {}
line = "oak_stairs = {2.0,0.0,5.0};"
table_name = line:match("[%a_]+%s")
do_line = assert(loadstring('local ' .. line .. ' return ' .. table_name))
table = do_line();
table.insert(blockTypes,table)
这里我们使用 match
获取正在加载的 table 的名称。
为 loadstring
创建一个字符串,构建 returns 和 table。
执行加载的字符串,并将其插入到 blockTypes
.
或者,您可以将要保存的文件调整为一个模块。
local blocktypes = {
oak_stairs = {2.0,0.0,5.0},
iron_ingot = {2.0,0.0,4.0},
turtle = {2.0,0.0,5.0},
}
return blockTypes
然后你会这样加载数据:
blockTypes = require("blockTable")