--- 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) ```