#author("2019-04-08T09:40:17+09:00","default:Miyashita","Miyashita") #author("2019-10-17T14:12:51+09:00","default:Miyashita","Miyashita") *ファイル I/O [#ofac7ee4] (バイナリでない)テキストや数値の入出力について. #contents **ファイルの開閉 [#a6bd9920] 基本的にこの2種類を使用している. -open〜close #codeprettify(lang-julia){{ out = open("file.txt","w") println(out,"foobar") close(out) }} -open, do〜end #codeprettify(lang-julia){{ open("file.txt","w") do out println(out,"foobar") end }} open, do〜endの場合は,closeは不要.ただし,スコープの関係でdo〜end内で定義した変数はその中でしか有効にならない.~ #codeprettify(lang-julia){{ julia> open("file.txt","r") do f a = readline(f) end "foobar" julia> println(a) ERROR: UndefVarError: a not defined }} globalにすれば一応do〜end外でも使えるが,紛らわしいので読み取りをする場合は素直にopen〜closeの方が良いと思われる.~ また,後述のreadline, readlinesはopenを使わなくても良い. #codeprettify(lang-julia){{ julia> open("file.txt","r") do f global a = readline(f); # global変数に end julia> println(a) # do〜end外でも有効 foobar }} #codeprettify(lang-julia){{ julia> f = open("file.txt","r"); julia> a = readline(f); julia> close(f) julia> println(a) foobar }} openの2つめの引数にあるのは読み(read),書き(write),追加(append)専用のファイルにする識別子で,"r","w","a"で指定する.~ "r+","w+","a+"でそれぞれ異なる処理も可能ではあるが,あまり使用しない. 詳細は[[Base.open>https://docs.julialang.org/en/v1/base/io-network/#Base.open]]にある. **入力 [#sfc11947] ***基本 [#sf4b8785] [[readline>https://docs.julialang.org/en/v1/base/io-network/#Base.readline]], readlinesをよく使う.~ readlineは1行分,readlinesは可能な限り全部読み取る. #codeprettify(lang-julia){{ readline(io::IO=stdin; keep::Bool=false) readline(filename::AbstractString; keep::Bool=false) }} openを使用し,IOStream型を引数にしたreadlineは,読む度に読み取り開始位置が移動するが,~ ファイル名のAbstractString型を引数とした場合は,何度実行しても1行目しか読めない. #codeprettify(lang-julia){{ julia> f = open("file.txt","r"); julia> readline(f) # 1行目 "foobar" julia> readline(f) # 2行目 (ファイルの末尾) "" }} #codeprettify(lang-julia){{ julia> readline("file.txt") # 1行目 "foobar" julia> readline("file.txt") # 次も1行目 "foobar" }} ~ ヘッダー部分をreadlineで読んで,残り全部をreadlinesということもできる. #codeprettify(lang-julia){{ f = open("file.txt","r") header = readline(f) # 1行目だけheaderへ body = readlines(f) # 残り全部 close(f) }} ***readline, readlines後の変換 [#ee3e3169] readlinesで読んだbodyには複数行の情報があるとし,例えば n行目(row)の,m〜l (column)を参照して数値に変換するには #codeprettify(lang-julia){{ num = parse(Float64, body[n][m:l]) }} のようにする.~ 配列にするときはsplitとparseで, #codeprettify(lang-julia){{ strarray = split(body[n], r"\s+",keepempty=false) # bodyのn行目を空白区切りにして分割 numarray = parse.(Float64, strarray) # 文字列の配列を Float64 配列に }} ~ また,ヘッダーなどで,「何カラム目にあるかわからないけどどこかにある数値の部分を抜き出す」なら,正規表現とmatchを使う. #codeprettify(lang-julia){{ # 数値っぽいものがマッチする正規表現 regex = r"([+-]?(?:\d+\.?\d*|\.\d+)(?:[eE][+-]?\d+)?)" # readline(f)で読んだ行の中から数値を抜き出し,その1つをFloat64に変換する val = parse(Float64, match(regex, readline(f)).captures[1]) }} ***その他 [#dc532725] 直接配列に落としこむ場合は,[[DelimitedFiles.readdlm>https://docs.julialang.org/en/v1/stdlib/DelimitedFiles/index.html]]でも良い.~ #codeprettify(lang-julia){{ readdlm(source, delim::AbstractChar, T::Type, eol::AbstractChar; header=false, skipstart=0, skipblanks=true, use_mmap, quotes=true, dims, comments=false, comment_char='#') }} open〜closeは不要でファイル名を引数とする. #codeprettify(lang-julia){{ using DelimtedFiles: readdlm # 3行飛ばして4行目から読み取り開始する場合は skipstart=3 dataorg = DelimitedFiles.readdlm(filename, skipstart=3) }} ~ ~ **出力 [#g7cf4dae] ***基本 [#u7f59c88] 標準出力もファイル出力も基本的には同じfunctionを使えばよく,print, println, Printf.@printfなど.~ 最初の引数に IOStream型があればそれに,なければ標準出力に. #codeprettify(lang-julia){{ julia> print("hoge") # 標準出力 hoge julia> print(stdout, "hoge") # 上と同じ hoge }} #codeprettify(lang-julia){{ julia> open("file.txt","w") do out #ファイルに書く print(out,"hoge") end julia> readlines("file.txt") # readline"s"なので配列 1-element Array{String,1}: "hoge" }} ***配列の出力 [#u99cb781] [[配列の出力>../配列の出力(print)]]に書いた通り.~ 数値配列を組み直すときは,Array{T,1}なのかArray{T,2}なのか注意する. #codeprettify(lang-julia){{ open("file.txt","w") do out Base.print_array(out, hcat(x[:],y[:],z[:])) # x,y,zの3列にして掃き出し end }}