0

Hey I'm writing a simple game, where I want to save progress and load it at another point. One one the elements to save is an array. I want to save this array in one single line as an array and also load it again as an array, but it only takes the first element and the following elements overwrite further content

Example (wrong) - Save Data

player_1 = "name"
array = [1, 2, 3]
count = 1000
File.open("game.txt", "w+")  do |file|
  file.puts player_1
  file.puts array
  file.puts count
end

Example (wrong) - Load Data

file_data = File.open("game.txt").readlines.map(&:chomp)

player_1 = file_data[0]
array = file_data[1]
count = file_data[2]

OUTPUT: TEXTFILE

name
1
2
3
1000

So I converted the array to a string and write it in text-file (it works but seems inconvenient)

to save the array

file.puts double_checker.to_s

# Output: String
"[1, 2, 3]"

to load the array (load string from text file, delete special chars, convert it back to array, convert elements to integers)

# Converts String back to Array, digits convert to Integers
double_checker = double_checker.delete(" []").split(",").map { |s| s.to_i }


# Output: Array
[1, 2, 3]

Now my question: Is there a way to store the array directly into to text file (in one line) and read it the same way, so I can store the array straight into a variable?

Or is it only possible to store Strings into a text file?

I'm trying to figure out how I can use write/read to save and load files for example a game progress.

4
  • Make sure you know what tags are before you add them. For example, readfile is a Windows API function to read data from the specified file or input/output (I/O) device, and totally unrelated to what you're doing here. And since you're using the Ruby tag you don't need to put "Ruby" into the question title. Additionally, please avoid conversational parts in questions. See this question's edits for more information. Commented Apr 8, 2020 at 3:24
  • Why do you want to use a Text-File. I thiink it would be easier to use for example a JSON-File or YAML-File. Ruby stdlib supports parsing and dumping/generating out of the box. Commented Apr 8, 2020 at 7:30
  • Btw. in many cases you don't have to call File.open (and String#chomp): File.readlines("game.txt", chomp: true). This automatically also closes the file immediately. Commented Apr 8, 2020 at 11:30
  • From the puts docs: "If called with an array argument, writes each element on a new line." If you want puts to output the whole array in one line, you have to convert it into a single-line string yourself, maybe via join. Commented Apr 8, 2020 at 11:30

1 Answer 1

2

One option would is to use Marshal::dump and Marshal::load.

player_1 = "name"
array = [1, 2, 3]
count = 1000

File.open("game.txt", 'wb') do |f|
  f.write(Marshal.dump([player_1, array, count]))
end
  #=> 28

player_1, array, count = Marshal.load(File.binread("game.txt"))
  #=> ["name", [1, 2, 3], 1000] 

Note that it is not guaranteed that an object serialized using dump with one version of Ruby will be readable with load with a later version of Ruby. On the other hand, Marshal can be used to serialize a wide range of Ruby objects.

"The marshaling library converts collections of Ruby objects into a byte stream", which is why Marshal's serialized objects should be written to and read from binary files.

Another option is to use JSON#generate and JSON#parse.

require 'json'

File.write("game.txt", JSON.generate([player_1, array, count]))
  #=> 21

player_1, array, count = JSON.parse(File.read("game.txt"))
  #=> ["name", [1, 2, 3], 1000]

One can alternatively use JSON::Ext::Generator::GeneratorMethods::Array#to_json to serialize the array:

player_1, array, count].to_json
  #=> "[\"name\",[1,2,3],1000]" 
Sign up to request clarification or add additional context in comments.

1 Comment

Ruby's Marshal isn't text-based storage format, so any I/O stream dealing with marshalled data should be in binary mode: e.g. read -> binread. Otherwise OP might experience saving and loading issues on Windows.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.