Input Output (IO)
Contents
Input Output (IO)¶
Often one wants to store the results of their program runs. This is done by saving the data to a file or database. We will focus on storing to files.
To acheive this we will use the input output (here after abreviated IO) capabilites of Julia.
You have actually been using a type of output through out the previous modules. Printing to the console is a form of io, e.g. ```println(“hello world”)````
There is a corresponding way to read user input from the console however it doesn’t work in these Jupyter notebook so you need to run it in a regular julia file. Copy and paste the following lines of code into a julia file and run it locally. (Or run module-4-hello-input.jl)
print("Please Tell Me Your Name and Press Enter: ")
a = readline() #This line reads the text from the user in the console after they click the enter key.
println("hello $(a)")
File IO¶
One of the most common type of IO is reading and writing to a file. There are many formats that we can store data on a file. Some common human readable formats:
Plain Txt (.txt extension)
Comma Separated Values (.csv extension)
Javascript Object Notation (.json extension)
We will show examples of reading and writing to all of these.
Writing to Plain Text¶
The first step is to create an object called an IOStream that points to the file we want to write to. Julia provides us the function open() to do this. The function takes two arguments:
The path of the file
a character code signifying what we are going to do with the file
r
read
w
write and overwrite exiting data in the file (truncate)
a
write and append to the end
r+
read, write
w+
read, write, create (a file that doesn’t exist yet), truncate truncate
a+
read, write, create, append
Next to write to the file we use the function write(). The first argument passed to write is our IOStream, the second is the text we want to write.
Finally you must close the IOStream (Otherwise other processes on the computer won’t be able to use it, i.e. you won’t be able to open it).
io = open("hello_output.txt", "w+");
write(io, "Hello File Output")
close(io)
After running the above code you should be able to open the file hello_output.txt and see its contents.
Now lets write other text to it using write and see that the data clears and puts in the new text.
io = open("hello_output.txt", "w+");
write(io, "Different Text \n") #the \n means create a new line after this text
close(io)
Now lets append instead:
io = open("hello_output.txt", "a");
write(io, "A second line of text \n")
close(io)
To make that \n more clear lets do one more append without it and see the result. (You can run this code over and over and it will keep writing on the same line.)
io = open("hello_output.txt", "a");
write(io, "A third line ")
write(io, "of text. ")
close(io)
Reading from Plain Text¶
Now we will read from a text file: hello_file_input.txt. The process is basically the same, but we will use the function readline() instead of write.
io = open("./hello_file_input.txt", "r");
our_input = readline(io) #reads one line from the file
close(io)
println(our_input)
line 1
Text files usually have more than one line, so we want a way to read all of the text. There are two ways of doing this. There are reasons for doing one or the other.
Use the readlines() function which returns all of the lines in an array of strings.
You know you want all the lines, the file is small enough that it doesn’t matter to get them all at once
Loop using the readline() funtion until the read method gives you an end of file message using the eof() function.
You are searching for specific text so you don’t need the whole file and can stop once you’ve found what you want, the file is too large to put into memory all at once, i.e. the file has more data than your computer has RAM ~16 GB.
Loop Read¶
io = open("./hello_file_input_multiline.txt", "r");
while !eof(io) # while the iostream has not reached the end of the file
our_input = readline(io) #reads one line at a timee
println(our_input)
if our_input == "line 4"
break # stop at line 4
end
end
close(io)
line 1
line 2
line 3
line 4
readlines()¶
io = open("./hello_file_input_multiline.txt", "r");
our_input = readlines(io) #reads one line at a timee
for input in our_input
println(input)
end
close(io)
line 1
line 2
line 3
line 4
line 5
Comma Separated Lists¶
Comma separated lists are a convenient way to store tabular data (e.g. tables, matrices, spreadsheets). The following table
——- |
——- |
—— |
——- |
—- |
---|---|---|---|---|
hello |
table |
text |
here |
is |
some |
stuff |
1 |
4 |
3 |
8 |
8 |
8 |
8 |
8 |
would be represented as:
hello,table,text,here,is
some,stuff,1,4,3
8,8,8,8,8
You can see an example file here: example.csv
You can also open this file in Excel. You can also export excel files to csv. Export data to a text file by saving it
You can convert an Excel worksheet to a text file by using the Save As command: Detailed Instructions
Go to File > Save As.
Click Browse.
In the Save As dialog box, under Save as type box, choose the text file format for the worksheet; for example, click Text (Tab delimited) or CSV (Comma delimited).
There is also a vs-code extension to modify CSV files. Name: Edit csv VS Marketplace Link: https://marketplace.visualstudio.com/items?itemName=janisdd.vscode-edit-csv
Reading from CSV¶
Csv files are actually just text files, you don’t have to name them csv for this to work, you could have a text file with comma separated data, so we will read from them and write to them in the same way.
io = open("./example.csv", "r");
our_input = readlines(io) #reads one line at a time
for input in our_input
println(input)
end
close(io)
row1,row2,row3,row4,row5
39.765,61.974,49.116,98.257,39.836
17.807,63.734,77.89,42.989,34.118
60.773,78.374,30.569,81.741,25.595
93.595,80.359,8.917,13.898,63.927
32.753,51.49,21.208,71.139,86.566
40.095,33.315,35.285,64.109,63.314
22.353,56.237,53.043,26.098,66.377
3.748,86.25,43.815,13.613,95.699
86.384,70.958,36.108,34.371,67.863
21.923,96.298,7.348,52.789,53.525
94.17,41.767,84.59,8.32,27.025
56.678,98.974,47.716,8.437,99.16
82.14,38.983,10.205,90.33,11.064
70.442,76.169,43.986,96.74,92.048
51.474,96.682,73.766,61.426,43.427
What if we want to get the values from the csv and use them individually, for example putting them in a matrix and printing the matrix in a nice fasion using the display() function.
readline() and readlines() return a string or an array of strings representing the rows respectively. So we need to take two steps, take each row and split it into individual items and then put them in the correct place in the matrix. For this first example we will assume we know the size of the matrix up front.
io = open("./example.csv", "r");
our_input = readlines(io) #reads one line at a time
csv_values = zeros(15,5)
row = 1
for input in our_input[2:end] # for each skipping the first row (header) row
row_values = split(input, ",")
column = 1
for value in row_values
numerical_value = parse(Float64, value) # convert the string to a Float64
csv_values[row,column] = numerical_value # put it in the matrix
column += 1 # increment our column position in the row
end
row += 1 #now that we have done all of the columns for the row, increment to the next row
end
close(io)
display(csv_values)
15×5 Matrix{Float64}:
39.765 61.974 49.116 98.257 39.836
17.807 63.734 77.89 42.989 34.118
60.773 78.374 30.569 81.741 25.595
93.595 80.359 8.917 13.898 63.927
32.753 51.49 21.208 71.139 86.566
40.095 33.315 35.285 64.109 63.314
22.353 56.237 53.043 26.098 66.377
3.748 86.25 43.815 13.613 95.699
86.384 70.958 36.108 34.371 67.863
21.923 96.298 7.348 52.789 53.525
94.17 41.767 84.59 8.32 27.025
56.678 98.974 47.716 8.437 99.16
82.14 38.983 10.205 90.33 11.064
70.442 76.169 43.986 96.74 92.048
51.474 96.682 73.766 61.426 43.427
I have also attached an example that does not assume it knows the amount of data in the csv. csv_print.jl In it I use the package CSV.jl and DataFrames.jl packages which handles all the CSV parsing for us.
Writing CSV¶
Here is a not very efficient but illustrative way of how to create a csv file
io = open("./write_to_csv.csv", "w+");
data = [1 2 3; 4 5 6; 7 8 9]
for i in 1:3
for j in 1:3
csv_text = "$(data[i,j])"
if j != 3 #don't use comma if there
csv_text = csv_text * "," #concatenates the strings
end
write(io, csv_text)
end
write(io, "\n") # add new line
end
close(io)
Again the better way to do this is using CSV.jl
using Tables, CSV
io = open("./write_to_csv_with_package.csv", "w+");
data = [1 2 3; 4 5 6; 7 8 9]
table = Tables.table(data)
CSV.write(io, table)
close(io)
JSON (Javascript Object Notation)¶
JSON is a way of storing “object” data in a file that is human readable. Each property is denoted by a “NAME_OF_PROPERTY” then a : then the value for that property. Properties can be lists. The items which are comma separated and surrounded by []. You can read and write to JSON files using the JSON.jl package.
A simple example of a javascript object for a simple struct:
mutable struct Bike
weight :: Float64
make :: String
x_position :: Int
y_position :: Int
end
{
"weight" : 10.39,
"make" : "Trek",
"x_position" : 10,
"y_position" : -2
}
Here is a more complex example that is an export of the bike simulation, with arrays of data.
{
"bikes": [
{
"bike_attributes": {
"make": "Make1",
"model": "Model1",
"weight": 15.04,
"drag_coefficient": 0.746
},
"x_position": 0,
"y_position": 3
},
{
"bike_attributes": {
"make": "Make1",
"model": "Model1",
"weight": 19.4,
"drag_coefficient": 0.597
},
"x_position": 2,
"y_position": 99
}
],
"current_time": 5,
"timed_bike_positions": [
[
[1, 1, 1, 0],
[1, 1, 2, 3]
],
[
[1, 2, 1, 2],
[100, 99, 99, 99]
]
],
"simulation_run_time": 4
}
Note: The above JSON has been “pretty printed” so it is easier to read. The white spacing and multiple lines are not strictly necessary.
JSON parse method will return what is called a Dictionary. It is an object that has the ability to look up items in it by name using the following syntax:
my_dict = Dict()
my_dict["value"] = "hello"
my_dict["some_other_property"] = 1.23
println(my_dict["value"])
println(my_dict["some_other_property"])
hello
1.23
JSON Example Code¶
using JSON
mutable struct Bike
weight :: Float64
make :: String
x_position :: Int
y_position :: Int
end
our_json_object = JSON.parsefile("simulation_example.json")
display("all bikes")
display(our_json_object["bikes"])
display("bike 1 x position")
display(our_json_object["bikes"][1]["x_position"])
bike = Bike(10, "TREK", 3, -3)
io = open("example_json_output.json", "w+")
JSON.print(io, bike)
close(io)
"all bikes"
2-element Vector{Any}:
Dict{String, Any}("y_position" => 3, "bike_attributes" => Dict{String, Any}("make" => "Make1", "weight" => 15.04, "model" => "Model1", "drag_coefficient" => 0.746), "x_position" => 0)
Dict{String, Any}("y_position" => 99, "bike_attributes" => Dict{String, Any}("make" => "Make1", "weight" => 19.4, "model" => "Model1", "drag_coefficient" => 0.597), "x_position" => 2)
"bike 1 x position"
0
Exercises¶
Main Exercise¶
Create your own program. You can do anything you want as long as it fulfils of the following criteria.
Required:
A written problem description of what the code does and how it fulfils the requirements (1-2 paragraphs)
Can take in multiple inputs and give correct different outputs
Do some sort of math
Multiple Functions (use guidance in previous modules on separation of concerns)
Unit test(s) proving that it does what is supposed to (doesn’t have to unit test the whole thing but tests your function)
2/3 of your choice
Reads from a file/writes to a file
Matrix algebra
Models some data using object oriented concepts
Some suggestions for inspiration:
Find a text book problem and create something that can solve any problem of the same type with any input
Create a Tick-Tac-Toe / Rock Paper Scissors game to play against the computer and keep track of scores over time
Use your imagination, it can be as creative (or as trivial) as you like. I just want you to get some experience starting from just an idea and turning it into code. This exercise is likely to be the most challenging one of the whole course and may take more time than the others. If you need help, please reach out!
Preparation for Final Module¶
Watch the Video for the final project and make sure you can run it in Google Collab.