---
engine: julia
---

```{julia}
#| error: false
#| echo: false
#| output: false
using InteractiveUtils
```

# Ein- und Ausgabe



zahlreiche Varianten und Funktionen, das Folgende ist eine kleine Auswahl

## Konsole

- OS-abhängig; üblicherweise 3 Kanäle _(streams)_: `stdin, stdout, stderr`  (Standardinput, -output, -errorkanal)



- Schreiben nach `stdout`: `print()`,`println()`,`printstyled()`
- Schreiben nach `stderr`:  `print(strerr,...)`, `println(stderr,...)`, `printstyled(stderr,...)`
- Lesen von `stdin`: `readline()`

### Umwandeln von Strings in andere Typen:
  
  - `chomp()` entfernt newline
  - `split()` zerlegt in "Wörter" 
  - `parse()` wandelt in andere Typen um

### Buffer

- `write`-Zugriffe werden gebuffert.
  
  - `flush(stdout)`   leert Buffer


```{julia}

function input(prompt = "Eingabe:")
    println(prompt)
    flush(stdout)
    return chomp(readline())
end

```

```{julia}
#| eval: false
a = input("Bitte 2 Zahlen eingeben!")
```


```{julia}
#| echo: false
a = "34 56"
```

```{julia}
av = split(a)
```


```{julia}
parse.(Int, av)
```


```{julia}
# Ausgaben auf den Fehlerkanal stderr erscheinen im Jupyter in rot:
@warn "Das @warn-Macro schreibt nach stderr."
println("Hallo!")
println(stderr, "Das sollte nicht passieren!")    
```

### Einzelne Tastenanschläge einlesen

- `readline()` u.ä. warten auf den Abschluss der Eingabe durch Drücken der `Enter`-Taste. 
- Zum Einlesen einzelner _keystrokes_:
  
  - [https://stackoverflow.com/questions/56888266/how-to-read-keyboard-inputs-at-every-keystroke-in-julia](https://stackoverflow.com/questions/56888266/how-to-read-keyboard-inputs-at-every-keystroke-in-julia)
  - [https://stackoverflow.com/questions/60954235/how-can-i-test-whether-stdin-has-input-available-in-julia](https://stackoverflow.com/questions/60954235/how-can-i-test-whether-stdin-has-input-available-in-julia)
  

## Formatierte Ausgabe mit dem `Printf`-Paket

Die Macros `@sprintf` und `@printf` sind den gleichnamigen C-Funktionen nachempfunden

- Formatstring: Normaler String mit Platzhaltern
- Platzhalter haben die Form 
```
%[flags][width][.precision]type
```
   (wobei die Angaben in eckigen Klammern alle optional sind)
- Typen: 
```
%s      string
%i      integer
%o      integer octal (base=8)
%x, %X  integer hexadecimal (base=16) with digits 0-9abcdef  or 0-9ABCDEF, resp.
%f      floatong point number
%e      floating point number, scientific representation
%g      floating point, uses %f or %e depending on value
```

- Flags:
```
Pluszeichen:    rechtsbündig (Standard)
Minuszeichen:   linksbündig
Null:           mit führenden Nullen
```

- Width: 
```
Anzahl der minimal verwendeten Zeichen (wenn nötig, werden auch mehr genommen)
```


Zeit für Beispiele:


```{julia}
using Printf    # Paket laden nicht vergessen!
```


```{julia}
@printf("|%s|", "Hallo")     # string mit Platzhalter für String
```


```{julia}
@printf("|%10s|", "Hallo")   # Minimallänge, rechtsbündig    
```


```{julia}
@printf("|%-10s|", "Hallo")     # linksbündig
```


```{julia}
@printf("|%3s|", "Hallo")     # Längenangabe kann überschritten werden 
                              # besser eine 'kaputt formatierte' Tabelle als falsche Werte!!
```


```{julia}
j = 123
k = 90019001
l = 3342678

@printf("j= %012i, k= %-12i, l = %12i", j, k, l)   #  0-Flag für führende Nullen
```

`@printf` und `@sprintf` können wie alle Macros wie Funktionen aufgerufen werden:


```{julia}
@printf("%i %i", 22, j)
```

-- oder wie Macros, also ohne Funktionsklammern und ohne Komma:


```{julia}
@printf "%i %i" 22 j
```

`@printf` kann als erstes Argument noch einen stream übergeben bekommen. 

Ansonsten besteht die Argumentliste aus

- Formatstring mit Platzhaltern
- Variablen in der Reihenfolge der Platzhalter, in Anzahl und Typ zu den Platzhaltern passend


```{julia}
@printf(stderr, "Erstes Resultat: %i %s\nZweites Resultat %i", 
                                   j, "(geschätzt)"       ,k)
```

`@sprintf` druckt nichts, sondern liefert den ausgefüllten formatierten String zurück: 


```{julia}
str = @sprintf("x = %10.6f", π );
```


```{julia}
str
```

##### Formatierung der Gleitkommazahlen:

Bedeutung des _Precision_-Wertes:

- `%f` und  `%e`-Format:  max. Anzahl der Nachkommastellen
- `%g`-Format:  max. Anzahl von ausgegebenen Ziffern (Vor- + Nachkommastellen) 


```{julia}
x = 123456.7890123456

@printf("%20.4f   %20.4e", x, x)     # 4 Nachkommastellen
```


```{julia}
@printf("%20.7f %20.7e", x, x)     # 7 Nachkommastellen
```


```{julia}
@printf("%20.7g %20.4g", x, x)    # insgesamt 7 bzw. 4 Stellen
```

## Dateioperationen

Dateien werden

 - geöffnet ==>  Dabei ensteht ein neues _stream_-Objekt (zusätzlich zu `stdin, stdout, stderr`)
 - dann kann dieser _stream_ gelesen und geschrieben werden
 - geschlossen ==> _stream_-Objekt wird von Datei getrennt
 
 ```
 stream = open(path, mode)
 ```
 
 - path: Dateiname/pfad
 - mode: 
 ```
 "r"    read, öffnet am Dateianfang
 "w"    write, öffnet am Dateianfang (Datei wird neu angelegt oder überschrieben)
 "a"    append, öffnet zum Weiterschreiben am Dateiende
 ```  


```{julia}
f = open("datei.txt", "w")
```


```julia
@printf(f, "%20i\n", k)
```


```{julia}
println(f, " zweite Zeile")
```


```{julia}
close(f)
```


```{julia}
;cat datei.txt
```


```{julia}
f = open("datei.txt", "r")
```


```{julia}
n = 0
for i in readlines(f)    # Lese zeilenweise
    n += 1
    println(n, i)       # Drucke mit Zeilennummer
end
```

## Pakete für Dateiformate

Pakete für die Ein- und Ausgabe in den verschiedensten Dateiformaten 

- [PrettyTables.jl](https://ronisbr.github.io/PrettyTables.jl/stable/) Ausgabe von formatierten Tabellen
- [DelimitedFiles.jl](https://docs.julialang.org/en/v1/stdlib/DelimitedFiles/) Ein- und Ausgabe von Matrizen u.ä.
- [CSV.jl](https://csv.juliadata.org/stable/) Ein- und Ausgabe von Dateien mit "comma-delimited values" u.ä.
- [XLSX.jl](https://felipenoris.github.io/XLSX.jl/stable/tutorial/) Ein- und Ausgabe von Excel-Dateien

und viele andere mehr...

### Delimited Files



```{julia}
using DelimitedFiles
```


```{julia}
A = rand(200,3)
```


```{julia}
f = open("data2.txt", "w")
```


```{julia}
writedlm(f, A)
```


```{julia}
close(f)
```


```{julia}
;head data2.txt
```


```{julia}
B = readdlm("data2.txt")

```


```{julia}
# man kann open() auch als 1.Argument eine function(iostream) übergeben, die auf den stream 
# angewendet wird, wonach der stream automatisch geschlosssen wird.  
#
# Mit der do-Notation sieht obiger code so aus:

open("data2.txt", "w") do io
    writedlm(io, A)
end

```

### CSV und DataFrames

- [DataFrames.jl](https://dataframes.juliadata.org/stable/) ist ein Paket zum bequemen Umgang mit tabellarischen Daten




```{julia}
using CSV, DataFrames, Downloads
```


```{julia}
# Wetterdaten von Westerland, s. https://dev.meteostat.net/bulk/hourly.html


url = "https://bulk.meteostat.net/v2/hourly/10018.csv.gz"
```


```{julia}
http_response = Downloads.download(url)
```


```{julia}
file = CSV.File(http_response, header=false)
```


```{julia}
# https://dev.meteostat.net/bulk/hourly.html#endpoints

# Spalte 1  Datum
#        2  Uhrzeit (Stunde)
#        3  Temp
#        5  Luftfeuchtigkeit
#        6  Niederschlag
#        8 Windrichtung
#        9 Windstärke


df =  DataFrame(file)
```


```{julia}
describe(df)
```


```{julia}
using StatsPlots
```


```{julia}
using Dates
```


```{julia}
# neue Spalte mit Sp.1 und 2  (date & time) kombiniert

df[!, :datetime] = DateTime.(df.Column1) .+ Hour.(df.Column2);   
```


```{julia}
describe(df)
```


```{julia}
@df df plot(:datetime, :Column3)
```


```{julia}
@df df plot(:datetime, [:Column9, :Column6, :Column3], 
            xlims = (DateTime(2022,1,1), DateTime(2022,7,1)), 
            layout=(3,1), title=["Wind" "Regen" "Temp"], legend=:none)
```



