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

Read and Write a Specific Line

Started by Hayden_Almeida, 24 May 2015 - 09:14 PM
Hayden_Almeida #1
Posted 24 May 2015 - 11:14 PM
Hello guys, i am trying to read and modify a specific line from a file. The line is number 3


   local arq = fs.open("HAsystem/usuario", "r")
   local sContents = arq.readAll() -- capture file in a string
   arq.close()

   tContents = textutils.unserialize(sContents) -- convert string to table

   --modifying a specific line
   table.remove(tContents, 3)
   table.insert(tContents, 3, tentativas)


bla bla bla...

The error comes in the line of

   table.remove(tContents, 3)

ERROR: bad argument: table expected, got nil

The file "usuario" is like this:

Hayden
123123
0  -- This Line i want to change!!!

It would be much easier if we have the function ReadLine or writeLine with parameters: (file [,line] [,"text"])
Edited on 24 May 2015 - 10:40 PM
KingofGamesYami #2
Posted 24 May 2015 - 11:30 PM
If the contents of the file isn't a serialized table, textutils.unserialize will return nil.

I think you want this:

local arq = fs.open("HAsystem/usuario", "r")
local tContents = {}
for line in arq.readLine do
  tContents[ #tContents + 1 ] = line
end
arq.close()
--#remove/insert/modify/whatever

local arq = fs.open("HAsystem/usuario", "w")
for i, v in ipairs( tContents ) do
  arq.writeLine( v )
end

Edit: Fixed a bug in my code. It's been pointed out below, thanks :)/>
Edited on 24 May 2015 - 10:36 PM
Hayden_Almeida #3
Posted 24 May 2015 - 11:38 PM
If the contents of the file isn't a serialized table, textutils.unserialize will return nil.

I think you want this:

local arq = fs.open("HAsystem/usuario", "r")
local tContents = {}
for line in arq.readLine() do
  tContents[ #tContents + 1 ] = line
end
arq.close()
--#remove/insert/modify/whatever

local arq = fs.open("HAsystem/usuario", "w")
for i, v in ipairs( tContents ) do
  arq.writeLine( v )
end

This line:

for line in arq.readLine() do
Gives this error: attempt to call a string
MatthewC529 #4
Posted 24 May 2015 - 11:38 PM
I do not think you understand what Serialization is intended to do. On the surface, Serialization is intended to transform data so that it can be transformed back to it's original form later on (I am admittedly not familiar with ComputerCraft's system). Serialization as used in ComputerCraft (or, as an analog, in Java) is typically not used for File storage, but for RedNet/Internet communication.

Instead you should either open the file for writing and modify it that way or copy the data to tContents, modify and then write it out.

Other systems are typically used for file storage, such as JSON or XML or YAML.
Edited on 24 May 2015 - 09:39 PM
Anavrins #5
Posted 24 May 2015 - 11:43 PM
This line:

for line in arq.readLine() do
Gives this error: attempt to call a string
Remove the brackets after readLine.
MatthewC529 #6
Posted 24 May 2015 - 11:44 PM
– snip –
This line:

for line in arq.readLine() do
Gives this error: attempt to call a string


local arq = fs.open("HAsystem/usuario", "r")
local tContents = {}
local line = arq.readLine()
while line ~= nil do
tContents[#tContents + 1] = line
line = arq.readLine()
end
arq.close()

-- Modify Here

local arq = fs.open("HAsystem/usuario", "w")
for i, v in ipairs( tContents ) do
  arq.writeLine( v )
end

-- Flush and Close file
arq.close()

will work. Or what was said above.
Edited on 24 May 2015 - 09:46 PM
Hayden_Almeida #7
Posted 24 May 2015 - 11:51 PM
– snip –
This line:

for line in arq.readLine() do
Gives this error: attempt to call a string


local arq = fs.open("HAsystem/usuario", "r")
local tContents = {}
local line = arq.readLine()
while line ~= nil do
tContents[#tContents + 1] = line
line = arq.readLine()
end
arq.close()

-- Modify Here

local arq = fs.open("HAsystem/usuario", "w")
for i, v in ipairs( tContents ) do
  arq.writeLine( v )
end

-- Flush and Close file
arq.close()

will work. Or what was said above.

No errors, but dont work.
Because the line 2 was effected (get deleted) and line 3 too.
MatthewC529 #8
Posted 25 May 2015 - 12:08 AM
No errors, but dont work.
Because the line 2 was effected (get deleted) and line 3 too.

What kind of file is usuario? What kind of data is it reading (i.e. what is the format) I ran this test in the Mimic Online Emulator and although I ran into issues with

for line in arq.readLine do

Using what I suggested worked fine.
Hayden_Almeida #9
Posted 25 May 2015 - 12:31 AM
No errors, but dont work.
Because the line 2 was effected (get deleted) and line 3 too.

What kind of file is usuario? What kind of data is it reading (i.e. what is the format) I ran this test in the Mimic Online Emulator and although I ran into issues with

for line in arq.readLine do

Using what I suggested worked fine.

Main Post updated. Look again
Anavrins #10
Posted 25 May 2015 - 12:31 AM
"for line in arq.readLine do" works fine, either you got something wrong or Mimic is broken somehow.

Post the new code that you are trying so we can guide you.
Edited on 24 May 2015 - 10:33 PM
MatthewC529 #11
Posted 25 May 2015 - 12:41 AM
"for line in arq.readLine do" works fine, either you got something wrong or Mimic is broken somehow.

Post the new code that you are trying so we can guide you.

You are correct. My apologies.

Main Post updated. Look again

This code works fine, I recommend working with it:


local arq = fs.open("HAsystem/usuario", "r")
local tContents = {}

for line in arq.readLine do
  tContents[ #tContents + 1 ] = line
end
arq.close()

table.remove(tContents, 3)
table.insert(tContents, 3, "Test")

local arq = fs.open("HAsystem/usuario", "w")
for i, v in ipairs( tContents ) do
  arq.writeLine( v )
end
arq.close()

*Ignore all that stuff, damn emulator*
Edited on 24 May 2015 - 10:52 PM
Bomb Bloke #12
Posted 25 May 2015 - 01:02 AM
No errors, but dont work.
Because the line 2 was effected (get deleted) and line 3 too.

I suspect that has to do with the code you would've had to've added to modify your line. If for whatever reason you're still stuck after Matthew's latest suggestion, post the full code you're stuck with so people can actually point out where the problem is.

Oh, and just for giggles:

local tContents = {}
for line in io.lines("HAsystem/usuario") do tContents[ #tContents + 1 ] = line end
Hayden_Almeida #13
Posted 21 June 2015 - 03:59 AM
"for line in arq.readLine do" works fine, either you got something wrong or Mimic is broken somehow.

Post the new code that you are trying so we can guide you.

You are correct. My apologies.

Main Post updated. Look again

This code works fine, I recommend working with it:


local arq = fs.open("HAsystem/usuario", "r")
local tContents = {}

for line in arq.readLine do
  tContents[ #tContents + 1 ] = line
end
arq.close()

table.remove(tContents, 3)
table.insert(tContents, 3, "Test")

local arq = fs.open("HAsystem/usuario", "w")
for i, v in ipairs( tContents ) do
  arq.writeLine( v )
end
arq.close()

*Ignore all that stuff, damn emulator*

Works Fine.

So how can i read a certain line?
I am trying to use serialize to print a table[] , but unable to perform it.
Bomb Bloke #14
Posted 21 June 2015 - 12:35 PM
So how can i read a certain line?

Keep reading in lines until you get the one you want. The fs API available to ComputerCraft doesn't allow you to skip to a certain part of a file, but even if it did (and to be honest, I'm not entirely sure why seeking is missing), how would it know which bytes contained the ones you wanted, without reading the data beforehand to figure out how many line breaks had occurred?

Forget about serialisation. That has nothing to do with what you're saying you want to do.
Edited on 21 June 2015 - 10:37 AM
Hayden_Almeida #15
Posted 28 August 2015 - 07:59 PM
Last not working.
I try this code:

local arq = fs.open("HAsystem/usuario", "r")
local tContents = {}
for line in arq.readLine do
  tContents[ #tContents + 1 ] = line
end
arq.close()
table.remove(tContents, 3)
table.insert(tContents, 3, "Test")
local arq = fs.open("HAsystem/usuario", "w")
for i, v in ipairs( tContents ) do
  arq.writeLine( v )
end
arq.close()
but the result i got is: All the lines was erased
Exerro #16
Posted 28 August 2015 - 08:13 PM
That should definitely work. Just a small note, rather than the table.*() calls about halfway through, you can just do `tContents[3] = "Test"`.

If it's not working, I'd suggest that the original file was empty. If that were the case, then #tContents would be 0 even though you set the third index (the first and second would need to have something like "" in them for #tContents to be 3). If #tContents is 0, then the ipairs loop won't work, and you'll get an empty file as a result.
Hayden_Almeida #17
Posted 31 August 2015 - 02:26 AM
NOW ITS WORKING!


local arq = fs.open("HAsystem/usuario", "r")
local tContents = {}
for line in arq.readLine do
  tContents[ #tContents + 1 ] = line
end
arq.close()
table.remove(tContents, 3)
table.insert(tContents, 3, "Test")
local arq = fs.open("HAsystem/usuario", "w")
for i, v in ipairs( tContents ) do
  arq.writeLine( v )
end
arq.close()
H4X0RZ #18
Posted 31 August 2015 - 02:07 PM
NOW ITS WORKING!


local arq = fs.open("HAsystem/usuario", "r")
local tContents = {}
for line in arq.readLine do
  tContents[ #tContents + 1 ] = line
end
arq.close()
table.remove(tContents, 3)
table.insert(tContents, 3, "Test")
local arq = fs.open("HAsystem/usuario", "w")
for i, v in ipairs( tContents ) do
  arq.writeLine( v )
end
arq.close()

There's no difference to the code 3 (?) answers above?
Edited on 31 August 2015 - 12:08 PM