---
# System prepended metadata

title: File reading and writing in python
tags: [IB, Computer Science, python]

---

# File reading and writing in python



:::info
This cannot be used with the one compiler for _reasons_
:::

We should use the method open and then close with the path. 

```python!
file = open("testinput.txt")
print(file)

```

output:
![image](https://hackmd.io/_uploads/rJeyydVZbe.png)


We have different modes

r-> read
w -> write
a -> append 
r+ -> read and write. 

If we don't give the input it will be read by default. If we want to change the way we do it, we can use a string as a second parameter.

:::danger
Writing is not the same as appending. If you write a file you're overriding what it was before. 
:::

What if I want to "edit" a file? Usually you read it, you store in a variable and then you write with the appropiate modifications. 


```python!
file = open("testinput.txt", "a")
print(file)
```



```python!
file = open("testinput.txt","a")
file.writelines("\nWe're the crystal gems")
file.close()
```

For making a new line we need to use special characters. The new line is usually `\n` in text fi


```python!

fileData= str(list(range(1,11)))[1:-1]
with open ("testfile.txt", "w") as file:
    file.writelines(fileData)
    file.close()
    
```


```python!
fileData= str(list(range(1,11)))[1:-1].replace(", ", "\n")
with open ("testfile.txt", "w") as file:
    file.writelines(fileData)
    file.close()
```

```python!
myList = list(range(1,11))
string = str(myList)[1:-1]
stringWithLines = string.replace(", ", "\n")
with open ("testfile.txt", "w") as file:
    file.writelines(stringWithLines)
    file.close()
```



#prepare the string
myList = list(range(1,10001))
string = str(myList)[1:-1]
stringWithLines = string.replace(", ", "\n")
#write the file 
with open("testfile.txt", "w") as file:
    file.writelines(stringWithLines)
    file.close()
    
    +
    
```python!
file = open("testinput.txt")
print(file)
for line in file:
    print(line)
    splittedLine = line.split(" ")
    mappedLine = map(float, splittedLine)
    print(mappedLine)
    numbers = list(mappedLine)
    print(numbers)
    numbers = list(map(int, line.split(" ")))
    
```


```python!
file open(patata.txt)

start = True #Flag variable
for line in file:
  if start:
    start = False
    continue
  if (condition):
    #dosomething 
```


```python!
file open(patata.txt)

foundIncludedPlugins = False
plugins = []
for line in file:
  if line == "Included plugins:":
    foundIncludedPlugins = True
  if foundIncludedPlugins and line[0] == " ":
       plugins.append(line)
```       


### Exam exercise the CSV of countries 

:::info
:link: This exercise combines 2D lists that you can look for it here https://hackmd.io/-ylq-DUoTKOS6qGCiq3JRA
:::

I have a CSV downloaded from the Canarian Statistics Institute (From the Canary Islands, Spain) with the names of the countries and their coordinates. The full project needs to create a map. The file has this structure (the grey text is the line number, it’s not part of the file but the number that is nonconsecutive is part of the line) 
![image](https://hackmd.io/_uploads/H10gmIvIZx.png)

 The information required is the name of the country and its coordinates (longitude and latitude). 

A-	Construct in Python an algorithm that reads “data.csv” and creates a 2D list called countries with the following structure: [5] 
![image](https://hackmd.io/_uploads/Sy_G7IDLbe.png)

:::info
This is way easier splitting, to check a similar exercise focus in the split part you can go here: https://hackmd.io/y_afcRmLQcysv05xlSqRuQ#Process-data-from-a-line-in-a-csv-file 
:::

Solution:
:::spoiler

Implementation 1:

```python!
file = open("data.csv") #one mark with the correct opening
countries =  []
for line in file: #one mark with the correct loop
    countries.append([])
    fields = line.split(",") #1 mark for the split
    countries[-1].append(fields[1]) #append the second element
    countries[-1].append(float(fields[3])) #if you miss the casting done with float it's ok
    countries[-1].append(float(fields[4])) #if you miss the casting done with float it's ok
    
```

Implementation 2:


```python!
file = open("data.csv") #one mark with the correct opening
countries =  []
row = 0
for line in file: #one mark with the correct loop
    countries.append([])
    fields = line.split(",") #1 mark for the split
    countries[row].append(fields[1]) #append the second element
    countries[row].append(float(fields[3])) #if you miss the casting done with float it's ok
    countries[row].append(float(fields[4])) #if you miss the casting done with float it's ok
    row = row +1
```

Implementation 3 (forgot how to split):

```python!
file = open("data.csv") #one mark with the correct opening
countries =  []
for line in file: #one mark with the correct loop
    countries.append([])
    fieldIndex = 0
    currentField = ""
    for char in line:
        if char != "," and char != "\n": #\n is the special character for "end of the line" I could give the mark if forgot
            currentField = currentField + char
        else:
            if fieldIndex == 1 or
               fieldIndex == 3 or
               fieldIndex == 4:
                  countries[fieldIndex] = currentField
                  fieldIndex +=1
            fieldIndex = fieldIndex +1
            currentField = ""
```
Another implementation without split and "\n" using index while looping through the line. 

```python!
file = open("data.csv") #one mark with the correct opening
countries =  []
for line in file: #one mark with the correct loop
    countries.append([])
    fieldIndex = 0
    currentField = ""
    for lineIndex in range(len(line)): #lineIndex can be named li or something shorter in an exam
        if line[lineIndex] != "," and lineIndex != len(line)-1: 
            currentField = currentField + char
        else:
            if fieldIndex == 1 or
               fieldIndex == 3 or
               fieldIndex == 4:
                  countries[fieldIndex] = currentField
                  #this implementation doesn't cast the numbers to float
                  fieldIndex +=1
            fieldIndex = fieldIndex +1
            currentField = ""
```

Another inplementation with no split:

```python!
file = open("data.csv") #one mark with the correct opening
countries =  []
for line in file: #one mark with the correct loop
    countries.append([
        line[line.find(",")+1:line.find(",PAISES")],
        line[line.find(",PAISES,")+8:line.rfind(",")],
        line[line.rfind(","):]
    ])
        
```

:::

This exercise continues validating the 2D list here https://hackmd.io/RCQ32fpjS-up6rYC74jPoQ#Validating-country-data