This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
lifewcody's profile picture

Put file in table

Started by lifewcody, 19 June 2015 - 03:11 AM
lifewcody #1
Posted 19 June 2015 - 05:11 AM
Hi!

What I am trying to do it have the end goal of:


{
  [ "test" ] = "hi",
  [ "foo" ] = "bar",
}

I have 2 files, file1 and file 2

file1:

  [ "test" ] = "hi",

file2:

  [ "foo" ] = "bar",

The code I have:


local cDir = fs.combine(dir, 'temp')
  local start = "{\n"
  local commandList = fs.list(cDir)
  for k, v in pairs(commandList) do
    local h = fs.open(fs.combine(cDir, v), 'r')
    local contents = h.readAll()
    h.close()
    start = start .. contents
  end
  start = start .. "\n}"
local end = textutils.unserialize(start)

Apparently the above does not want to work for me, so is there any other way to do this?

Thanks
Grim Reaper #2
Posted 19 June 2015 - 05:29 AM
Try something like this:


local tFiles = {} -- tFiles[sName] = sContents

-- Iterate through all files and folders in the directory.
-- NOTE: This only grabs files in the directory; it does not tree.
for _, sName in pairs(fs.list(sDir)) do
	local sPath = sDir .. '/' .. sName

	if not fs.isDir(sPath) then
		-- Read the contents of this file and place it into the files table.
		local tFileHandle = fs.open(sPath, 'r')
		tFiles[sName]	 = tFileHandle.readAll()

		-- Close the handle to prevent i/o issues.
		tFileHandle.close()
	end
end

So, if you have a directory with the files 'foo' and 'bar' in it, then the tFiles table will look like:

tFiles = {
    ["foo"] = "Contents of foo.\nMaybe another line.",
    ["bar"] = "The contents of bar here."
}
Edited on 19 June 2015 - 03:31 AM
lifewcody #3
Posted 19 June 2015 - 05:31 AM
Try something like this:


local tFiles = {} -- tFiles[sName] = sContents

-- Iterate through all files and folders in the directory.
-- NOTE: This only grabs files in the directory; it does not tree.
for _, sName in pairs(fs.list(sDir)) do
	local sPath = sDir .. '/' .. sName

	if not fs.isDir(sPath) then
		-- Read the contents of this file and place it into the files table.
		local tFileHandle = fs.open(sPath, 'r')
		tFiles[sName]	 = tFileHandle.readAll()

		-- Close the handle to prevent i/o issues.
		tFileHandle.close()
	end
end

That makes the file name part of the key and I can't have the file name apart of the key.
valithor #4
Posted 19 June 2015 - 05:33 AM
After testing it it worked perfectly fine for me after I removed the last line since you can't use end as a variable.

Something you should check is make sure the cDir is the actual path to the directory you are using, and that fs.list(cDir) is actually returning a list of files or nil (would be nil if the file path does not point to a directory).

Other than that it worked perfectly fine.
Grim Reaper #5
Posted 19 June 2015 - 05:37 AM
That makes the file name part of the key and I can't have the file name apart of the key.

Would you please clarify what you do want the key to be, then?
valithor #6
Posted 19 June 2015 - 05:40 AM
That makes the file name part of the key and I can't have the file name apart of the key.

Would you please clarify what you do want the key to be, then?

He just wants each thing to be an entry in the table. So if a file had: ["test"] = "hi", then he wants the key to be "test" and the value to be "hi".

The code he posted does exactly what he wants, except for the last line. The only reason it might not do what he wants is if he is looking in the wrong directory with the fs.list.

edit:

@jubba
I suggest printing what cDir is and seeing if that is the correct path.
Edited on 19 June 2015 - 03:41 AM
lifewcody #7
Posted 19 June 2015 - 05:41 AM
After testing it it worked perfectly fine for me after I removed the last line since you can't use end as a variable.

Something you should check is make sure the cDir is the actual path to the directory you are using, and that fs.list(cDir) is actually returning a list of files or nil (would be nil if the file path does not point to a directory).

Other than that it worked perfectly fine.

Whoops, didn't even realize the end variable, I just threw that in, in my code it's 'commands'

I also have it write to a file, here is what it outputs:

{ipm={}}

File it pulls from:


[ "ipm" ] = {
	    [ "install" ] = function(package)
		  print("Going to install " .. package)
	    end,
	    [ "?" ] = function()
		  print("Usage: <install>")
	    end,
	  },
Grim Reaper #8
Posted 19 June 2015 - 05:43 AM
He just wants each thing to be an entry in the table. So if a file had: ["test"] = "hi", then he wants the key to be "test" and the value to be "hi".

Oops, my bad. I understand now, thanks :)/>
lifewcody #9
Posted 19 June 2015 - 05:45 AM
That makes the file name part of the key and I can't have the file name apart of the key.

Would you please clarify what you do want the key to be, then?

He just wants each thing to be an entry in the table. So if a file had: ["test"] = "hi", then he wants the key to be "test" and the value to be "hi".

The code he posted does exactly what he wants, except for the last line. The only reason it might not do what he wants is if he is looking in the wrong directory with the fs.list.

edit:

@jubba
I suggest printing what cDir is and seeing if that is the correct path.

Regarding what you said about printing cDir, it prints: disk/bin (which is where the files are)
valithor #10
Posted 19 June 2015 - 05:57 AM
I also have it write to a file, here is what it outputs:

{ipm={}}

File it pulls from:


[ "ipm" ] = {
		[ "install" ] = function(package)
		  print("Going to install " .. package)
		end,
		[ "?" ] = function()
		  print("Usage: <install>")
		end,
	  },

Using the same code I am unable to replicate this, so it is either mimic (the emulator I am using) or a emulator you are using (if you are using one). Although from seeing what it is converting to a table it should work so I doubt it is the emulator.

Just know you can not actually serialize a function, so it should error instead of writing to a file. If you are in fact using a emulator it might just not be erroring and just removing the values from the table when writing.

There really is nothing wrong with the code. It worked exactly how you said it should work when i tested it.
Edited on 19 June 2015 - 03:57 AM
lifewcody #11
Posted 19 June 2015 - 05:58 AM
I also have it write to a file, here is what it outputs:

{ipm={}}

File it pulls from:


[ "ipm" ] = {
		[ "install" ] = function(package)
		  print("Going to install " .. package)
		end,
		[ "?" ] = function()
		  print("Usage: <install>")
		end,
	  },

Using the same code I am unable to replicate this, so it is either mimic (the emulator I am using) or a emulator you are using (if you are using one). Although from seeing what it is converting to a table it should work so I doubt it is the emulator.

Just know you can not actually serialize a function, so it should error instead of writing to a file. If you are in fact using a emulator it might just not be erroring and just removing the values from the table when writing.

There really is nothing wrong with the code. It worked exactly how you said it should work when i tested it.

I'm actually not using an emulator at all, I'm running the program from in game.
valithor #12
Posted 19 June 2015 - 06:05 AM
That is very weird it might be worth trying the following.

1. Print what you are unserializing before you try to unserialize it.
2. Instead of writing to a file run this code directly after converting to a table.

for k,v in pairs(textutils.unserialize(start)["ipm"]) do
  print(k)
end
This will check if the two keys are actually there.
3. Check to see if the code in game is the same as on the forums. You might have written it slightly different here seeing as you changed at least one of the variable names in moving it over.

Hopefully someone else can find what is causing it to work for me but not for you. I really have no idea seeing there really is nothing wrong with it… lol
lifewcody #13
Posted 19 June 2015 - 06:09 AM
That is very weird it might be worth trying the following.

1. Print what you are unserializing before you try to unserialize it.
2. Instead of writing to a file run this code directly after converting to a table.

for k,v in pairs(textutils.unserialize(start)["ipm"]) do
  print(k)
end
This will check if the two keys are actually there.
3. Check to see if the code in game is the same as on the forums. You might have written it slightly different here seeing as you changed at least one of the variable names in moving it over.

Hopefully someone else can find what is causing it to work for me but not for you. I really have no idea seeing there really is nothing wrong with it… lol

Ran that code you put and got the output:

http://gyazo.com/57ba263beb1157d27d83f0a80e1f8ca6 (They are there)

Also what I am unserializing before I try to:

http://gyazo.com/e700149b35de10889e56f671fad8b0ce
Bomb Bloke #14
Posted 19 June 2015 - 06:11 AM
I'm actually not using an emulator at all, I'm running the program from in game.

It's still true that you can't serialise functions, though. If you want to write a function definition to a file, you can't use a pointer to a defined function in order to do it.
lifewcody #15
Posted 19 June 2015 - 06:12 AM
I'm actually not using an emulator at all, I'm running the program from in game.

It's still true that you can't serialise functions, though. If you want to write a function definition to a file, you can't use a pointer to a defined function in order to do it.

Could you clarify that a bit for me?
valithor #16
Posted 19 June 2015 - 06:15 AM
That is very weird it might be worth trying the following.

1. Print what you are unserializing before you try to unserialize it.
2. Instead of writing to a file run this code directly after converting to a table.

for k,v in pairs(textutils.unserialize(start)["ipm"]) do
  print(k)
end
This will check if the two keys are actually there.
3. Check to see if the code in game is the same as on the forums. You might have written it slightly different here seeing as you changed at least one of the variable names in moving it over.

Hopefully someone else can find what is causing it to work for me but not for you. I really have no idea seeing there really is nothing wrong with it… lol

Ran that code you put and got the output:

http://gyazo.com/57b...d83f0a80e1f8ca6 (They are there)

Also what I am unserializing before I try to:

http://gyazo.com/e70...e56f671fad8b0ce

If they are there then they are just being removed when you try to write them to a file. If you try to call the functions from the table from within a program it will work.

shorter answer:
It works. The way you were checking it just made it appear as if it wasn't.
Edited on 19 June 2015 - 04:16 AM
Bomb Bloke #17
Posted 19 June 2015 - 06:21 AM
Could you clarify that a bit for me?

If you want to write the contents of a table to a file, and that table contains any functions, then it's not going to work.
lifewcody #18
Posted 19 June 2015 - 06:22 AM
Could you clarify that a bit for me?

If you want to write the contents of a table to a file, and that table contains any functions, then it's not going to work.

Okay, is there a way around that or no?
Bomb Bloke #19
Posted 19 June 2015 - 06:25 AM
You could record the string that you originally used to compile the function from, and write that. It'd require a fair bit of string manipulation to gather, though.

Edit:

Say you read in the contents of multiple files, discarding the final } from each of them (and replacing it with a comma if the isn't already one there), with the exception of the last file, where you discard the first { instead. Concatenate all the resulting strings, then write THAT to your output file. This way, the strings are never unserialised, and so the functions they define are never compiled.
Edited on 19 June 2015 - 04:32 AM