JuliaKurs23/chapters/13_IO.qmd

426 lines
7.6 KiB
Plaintext

---
engine: julia
---
```{julia}
#| error: false
#| echo: false
#| output: false
using InteractiveUtils
```
# Ein- und Ausgabe I/O
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
# aus dem ersten Beispielprogramm
function input(prompt = "Eingabe:")
println(prompt)
flush(stdout)
return chomp(readline())
end
```
```julia
a = input("Bitte 2 Zahlen eingeben!")
```
```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)
```
```julia
```