io.open() not working (returning nil) [Lua] Topic is solved

This forum can be used to talk about general design strategies, new ideas and questions in general related to wxWidgets. If you feel your questions doesn't fit anywhere, put it here.
Post Reply
User avatar
DoctorDavid
In need of some credit
In need of some credit
Posts: 6
Joined: Mon Nov 21, 2016 6:43 pm

io.open() not working (returning nil) [Lua]

Post by DoctorDavid » Mon Nov 21, 2016 7:31 pm

Hello, guys! I'm currently programming an IRC client in Lua using the wxLua library. At the moment I'm working on the server and user saving. And that's where the problem is: My IO writing doesn't work. On my understanding, it can't open the file (which it only will if the file isn't existing, hence the os.rename(file, file), which returns true if it was successful, else false.), hence it can't write stuff, though I have no idea why it does that. To be honest, it's quite late here and my brain is half asleep, but I was already trying to fix that problem this afternoon, so don't blame my brain please :lol:
Beware... Quite a lot of code!

Code: Select all

--Create a frame to show thing on
frame = wx.wxFrame(wx.NULL, wx.wxID_ANY, "IRC Client",
                   wx.wxDefaultPosition, wx.wxSize(600, 500),
                   wx.wxDEFAULT_FRAME_STYLE)

newframe = wx.wxFrame(wx.NULL, wx.wxID_ANY, "New Connection",
                   wx.wxDefaultPosition, wx.wxSize(300, 200),
                   wx.wxMINIMIZE_BOX + wx.wxRESIZE_BORDER + wx.wxSYSTEM_MENU + wx.wxCAPTION + wx.wxCLOSE_BOX + wx.wxCLIP_CHILDREN)

explode = function(string)
    local success = false
    local rand = 0
    local file = nil
    local returnval = {}
    while not success do
        rand = math.random(1, 1000)
        if not os.rename(tostring(rand), tostring(rand)) then
            local file = io.open(tostring(rand), "w")
            file:write(string)
            file:close()
            file = io.open(tostring(rand), "r")
            for i = 1, #string do
                returnval[#returnval+1] = file:read(1)
            end
            success = true
        end
    end
    return returnval
end

tohex = function(IN)
    local B,K,OUT,I,D=16,"0123456789ABCDEF","",0
    while IN>0 do
        I=I+1
        IN,D=math.floor(IN/B),IN%B+1
        OUT=string.sub(K,D,D)..OUT
    end
    return OUT
end

stringtohex = function(string)
    local hex = ""
    explodedstring = explode(string)
    for i = 1, #string do
        hex = hex..tohex(string.byte(explodedstring[i]))
    end
    return hex
end

local idcounter = wx.wxID_HIGHEST + 1
newid = function()
    idcounter = idcounter + 1
    return idcounter
end

--Little helper function to make writing servers easier
getServerHex = function(servers)
    local string = ""
    for var, val in pairs(servers) do
        string = string..stringtohex(tostring(#val)..val)
    end
    return string
end

---------------------------------------------------------------------
---------------------------------------------------------------------
--Info function to fetch misc data
infos = {}
infos.getServerList = function()
    if not os.rename("internal/saves/serverlist.tirc", "internal/saves/serverlist.tirc") then
        io.open("internal/saves/serverlist.tirc", "w"):write(getServerHex{"irc.freenode.net", "irc.esper.net"})
        return {"irc.freenode.net", "irc.esper.net"}
    else
        local list = io.open("internal/saves/serverlist.tirc", "r")
        if not io.read(0) then --if file is empty
            list:close()
            return {}
        else
            local serverlist = {}
            local length = 0x00
            local x = 1
            while io.read(0) do
                length = tonumber(list:read(2), 16)
                serverlist[x] = list:read(length)
                x = x + 1
            end
            list:close()
            return serverlist
        end
    end
end
------------------------------------------------------
------------------------------------------------------

infos.addServer = function(server)
    if not os.rename("internal/saves/serverlist.tirc", "internal/saves/serverlist.tirc") then
        io.open("internal/saves/serverlist.tirc", "a+"):close()
        return {}
    else
        io.open("internal/saves/serverlist.tirc", "w"):write(stringtohex(tostring(#server..server)))
    end
end

infos.getLastUsername = function()
    if not os.rename("internal/saves/55534552.tirc", "internal/saves/55534552.tirc") then
        local user = io.open("internal/saves/serverlist.tirc", "a+")
        user:close()
        return ""
    else
        local user = io.open("internal/saves/serverlist.tirc", "r")
        local username = user:read(tonumber(user:read(2), 16))
        user:close()
        return username
    end
end

--INSECURE!!!!!!!!!!! %[email protected]%ing make a secure function already ._.
infos.getLastPassword = function()
    if not os.rename("internal/saves/55534552.tirc", "internal/saves/55534552.tirc") then
        local user = io.open("internal/saves/serverlist.tirc", "a+")
        user:close()
        return ""
    else
        local user = io.open("internal/saves/serverlist.tirc", "r")
        local junk = user:read(tonumber(user:read(2), 16)) --The junk is basically the username(Only the pass is needed)
        local pass = user:read(tonumber(user:read(2), 16))
        user:close()
        return pass
    end
end

--Connection tab
local connections = wx.wxMenu()
local new = newid()
local reconnect = newid()
local close = newid()
local connectionmanager = newid()
connections:Append(new, "&New Connection", "Open a new connection.")
connections:Append(reconnect, "&Reconnect", "Reconnect to the server")
connections:Append(close, "&Close Connection")
connections:Append(connectionmanager, "Connection &Manager", "Open the connection manager.")

--Window tab
local window = wx.wxMenu()
local startoptions = newid()

--Create a menu bar
local menu = wx.wxMenuBar()
menu:Append(connections, "&Connections")
frame:SetMenuBar(menu)

--New connection window setup
local server = wx.wxTextCtrl(newframe, wx.wxID_ANY, "", wx.wxPoint(0, 0), wx.wxSize(300, 20))
local serverlist = wx.wxListBox(newframe, wx.wxID_ANY, wx.wxPoint(0, 20), wx.wxSize(300, 100), infos.getServerList())
local userlabel = wx.wxStaticText(newframe, wx.wxID_ANY, "Username:", wx.wxPoint(0, 120))
local username = wx.wxTextCtrl(newframe, wx.wxID_ANY, infos.getLastUsername(), wx.wxPoint(0, 133), wx.wxSize(140, 20))
local passlabel = wx.wxStaticText(newframe, wx.wxID_ANY, "Password:", wx.wxPoint(144, 120))
local password = wx.wxTextCtrl(newframe, wx.wxID_ANY, infos.getLastPassword(), wx.wxPoint(144, 133), wx.wxSize(140, 20))

--Events for the menu bar
--Events: Connection tab
frame:Connect(new, wx.wxEVT_COMMAND_MENU_SELECTED,
    function(event)
        newframe:Show(true)
    end )

--Events: New Connection
newframe:Connect(wx.wxID_ANY, wx.wxEVT_COMMAND_LISTBOX_SELECTED, function(event)
    server:SetValue(event:GetString())
    
end)

frame:Show(true)
The part marked with the "------"s is the part which is errored. If you want I can upload it to GitHub for better readability or whatever.
And here's the beautiful error message!

Code: Select all

Error: Lua: Error while running chunk
[string "Client.lua"]:69: attempt to index a nil value
stack traceback:
	[string "Client.lua"]:69: in function 'getServerList'
	[string "Client.lua"]:150: in main chunk

End lua script : Mon Nov 21 19:27:50 2016
Execution time : 0.047(s)
Probably it's just some very straightforward problem that I missed, but I'm really puzzled right now. The file isn't created, neither is the directory tree or whatever. (And just in case you wonder why I do everything in hex, it's basically just to make it not as easy to edit!) I know my coding habits are really bad and that this code could be optimised a lot, but to be honest with you: I don't need optimised code. :D It's not going to be a huge public thing to release and stuff, more for personal use. So please only tell me changes if it actually contributes to the problem! (Except if it's really really bad code... I know, I'm bad :lol:)
Oh, by the way: I'm using wxLuaEdit as editor. (just in case the logs differ!)

User avatar
DoctorDavid
In need of some credit
In need of some credit
Posts: 6
Joined: Mon Nov 21, 2016 6:43 pm

Re: io.open() not working (returning nil) [Lua]

Post by DoctorDavid » Mon Nov 21, 2016 8:00 pm

Oops, I forgot something! :lol: I'm running on Windows 8.1, wxLua 2.8.12.3 and Lua 5.2!

User avatar
doublemax
Moderator
Moderator
Posts: 13992
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: io.open() not working (returning nil) [Lua]

Post by doublemax » Mon Nov 21, 2016 8:43 pm

This sample seems unnecessarily complicated. Have you tried with simple, hardcoded filenames first?

In which directory are you trying to create a file? You don't have write access everywhere under Windows.
Last edited by doublemax on Tue Nov 22, 2016 3:22 pm, edited 1 time in total.
Reason: typo
Use the source, Luke!

User avatar
DoctorDavid
In need of some credit
In need of some credit
Posts: 6
Joined: Mon Nov 21, 2016 6:43 pm

Re: io.open() not working (returning nil) [Lua]

Post by DoctorDavid » Tue Nov 22, 2016 2:26 pm

That's actually a good point, although I'm in my Desktop Programming folder (with quite a large dir tree in that said folder) C:\Users\David\Desktop\Programmieren\Lua\wxLua\bin\wxLuaEdit.exe <- That is the path to the wxLuaEdit.exe (Like I said, desktop, so I should have writing permissions) and at \Lua\IRC Client\Client.lua lies the source. (Note that it runs everything relative to the .exe rather than to the source!) I tried to run it with admin permissions, and the same result. It can't index nil. (I tried those writing modes: "w", "w+", "a+", those create new files. "r", "r+" and "a" don't make sense because either they won't let me write or they don't create new files.) Also, it's a new day and I looked at the code again, and I can't find anything, even when I'm not tired. (Which is a paradox by itself :lol: )

ONEEYEMAN
Part Of The Furniture
Part Of The Furniture
Posts: 3409
Joined: Sat Apr 16, 2005 7:22 am
Location: USA, Ukraine

Re: io.open() not working (returning nil) [Lua]

Post by ONEEYEMAN » Tue Nov 22, 2016 2:51 pm

Hi,
Did you try to create a new file/folder in that directory with Windows Explorer?

Thank you.

User avatar
doublemax
Moderator
Moderator
Posts: 13992
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: io.open() not working (returning nil) [Lua]

Post by doublemax » Tue Nov 22, 2016 3:27 pm

Print out the filename, maybe it's invalid.

Maybe the directory used is not the one you think. Try with a hardcoded absolute path for a test. If that works use wxStandardPaths() to build a proper, absolute path.
Use the source, Luke!

User avatar
DoctorDavid
In need of some credit
In need of some credit
Posts: 6
Joined: Mon Nov 21, 2016 6:43 pm

Re: io.open() not working (returning nil) [Lua]

Post by DoctorDavid » Tue Nov 22, 2016 7:59 pm

Exactly the same error message. Hardcoded and relative paths apparently aren't the problem. :cry:

User avatar
doublemax
Moderator
Moderator
Posts: 13992
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: io.open() not working (returning nil) [Lua]

Post by doublemax » Tue Nov 22, 2016 9:08 pm

Did you check the wxLua samples? There should be some file operations somewhere.

I don't know much about lua, but i just found this:
https://www.lua.org/pil/21.2.html

Apparently io.open returns an error message. Which one do you get?
Use the source, Luke!

User avatar
DoctorDavid
In need of some credit
In need of some credit
Posts: 6
Joined: Mon Nov 21, 2016 6:43 pm

Re: io.open() not working (returning nil) [Lua]

Post by DoctorDavid » Wed Nov 23, 2016 5:10 pm

Well, I didn't know of that feature... It's handy! :lol: "No such file or directory" And then I realized: I didn't have those folders set up. So what I'm going to do is make an "installer" kinda thing that creates those things automatically. In order to open those things, you need to have these folders. They won't be created by themselves!! But thanks anyway, that saved my life <3

EDIT:
What I forgot to mention was this: You can use lfs to create folders for you (You can install it via LuaRocks)

Code: Select all

local lfs = require("lfs")
and to actually make a directory:

Code: Select all

lfs.mkdir("foo")
lfs.mkdir("foo/bar")
lfs.mkdir("foo/bar/lol")
lfs.mkdir("foo/baz")
I tested things around and it appears you can't just do

Code: Select all

lfs.mkdir("foo/bar")
and you're set, you actually need to make every folder separately. (Note that you need to specify the parent folder like in my example, so the tree would be
foo
|--bar
|----lol
|--baz
Don't forget that!

Post Reply