Julia Language

[Julia] 텍스트 파일(.txt)에 데이터 쓰고 읽기

공부하는백수 2021. 5. 13. 12:09

※ 다음 링크에서 줄리아 프로그래밍과 관련한 글 목록을 확인하실 수 있습니다.

Julia 프로그래밍 관련 글 목록


텍스트 파일 쓰기

using Printf
using Dates

savefilename = "text.txt"
fid = open(savefilename, "w")

a = Array(1:10)

println(fid, "date: ", Dates.today())
println(fid, "time: ", Dates.Time(Dates.now()))
println(fid, "")
println(fid, "="^80)
println(fid, ">> Frequency Settings")
println(fid, "a: ", a)
@printf(fid, "pi: %0.8f", pi)

close(fid)

  Julia에서는 다양한 프린트 함수를 제공하는데 위 예제에서는 println@printf를 예시로 사용하였다. @printf는 C언어에서의 printf 함수를 Julia에 사용하고자 할 때 Printf 패키지를 using 키워드로 로드하여 사용할 수 있다. 사용방법은 C언어에서의 printf와 같다. 그리고 Dates 패키지는 시간관련 정보를 파일에 함께 저장하는 예시를 보이기 위한 목적으로 사용하였다.

  텍스트 파일을 저장하기 위해 가장 먼저 하여야 할 일은 다른 언어와 마찬가지로 파일을 쓰기모드로 여는 것이며, 이때 사용하는 것이 open 함수이다. 파일 open 시 쓰기 모드와 읽기 모드 등의 옵션은 아래 그림과 같이 지정할 수 있다. (다른 언어들과 크게 다르지 않다.)

(출처: https://docs.julialang.org/en/v1/base/io-network/)

  파일을 연 후, println 함수와 @printf 함수를 이용하여 문자열, 배열, 스칼라 값 등을 위 코드에서의 예시와 같이 저장할 수 있으며, 마지막에는 close 함수를 이용하여 파일을 닫아 주어야 한다. 위 예제 코드를 통해 생성된 텍스트 파일의 내용은 다음과 같다. 매우 간단한 예제이기는 하지만 코드와 파일 내용을 비교해가며 파일 저장 과정을 완벽히 이해하도록 하자.

 

 

  Python에서의 with~as와 유사하게 Julia에서도 아래와 같은 방법으로 파일 open do 키워드를 통해 파일을 저장하는 것도 가능하다. 저장 결과는 앞의 예제와 완전히 동일한데, 아래와 같은 코드를 사용할 경우 close 함수를 통해 파일을 닫는 과정을 생략할 수 있다. (참고로 이는 Pyhton도 마찬가지이다.)

open(savefilename, "w") do fid
    println(fid, "date: ", Dates.today())
    println(fid, "time: ", Dates.Time(Dates.now()))
    println(fid, "")
    println(fid, "="^80)
    println(fid, ">> Frequency Settings")
    println(fid, "a: ", a)
    @printf(fid, "pi: %0.8f", pi)
end

텍스트 파일에서 데이터 읽기

한 번에 읽기 (read, readlines)

  파일쓰기와 마찬가지로 open 함수와 do 키워드를 사용하여 아래와 같은 방식으로 텍스트 파일을 열고 read 함수를 이용하여 파일 내의 모든 내용을 한 번에 읽을 수 있다.

s = open("text.txt") do file
    read(file, String)
end

   위 코드를 이용하여 앞서 저장한 텍스트 파일의 내용을 String 타입으로 읽어오면 아래와 같이 하나의 문자열로 읽어오게 된다. 

julia> s
"date: 2021-05-13\ntime: 12:15:27.242\n\n================================================================================\n>> Frequency Settings\na: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]\npi: 3.14159265"

  위와 같이 데이터를 읽어오면 데이터 핸들링에 손이 많이 가기 때문에 라인을 구분하여 읽어오는 것이 때로는 더 유용하다. readlines 함수를 사용하면 텍스트 파일 내 모든 라인을 한 번에 읽은 후 String Array 형태로 저장할 수 있다.

s = open("text.txt") do file
    readlines(file)
end

 

  read 함수의 두 번째 인자에 데이터 타입을 지정할 수 있는데, 만약 파일 내에 숫자들만 저장되어 있다면 String으로 파일 내용을 읽어온 후 split 함수로 문자열을 쪼개고 parse 함수를 이용하여 저장된 값들을 Array 형태로 저장할 수 있다. 예를 들어, 아래와 같은 내용으로 "text1.txt" 파일이 있다고 가정해보자.

  "text1.txt"에 저장된 값들을 a라는 array에 저장하는 예제 코드는 다음과 같다.

s = open("text1.txt") do file
    read(file, String)
end
a = parse.(Float64, split(s))

  위와 같이 숫자 데이터를 읽으면 1차원 Array 형태로 저장된다. 2차원 Array로 저장하고 싶다면 아래의 예제를 응용하는 것이 도움이 될 수 있다. 참고로 hcattranspose 함수를 사용하지 않으면 데이터는 Array of Arrays 형태로 저장된다. Array of Arrays를 matrix로 변화하는 다른 더 좋은 방법이 있는지는 모르겠으나 나는 아래와 같은 방법을 사용한다.

s = open("text1.txt") do file
    readlines(file)
end
splited_s = split.(s)
parsed_s = [parse.(Float64, x) for x in splited_s]
mat_s = transpose(hcat(parsed_s...))

  위 코드를 통해 mat_s는 아래와 같이  2x3 Array로 저장되며 각 요소에 직관적으로 접근이 가능하다.

 

줄 단위로 읽기 (eachline, readline)

  파일 전체가 아니라 줄 단위로 읽기 위해서는 eachline이나 readline 함수를 사용하면 된다. eachline을 사용하는 예제는 다음과 같다.

open("text.txt") do file
    for s in eachline(file)
        println(s)
        # println("$(length(ln)), $(ln)")
    end
end

 

  텍스트 파일을 줄 단위로 읽으면서 특정 문자가 포함된 줄의 데이터만 읽거나 skip할 필요가 있는 경우가 있다. 이런 경우에는 contains 함수(혹은 occursin 함수)를 사용하여 현재 라인에서 특정 문자의 포함 여부를 체크한 후 조건을 만족할 경우에만 데이터를 읽을 수 있다.

  다음 예제에서는 "="이 포함된 줄의 데이터는 읽지 않는 동작을 readline 함수를 이용하여 구현해보았다. 그리고 아래 예제에서는 for문을 사용한 앞의 예제와는 달리 eof 함수(end of file)를 이용하여 파일의 끝에 도달할 때까지 while 문을 사용하여 줄 단위로 데이터를 읽어보기로 한다.

open("text.txt") do f
  line = 1
  while !eof(f)
    x = readline(f)
    if contains(x, "=")
        continue
    end
    println(x)
  end
end

 

  의도한 바와 같이 "="가 포함된 줄은 생략된 결과가 출력되는 것을 확인할 수 있다.

 

 

참고할만한 포스트

[Julia] 기초 문법 공부 - 문자와 문자열의 모든 것

[Julia] 기초 문법 공부 - 문자열을 다루기에 유용한 함수들