Jump to content




"human-readable" textutils.serialize not easy to unserialize


  • You cannot reply to this topic
9 replies to this topic

#1 Bab

  • Members
  • 61 posts

Posted 01 January 2015 - 08:19 PM

I've been away from the forums and CC for a while, but back when I used it textutils used the old format, which meant you could serialize a table to a file and later just read the single line and unserialize it. However, this doesn't work anymore due to the new human-readable format which makes the previously one line table take up multiple lines. How would I easily go about reading a table from a file full of other variables?

#2 wieselkatze

  • Members
  • 221 posts
  • LocationGermany

Posted 01 January 2015 - 09:11 PM

That's as easy as using readLine().
If you look here you see that there is a f.readAll(). This reads the whole file and concatenates all lines together with \n as the separator.

You could just use this:

local f = fs.open( yourfile, "r" )
local content = textutils.unserialize( f.readAll() )
f.close()

an content would be your unserialized table.

#3 Bab

  • Members
  • 61 posts

Posted 01 January 2015 - 09:50 PM

The problem with that, however is that beside that table I also have other variables saved in the file. So beside a positional table I also have variables for the amount of blocks mined, in the same file. This was very convenient with the old textutils.

#4 wieselkatze

  • Members
  • 221 posts
  • LocationGermany

Posted 01 January 2015 - 09:58 PM

How exactly does your file look like? As textutils.unserialize() only uses loadstring(), you could actually pretty easily write your own function for loading all the variables and then accessing them via creating an own environment for them - kinda like os.loadAPI().

#5 Bab

  • Members
  • 61 posts

Posted 01 January 2015 - 10:08 PM

In this case, the file is
-1082.0
49.0
1601.0
20.0
1000.0
20.0
{
  dir = 1,
  z = 1601,
  y = 50,
  x = -1082,
}
{
  dir = 2,
  z = 1601
  y = 50,
  x= -1082,
}


#6 wieselkatze

  • Members
  • 221 posts
  • LocationGermany

Posted 01 January 2015 - 10:35 PM

Okay, if you wrote the variable names in front of the values, you could definitely use loadstring().
Like this:
a = -1082.0
b = 49.0
...

You could then make a function like this:
local function loadFile( path )
  if fs.exists( path ) then
	local f = fs.open( path, "r" )
	  if f then
		local content, env = f.readAll(), {}
		local func, err = loadstring( content )
		
		if err then
		  error( err )
		end
		
		setfenv( func, env )
		func()
		
		return env
	  end
  end
end

This would be a 'smaller' version of os.loadAPI. As the global functions are not needed there is no need for setting _G as __index in env's metatable. Also there is nor checking if the API is actually loaded - we wouldn't have to do that as this isn't an API anyway.

You could then use the function to get a table with all the variables you need and use them like this:
local a = loadFile( "yourpath/something" )
print( a.a ) --# Or whatever you named your variable

EDIT: The indendation got somewhat messy, meh.

Edited by wieselkatze, 01 January 2015 - 10:38 PM.


#7 Bab

  • Members
  • 61 posts

Posted 01 January 2015 - 10:48 PM

It's not so much that I don't know how to get it working, it's just a lot more effort for something that used to be simple and intuitive. I save the file with f.writeLine(textutils.serialize(variable)) and read it with textutils.unserialize(f.readLine()), but now I need to save the parts individually, or do something like you did which is a really roundabout way for it.

#8 MKlegoman357

  • Members
  • 1,170 posts
  • LocationKaunas, Lithuania

Posted 01 January 2015 - 11:13 PM

local oneLineSerializedTable = textutils.serialize({test = 1}):gsub("\n", "")


#9 Bab

  • Members
  • 61 posts

Posted 01 January 2015 - 11:33 PM

Now that's a nice, simple, hackish solution. Thanks, both of you!

Edited by Bab, 01 January 2015 - 11:34 PM.


#10 wieselkatze

  • Members
  • 221 posts
  • LocationGermany

Posted 02 January 2015 - 12:53 AM

View PostMKlegoman357, on 01 January 2015 - 11:13 PM, said:

local oneLineSerializedTable = textutils.serialize({test = 1}):gsub("\n", "")

Wow, didn't think of that :D





1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users