안녕하세요. 언제나휴일입니다.
앞에서 FileStream 개체를 이용한 파일 입출력과 BinaryWriter, BinaryReader 개체를 이용한 파일 입출력을 다뤘습니다.
FileStream 개체로 입출력 [Windows Forms with C#]
BinaryWriter, BinaryReader를 이용한 입출력 [Windows Forms with C#]
이번에는 StreamWriter와 StreamReader를 이용한 파일 입출력 실습을 해 볼게요.
StreamWriter로 출력한 내용은 텍스트 뷰어나 편집기를 통해서 확인이 가능합니다. 텍스트 모드의 입출력이라고 말할 수 있어요.
여기에서는 CSV 포멧으로 입출력하기로 할게요.
(인코딩이 다르면 한글은 깨져 보일 수 있습니다.)
1. 시나리오
실습할 시나리오는 이전 게시글과 같습니다.
프로그램 시작할 때 파일에 있는 내용을 로딩하여 ListView에 보여줍니다.
사용자가 회원 정보를 입력하여 추가 버튼을 누르면 ListView에 추가합니다.
프로그램 종료할 때 ListView에 회원 정보를 파일에 기록합니다.
2. 이전 게시글과 같은 부분
컨트롤 배치 및 이벤트 핸들러 등록하는 부분까지 똑같습니다.
파일 이름을 상수로 선언한 부분도 같습니다.
const string fname = "data.csv";
Form1.cs에서 btn_add의 Click 이벤트 핸들러는 같습니다.
private void btn_add_Click(object sender, EventArgs e) { string id = tbox_id.Text; string name = tbox_name.Text; int age = tbar_age.Value; AddMember(id, name, age); tbox_id.Text = tbox_name.Text = ""; tbar_age.Value = 0; lb_age.Text = "0"; }
물론 but_add의 Click 이벤트 핸드러에서 호출하는 AddMember 메서드도 같습니다.
private void AddMember(string id, string name, int age) { string[] sitems = new string[] { id, name, age.ToString() }; ListViewItem lvi = new ListViewItem(sitems); lv_member.Items.Add(lvi); }
Form1.cs에서 tb_age의 Scroll 이벤트 핸들러도 같습니다.
private void tbar_age_Scroll(object sender, EventArgs e) { lb_age.Text = tbar_age.Value.ToString(); }
3. 파일 입출력 구현
StreamWriter로 출력할 때 사용하는 메서드는 Console 클래스에서 출력할 때 사용하는 메서드와 사용 방법이 같습니다.
StreamReader로 로딩할 때 사용하는 메서드는 Console클래스에서 입력할 때 사용하는 메서드와 사용 방법이 같습니다.
3.1 Form1의 FormClosed 이벤트 핸들러 구현
파일을 생성한 후에 StreamWriter 개체를 생성합니다.
입출력 작업 후에는 닫아주세요.
FileStream fs = File.Create(fname); StreamWriter sw = new StreamWriter(fs); ... 입출력 작업 ... sw.Close(); fs.Close();
lv_member에 있는 회원 정보를 얻어와서 출력하는 반복문에서 정보를 얻어오는 것은 이전과 같습니다.
출력할 때 WriteLine메서드를 이용하여 아이디, 이름, 나이를 출력합니다.
CSV 파일에서는 항목을 구분할 때 콤마를 사용하고 데이터는 개행으로 구분합니다.
foreach(ListViewItem lvi in lv_member.Items) { string id = lvi.SubItems[0].Text; string name = lvi.SubItems[1].Text; int age = int.Parse(lvi.SubItems[2].Text); sw.WriteLine("{0},{1},{2}", id, name, age); }
다음은 Form1의 FormClosed 이벤트 핸들러입니다.
private void Form1_FormClosed(object sender, FormClosedEventArgs e) { FileStream fs = File.Create(fname); StreamWriter sw = new StreamWriter(fs); foreach(ListViewItem lvi in lv_member.Items) { string id = lvi.SubItems[0].Text; string name = lvi.SubItems[1].Text; int age = int.Parse(lvi.SubItems[2].Text); sw.WriteLine("{0},{1},{2}", id, name, age); } sw.Close(); fs.Close(); }
3.2 Form1의 Load 이벤트 핸들러 구현
파일이 없으면 메서드를 종료합니다.
if (File.Exists(fname) == false) { return; }
읽기 모드로 파일을 열고 StreamReader 개체를 생성합니다.
파일 입출력 작업 후 닫아주세요.
FileStream fs = File.OpenRead(fname); StreamReader sr = new StreamReader(fs); ... 파일 입출력 작업 ... sr.Close(); fs.Close();
StreamReader 개체에 EndOfStream 속성으로 현재 끝까지 읽었는지 판단할 수 있어요.
반복해서 한 줄 씩 얻어옵니다.
그리고 콤마를 기준으로 분리한 후에 해당 정보로 회원 정보를 추가합니다.
while(sr.EndOfStream==false) { string data = sr.ReadLine(); if(data == null) { break; } string[] sitems = data.Split(','); AddMember(sitems[0], sitems[1], int.Parse(sitems[2])); }
다음은 Form1의 Load 이벤트 핸들러입니다.
private void Form1_Load(object sender, EventArgs e) { if (File.Exists(fname) == false) { return; } FileStream fs = File.OpenRead(fname); StreamReader sr = new StreamReader(fs); while(sr.EndOfStream==false) { string data = sr.ReadLine(); if(data == null) { break; } string[] sitems = data.Split(','); AddMember(sitems[0], sitems[1], int.Parse(sitems[2])); } sr.Close(); fs.Close(); }
4. Form1.cs 소스 코드
using System; using System.IO; using System.Windows.Forms; namespace 텍스트_모드_CSV { public partial class Form1 : Form { const string fname = "data.csv"; public Form1() { InitializeComponent(); } private void btn_add_Click(object sender, EventArgs e) { string id = tbox_id.Text; string name = tbox_name.Text; int age = tbar_age.Value; AddMember(id, name, age); tbox_id.Text = tbox_name.Text = ""; tbar_age.Value = 0; lb_age.Text = "0"; } private void AddMember(string id, string name, int age) { string[] sitems = new string[] { id, name, age.ToString() }; ListViewItem lvi = new ListViewItem(sitems); lv_member.Items.Add(lvi); } private void tbar_age_Scroll(object sender, EventArgs e) { lb_age.Text = tbar_age.Value.ToString(); } private void Form1_Load(object sender, EventArgs e) { if (File.Exists(fname) == false) { return; } FileStream fs = File.OpenRead(fname); StreamReader sr = new StreamReader(fs); while(sr.EndOfStream==false) { string data = sr.ReadLine(); if(data == null) { break; } string[] sitems = data.Split(','); AddMember(sitems[0], sitems[1], int.Parse(sitems[2])); } sr.Close(); fs.Close(); } private void Form1_FormClosed(object sender, FormClosedEventArgs e) { FileStream fs = File.Create(fname); StreamWriter sw = new StreamWriter(fs); foreach(ListViewItem lvi in lv_member.Items) { string id = lvi.SubItems[0].Text; string name = lvi.SubItems[1].Text; int age = int.Parse(lvi.SubItems[2].Text); sw.WriteLine("{0},{1},{2}", id, name, age); } sw.Close(); fs.Close(); } } }