이전 블로깅에서 클래스파일을 추가하고, 솔루션내의 파일들을 정리 하였는데, 이번에는 파일입출력을 간단히 다뤄보겠다.

처음했던 기능적기와(기능명세) 마찬가지로 구현할 기능을 세세하게 말로 풀어서 써보겠다. 이 기능에 대한 설명이 명확하지 않으면, 프로그램을 작성하는데에 있어 수정을 많이 하거나 생각지 못한 부분에서 버그가 생길 수 있으며, 정해지지 않은 기능을 프로그램 작성중에 발견하여 대대적인 수정이 필요한 경우가 생긴다. 

 

파일입출력하기

- 파일을 읽기기능 - 지정된 경로를 읽을 것인가? 경로를 입력받아 읽을것인가를 정해야한다.

- 파일을 쓰기기능 - 지정된 경로에 파일을 쓸것인가? 파일이 없다면 새로 생성할 것인가? 어떤 형태로 파일을 쓸것인가? 

위와같이, 파일 입출력시 예상되는 오류부분을 적는데 로또번호를 텍스트로 읽고, ( 기존번호 ) 텍스트파일 형태로 출력할 것이기 때문에 기능을 적는것이 필요하다. 여기에서는 정해진 경로에 지정하도록 해보겠다.

 

지난번 클래스파일 추가하기를 이용하여 FileController.cs 라는 class 를 추가해주자.

파일을 추가했다면, 위에서 적었던 기능명세를 주석을 이용하여 클래스내에 적어주자. 이 기능명세는 곧 함수가 된다고 생각하면 된다.

짧은 팁으로, 영역 전체를 주석처리 하는 기능은  Ctrl + K + C 이다. 해제기능은 Ctrl + K + U 다 프로그래밍을 하다보면 굉장히 자주 사용하게 되므로, 10번 정도 주석하고 풀기를 해서 자연스럽게 사용할 수 있도록 숙달해두자.

기능명세를 주석처리해둔 모습  기능은 곧 함수가 된다. (단축키는 Ctrl+k+c)

 

위처럼 기능명세를 주석으로 추가 했다면, 기능에 맞는 이름을 함수로 만들어보자.

파일읽기는 ReadFile()  파일쓰기는 WriteFile()

보면서 느꼈겠지만, 암묵적으로 클래스의 첫자와 함수의 첫자는 대문자로 쓰는것이 관습이다. 대다수의 변수는 소문자로 시작을 한다. 

기능명세 밑에 함수를 작성하였다.

함수를 추가했으면 함수에 어떤기능이 있는지 세부적으로 보자. 여기서는 정해진 경로를 읽을 것이기 때문에 

readPath, writePath 라는 이름의  string 타입의 변수를 클래스 아래에 두개 만들어두자.

 

여기까지 했으면, 솔루션 탐색기에서 프로젝트 우클릭을 통해 프로젝트 폴더로 가보자.

여기서 파일탐색기에서 폴더열기를 누르면, 프로젝트의 폴더가 열리게 된다.

 

폴더가 열리면 datas 라는 폴더를 만들어보자. 우클릭을 해서 새폴더를 만들고 이름을 datas로 바꾸어도 되지만, 

컴퓨터를 잘 아는척을 위해 새폴더만들기 단축키인 Ctrl + Shift + N 을 눌러 새폴더를 만들고, F2를 누르면 이름을 변경할수 있게 되는데 datas로 이름을 바꿔주자.

 

이제 폴더를 만들었으면, 코드 작성하던 곳으로 돌아가서 readPath 와 writePath 의 경로에 다음과 같이 변경해주자.

 

문자열을 처리할때 경로의 역슬래쉬를 쓸경우는 문자열 앞에 골뱅이 또는 at (엣) sign 이라고 하는 특수문자를 추가해준다.

경로를 다 적었으면, 보통의 프로그램이라면 관행적으로 가지고 있는 InitPath 라는 함수와 workingDirectory 라는 string 타입의 문자열 변수를 만들어준다. ( 참고로, 클래스내의 함수 밖 변수의 정식 명칭은 멤버변수라고 한다. 함수내의 변수는 로컬변수 라고 한다.) 

 

로컬변수와 멤버변수 예시

위처럼 함수와 멤버변수를 작성했으면, 프로젝트내의 경로에 접근해보자.

그전에 라이브러리 선언 부분을 System.IO 를 쓰고 나머지는 다 지우겠다. 그리고 InitPath 함수 내부에 다음처럼 작성해보자.

 

경로를 절대경로로(드라이브부터 프로젝트까지) 특정해버리면, 시스템이 달라질때마다, 프로그램을 새로 컴파일 ( 사람이 작성한 부분을 컴퓨터가 읽을 수 있도록 바꿔주는 기능 ) 해야 하므로 컴퓨터가 달라지더라도 이 프로그램이 실행되도록 상대경로로 지정할 필요가 있다. ( 잘 모르면 구글에서 검색해보자 )

 

왼쪽은 mylist.txt 라는 파일이 경로에 있으면 존재라는 글자와 경로가 출력되게 해두었고, 없으면 없음 이라고 출력되게 하였다.

우측은 FileControll 클래스의 인스턴스 ( 객체라고도 한다) 를 만들고 InitPath 함수를 호출시켜주었다. 위의 로또출력부분은 원활한 테스트를 위해 잠시 주석처리를 해두자. ( 주석은 영역설정하고 Ctrl + K + C )  추가로 콘솔창이 바로 꺼지는것을 방지하기 위해 아래 한줄도 추가해주자. 

 

아직 없어서 없음이 떴다.  그렇다면 콘솔창을 종료하고, 없으면 파일을 만들어 주도록 해보자.

먼저 MakeFile 이라는 함수를 추가하고 파라미터는 string path 로 추가해주자.

 

위처럼 파라미터가 있는 함수를 만들고, 파일을 만드는 부분을 추가해보자.

 

파일이 없으면 만들도록 하고 저장한후 실행 (F5) 해보자.

실행하면 에러가 없다면 아무것도 뜨지 않는 콘솔창이 뜰텐데 끄고, 솔루션탐색기에서 솔루션 폴더로 가보자.

 

아무내용이 없는 파일이 생긴것을 확인할 수 있다. 위에서 폴더를 직접 만들었는데,  이를 응용하면 폴더도 생성할 수 있다.

이제 내가 만든 로또번호를 파일에 저장을 해보자.  그전에 읽거나 저장하는 경로가 두개이기 때문에 ( 지금은 같지만 이후에바뀐다.) 경로를 가져오는 간단한 부분을 작성해보자.

 

위의것은 나열자라고 하며, 그냥 나열하는 기능이 있는데 데이터타입을 특정하거나, 값을 부여할 수 있다. 자세한것은 

C# 나열자 라고 구글에서 검색하면 된다. 아래의 GetFullPath 는 나열자를 파라미터로 사용하여 경로를 가져온다.

이 함수를 읽어보면, 파라미터가 READ 면 workingDirectory + readPath 를 가져오고 READ가 아니면  orkingDirectory + writePath 를 가져온다는 의미이다. 

 

이제 출력할 필요가 없으므로 위에서 만든 함수를 이용하여, InitPath 함수를 정리해보았다.

여기서 var path 에서 var는 최신언어들에서 제공되는 특성인데,  타입을 특정하지 않고 컴파일타임에 결정된다. ( 이를 암시적 형식 지역변수 라고한다)

즉 위의 코드에서 path 는 GetFullPath 의 return 타입이 string 이므로 암시적으로 string이 된다.

 

읽고 쓰고 경로를 조금 바꿔주자. 

그리고 만들어진 로또번호를 FileController 객체에 전달하기 위해 Numbers 클래스를 조금 변경해주겠다.

 

List 를 멤버변수로 바꿔주고, 저장하기전 보기좋게 바꿔주기위해 GetStringFormatValue 라는 함수를 만들고 작성해준다.

내용은 다음처럼 작성해준다. 이부분은 뽑아진 번호를 쉼표로 구분하게 한다.

 

위처럼 바꿔줬으면 FileController 로 돌아와서 WriteFile 의 파라미터를 다음과 같이 바꿔주고 내용을 작성해준다.

 

Number 클래스에서 만든 로또번호를 파라미터로 전달하고, 로또번호를 파일로 저장한다.

마지막으로 main 함수로 가서 다음처럼 바꿔준다. 

 

기본적인 파일 출력은 끝났다 저장하고 F5를 눌러 잘 실행되는지 확인해보자.

 

실행하면 파일이 만들어 지느라 한번 오류가 날수 있는데, 이부분은 다음에 다루기로 하고 다시 실행해주면 위와같이 이번주 로또번호가 파일에 잘 출력된것을 볼 수가 있다. 

여기까지 따라왔다면 프로젝트 폴더의 bin\Debug 폴더로 가면 아래처럼 파일들이 생성되어있는것을 볼 수가 있는데

축하한다. 여러분은 파일생성기능까지 있는 프로그램을 완성하였다.

다음에는 로또번호 여러개 생성하기 릴리즈모드로 exe 파일 뽑아보기 등을 블로그하겠다.

오늘작성한 프로그램은 이곳에서 다운받아서 exe 로 뽑아볼수 있다.

https://github.com/IlseonSEO/getlottonums/blob/main/lottoTest.zip

+ Recent posts