안녕하세요. CSV파일을 DataTable로 가져오기 글에서 동일하게 따라했는데 안된다고 하시는 분들이 있습니다.

원본 글: https://ilbbang.tistory.com/entry/C-Windows-Form-CSV파일을-DataTable로-가져오기

저도 이 점 충분히 이해합니다. 다른 글 보고 따라했는데 안되는 경우가 종종 있습니다. 그래서 전체 코드 및 영상, 샘플 파일을 공개합니다. 위와 같이 따라했을 경우 안되는 경우는 해당 컴퓨터의 환경 문제로 예상됩니다. 절차 코드 등에 대한 설명은 전부 생략했습니다. 설명이 필요하신 분은 위에 있는 글을 먼저 보시기 바랍니다.

우선 제가 처음 실행해서 프로젝트 생성, 화면 및 코드 작성, 디버깅 과정을 영상으로 만들었습니다.

위 영상에서 코드가 필요한 파일은 form1.cs 1개의 파일입니다. 해당 파일의 코드 전부를 아래에 작성했습니다.

using System;
using System.Data;
using System.Windows.Forms;

using System.IO;
using System.Data.OleDb;
using System.Globalization;

namespace WindowsFormsApp2
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            if (openFileDialog1.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                string filename = openFileDialog1.FileName;
                DataTable dt1 = getDataTableFromCsv(filename, false); ;
            }
        }

        private DataTable getDataTableFromCsv(string path, bool isFirstRowHeader)
        {
            string header = isFirstRowHeader ? "Yes" : "No";
            string pathOnly = Path.GetDirectoryName(path);
            string fileName = Path.GetFileName(path);
            string sql = @"SELECT * FROM [" + fileName + "]";
            using (OleDbConnection connection = new OleDbConnection(
                @"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + pathOnly + ";Extended Properties=\"Text;HDR=" + header + "\""))
            using (OleDbCommand command = new OleDbCommand(sql, connection))
            using (OleDbDataAdapter adapter = new OleDbDataAdapter(command))
            {
                DataTable dataTable = new DataTable();
                dataTable.Locale = CultureInfo.CurrentCulture;
                adapter.Fill(dataTable);
                return dataTable;
            }
        }
    }
}

이제 마지막으로 샘플 파일입니다. 샘플파일은 아무 csv 파일로 하셔도 상관없습니다.
예제 파일도 엑셀로 랜덤번호 30개 생성해서 숫자로 바꾼것일 뿐 아무 의미 없는데이터입니다.
그래도 혹시 모르니 제가 로드했던 샘플파일을 첨부합니다.

sample1.csv
0.00MB

위 내용에 대하여 궁금하신 점 있으면 댓글 남겨주세요.

감사합니다.

Visual Studio 윈도우 폼에서 CSV 파일을 DataTable로 가져오는 내용의 글을 올려보겠습니다.

우선 Visual Studio 프로그램 실행 후 위쪽 메뉴의 "파일" -> "새로 만들기" -> "프로젝트" 를 선택(클릭)합니다.

왼쪽 Visual 템플릿에서 "Visual C#" -> "Windows" -> "Windows Forms 응용 프로그램" 을 선택한 후에 아래쪽에 프로젝트 "이름", "위치" 를 지정하고 오른쪽 아래에 있는 "확인" 단추를 선택(클릭) 합니다.

그러면 기본 Form1이 만들어 지고 응용 프로그램을 만들 준비가 되었습니다.
도구상자에서 OpenFileDialog 를 Form1.cs[디자인] 화면 아무데나 마우스를 드레그하여 놓습니다.

그러면 아래 그림과 같이 Form1 아래쪽에 OpenFileDialog1이 추가된 것을 볼 수 있습니다.

OpenFileDialog1 은 파일을 열때 사용하는 도구이지만 Form 화면에 나타나지 않습니다.
이를 실행시키기 위해서는 버튼 등 화면에 보이는 도구가 필요합니다.

OpenFileDialog1 을 실행시키기 위한 Button을 Form1.cs[디자인] 화면 아무데나 마우스를 드레그하여 놓습니다.

그러면 아래 그림과 같이 Form1 안쪽에 Button1이 추가된 것을 볼 수 있습니다.

Button1 의 속성을 확인하고 Text를 "불러오기"로 변경합니다.

"불러오기" Button1을 마우스 더블클릭하면 다음 그림과 같이 클릭 시 실행될 코드를 입력할 공간이 나타납니다(Button1_Click)

다시 Form1.cs[디자인] 화면으로 돌아옵니다.

이번에는 OpenFileDialog1의 속성 내용을 수정하기 위해 Form1 아래쪽에 있는 OpenFileDialog1 을 클릭합니다.
속성에서 아래 내용대로 수정합니다.
첫번째 그림 Filter 속성은 CSV파일만 보이게 하기 위해 필터링 옵션을 추가합니다.

두번째, 세번째 그림은 OpenFileDialog 가 열릴때 기본으로 출력될 파일 이름입니다. 선택하기 전에는 아무 이름도 없는게 맞기 때문에 기본 입력된 값을 지웁니다.

네번째 그림은 OpenFileDialog 창이 열릴 때 왼쪽 상단에 뜨는 Title 입니다. 기능보다는 보여지는 화면이기 때문에 테스트할 때에는 굳이 안 바꿔도 상관없습니다.

Form1.cs 코드파일로 이동합니다,(Form1.cs[디자인] 화면에서 키보드 "F7" 단추를 선택(클릭)하면 코드파일로 이동합니다.)
버튼 클릭할때의 코드를 다음과 같이 입력합니다.

CSV파일을 DataTable 파일로 변환해 주는 매서드를 아래와 같이 추가합니다.

그리고 테스트를 위해ㅓ DataTable이 완성된 다음줄에 중단점을 걸어 줍니다.
(34줄 바로 옆에 흰 부분을 마우스로 선택(클릭)하면 아래 그림과 같이 빨간색 원이 나타나 중단점이 설정됩니다.)

이제 테스트를 끝낼 준비가 완료되었습니다.

상단 메뉴에서 "디버그" -> "디버깅 시작" 단추를 선택합니다.

디버깅이 시작되고 Form1이 실행되었습니다.

불러오기 단추를 선택(클릭)합니다.

엑셀 파일을 불러올 OpenFileDialog1이 실행되었습니다.

CSV파일 하나를 선택하고 열기 단추를 선택(클릭) 합니다.

그러면 아래 화면과 같이 중단점에서 코드가 중단된 것을 확인할 수 있습니다.

DataTable dt1에 CSV파일의 내용이 잘 들어갔는지 확인해보겠습니다.

여러가지 방법이 있지만 dt1부분을 마우스로 선택(클릭) 후 잠시 기다려 주면 아래 그림과 같이 dt1에 대한 세부 내용을 볼 수 있는 창이 나타납니다.
돋보기 그림을 마우스 선택(클릭) 합니다.

그러면 DataSet 시각화 도우미가 나타나며 CSV에 있는 내용 그대로 들어온 것을 확인할 수 있습니다.

이제 CSV에 있는 내용을 DataTable 로 가져와서 프로그래밍 할 수 있습니다.

이전 글이어서 코드가 그림파일입니다.
더욱 쉽게 따라하실 수 있게 영상, 코드, 샘플파일을 포함한 글을 하나 더 작성했습니다.
아래 글을 확인해 주세요.

https://ilbbang.tistory.com/entry/C-Windows-Form-CSV파일을-DataTable로-가져오기-영상코드샘플파일

감사합니다.

이번에는 파일을 분석해서 이 파일이 어느 종류의 파일인지를 알 수 있는 방법에 대해 알아보겠습니다.

사실 대부분의 경우 확장자가 잘 되어 있기 때문에 이 과정이 필요 없을 수 있습니다.
확장자가 jpg, png bmp 인 경우 그림파일, mp3 wav 인 경우 오디오 파일 avi mp4 인 경우 동영상 파일 등...
컴퓨터를 사용하다 보면 자연스럽게 알게 되는 정보이기 때문이죠.

그런데 흔하지는 않지만 실수 또는 잘못된 방법으로 파일의 확장자가 마음대로 변경된 경우를 경험하신 적 있으신가요?
저도 거의 없었지만 이전 휴대폰의 파일을 백업하고 오랜 기간이 지난 후에 보니 그림과 동영상 파일의 확장자가 001 002 같이 마음대로 바껴있더라고요.

물론 대략 폴더의 위치를 보고 확장자를 jpg 나 mp4로 바꿔서 실행해 보는 방법이 있습니다만
요즘 프로그래밍을 공부하다 보니 근본적으로 이 파일이 무슨 파일인지 알아내는 방법이 있는지, 이를 프로그래밍 할 수 있는 방법이 있을 지 궁금해 졌습니다.

그래서 구글로 검색을 해 본 결과 다음과 같은 프로그램을 찾았습니다.

TrID - File Identifier
http://mark0.net/soft-trid-e.html

위 프로그램은 파일의 내부를 분석해서 파일의 확장자가 무엇인지와 무슨 파일인지를 찾아주는 프로그램입니다. 실행 방식은 윈도우 cmd에서 실행해서 결과를 텍스트로 뿌려줍니다. 내 컴퓨터에서 실행하기 위해서는 아래 다운로드 링크 중에서 실행 파일과 TrIDDefs.TRD package 2개를 다운받은 후 압축을 풀면 됩니다.

저는 아래 그림과 같이 "C:\trid_w32" 폴더에 trid.exe, triddefs.trd 파일을 복사했습니다. 그리고 테스트를 위해 그림파일을 하나 가져와서 파일 이름을 unknownfile 이라고 하고 확장자를 지워버렸습니다.

그럼 cmd에서 실행해 볼까요? 윈도우키+R을 누르면 실행창이 뜨는데요 "cmd"라고 입력한 후에 확인을 클릭하면 됩니다. "C:\trid_w32" 폴더로 이동해서 명령어를 "trid unknownfile"라고 입력하면 아래 그림과 파일 분석 후에 결과가 나오게 됩니다.

이 프로그램의 결과를 visual studio 로 가져와서 원하는 형식으로 출력할 수 있을까요? 검색을 해 본 결과 가능한 것을 확인했습니다.

Process.start: how to get the output?
https://stackoverflow.com/questions/4291912/process-start-how-to-get-the-output

이제 프로그래밍을 해보겠습니다.

Visual Studio에서 새로운 프로젝트를 아래 그림과 같이 생성합니다. 프로젝트 이름은 "WindowsFormFileIdentifier" 로 지정하였습니다.

그리고 폼을 꾸며보겠습니다. 우선 기본 폼의 속성을 몇가지 변경합니다.

(Name): Form1 - Text: 파일형식 찾기 / Size: 400, 400

이제 도구들을 추가하고 속성을 변경하겠습니다.

라벨(Label) - (Name): label1 / Location: 20, 20 / AutoSize: True / Size: 137, 12(자동으로 설정됨) / Text: 파일 형식 찾기 프로그램
라벨(Label) - (Name): label2 / Location: 20, 60 / AutoSize: True / Size: 231, 12(자동으로 설정됨) / Text: 1. 오른쪽 버튼을 눌러 파일을 선택합니다.
버튼(Button) - (Name): button1 / Location: 260, 60 / AutoSize: False / Size: 75, 23 / Text: 파일 선택
라벨(Label) - (Name): label3 / Location: 20, 100 / AutoSize: True / Size: 73, 12(자동으로 설정됨) / Text: 선택한 파일:
라벨(Label) - (Name): label4 / Location: 100, 100 / AutoSize: True / Size: 29, 12(자동으로 설정됨) / Text: 없음
라벨(Label) - (Name): label5 / Location: 20, 140 / AutoSize: True / Size: 109, 12(자동으로 설정됨) / Text: 선택한 파일의 정보
자료보기창(DataGridView) - (Name): dataGridView1 / Location: 20, 180 / AutoSize: False / Size: 350, 160

꾸며진 결과는 아래 그림과 같습니다.

외형을 완성했으면 이제 프로그래밍을 해보겠습니다.
파일 선택 버튼을 더블클릭하면 자동으로 이벤트가 추가되고 코드보기 화면으로 전환됩니다.

코드를 작성하기 전에 bin\debug 폴더에 위에서 실행했던 trid.exe, triddefs.trd 2개의 파일을 붙여넣기 해야 합니다.
코드 왼쪽에 있는 솔루션 탐색기 메뉴에서 아이콘 중 모든파일 표시 아이콘을 클릭합니다. 기존에는 프로젝트와 관련이 없는 폴더나 파일은 숨겨져 있는데 이 아이콘을 클릭하면 모든 파일이 나타납니다. bin 폴더 안에 있는 debug 폴더에 커서를 놓고 오른쪽 마우스 버튼을 클릭한 후에 "파일 탐색기에서 폴더 열기" 메뉴를 클릭하면 해당 폴더 파일 탐색기가 열리게 됩니다.

이제 위에서 설명한 2개의 파일을 붙여넣기 하면 아래 그림과 같이 파일이 복사된 것을 확인할 수 있습니다.

이제 프로그래밍으 해보겠습니다. 매서드를 2개 만들겠습니다.

매서드1. 실행파일과 분석할 파일 경로를 활용하여 cmd에서 나왔던 정보를 datatable 형식으로 변환하여 출력해 주는 매서드 입니다.

        /// <summary>
        /// 선택한 파일에 대한 정보를 DataTable 형식으로 내보냅니다.
        /// </summary>
        /// <param name="FileName">선택한 파일의 전체 경로</param>
        /// <returns></returns>
        private DataTable GetResultsFromTridCMDStrings(string FileName)
        {
            // executableLocation 은 프로젝트 폴더\bin\debug 까지의 폴더입니다.
            string executableLocation = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
            // exefileLocation 는 executableLocation 안에 있는 실행파일 trid.exe 의 전체 경로입니다.
            string exefileLocation = Path.Combine(executableLocation, "trid.exe");

            // cmd에서 실행했던 것 처럼 프로세스를 실행하기 위한 설정값이 들어간 process 클래스를 proc라는 변수명으로 생성합니다.
            var proc = new Process
            {
                StartInfo = new ProcessStartInfo
                {
                    FileName = exefileLocation,
                    Arguments = FileName,
                    UseShellExecute = false,
                    RedirectStandardOutput = true,
                    CreateNoWindow = true
                }
            };

            // 출력을 위한 datatable을 생성합니다.
            DataTable dt = new DataTable();
            dt.Columns.Add("%", typeof(string)); // 확률
            dt.Columns.Add("Ext", typeof(string)); // 확장자
            dt.Columns.Add("Desc", typeof(string)); // 설명

            proc.Start(); // 위에서 생성한 proc를 실행합니다.
            while (!proc.StandardOutput.EndOfStream)
            {
                string line1 = proc.StandardOutput.ReadLine(); // cmd에서 나왔던 결과를 1줄씩 가져옵니다.

                if (line1.Contains("%")) // 라인에 %가 있을 경우에만 동작하게 했습니다.
                {
                    string dtcol1 = line1.Split('%')[0]; // 확률정보만 가져옵니다.
                    dtcol1 += "%";
                    string dtcol2 = line1.Split('(')[1]; // 확장자(점포함) 정보만 가져옵니다.
                    dtcol2 = dtcol2.Split(')')[0];
                    string dtcol3 = line1.Split(')')[1]; // 설명부분만 가져옵니다.
                    dtcol3 = dtcol3.Split('(')[0];

                    dt.Rows.Add(dtcol1, dtcol2, dtcol3); // 위의 3가지 정보가 포함된 DataRow를 추가합니다.
                }
            }

            return dt;
        }

매서드2. 위에서 제공된 결과를 DataGridView 컨트롤에서 볼 수 있도록 가져옵니다.

        /// <summary>
        /// 선택한 폴더의 파일 목록을 가져와서 DataGridView 도구에 보여줍니다.
        /// </summary>
        /// <param name="dt1">선택한 폴더의 파일 목록이 들어있는 DataTable을 입력합니다.</param>
        /// <param name="dgv1">결과를 출력할 DataGridView를 선택합니다.</param>
        private void ShowDataFromDataTableToDataGridView(DataTable dt1, DataGridView dgv1)
        {
            dgv1.Rows.Clear(); // 이전 정보가 있을 경우, 모든 행을 삭제합니다.
            dgv1.Columns.Clear(); // 이전 정보가 있을 경우, 모든 열을 삭제합니다.

            foreach (DataColumn dc1 in dt1.Columns) // 선택한 파일 목록이 들어있는 DataTable의 모든 열을 스캔합니다.
            {
                dgv1.Columns.Add(dc1.ColumnName, dc1.ColumnName); // 출력할 DataGridView에 열을 추가합니다.
            }

            int row_index = 0; // 행 인덱스 번호(초기 값)
            foreach (DataRow dr1 in dt1.Rows) // 선택한 파일 목록이 들어있는 DataTable의 모든 행을 스캔합니다.
            {
                dgv1.Rows.Add(); // 빈 행을 하나 추가합니다.
                foreach (DataColumn dc1 in dt1.Columns) // 선택한 파일 목록이 들어있는 DataTable의 모든 열을 스캔합니다.
                {
                    dgv1.Rows[row_index].Cells[dc1.ColumnName].Value = dr1[dc1.ColumnName]; // 선택 행 별로, 스캔하는 열에 해당하는 셀 값을 입력합니다.
                }
                row_index++; // 다음 행 인덱스를 선택하기 위해 1을 더해줍니다.
            }

            foreach (DataGridViewColumn drvc1 in dgv1.Columns) // 결과를 출력할 DataGridView의 모든 열을 스캔합니다.
            {
                drvc1.AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells; // 선택 열의 너비를 자동으로 설정합니다.
            }
        }

위에서 만든 2개의 매서드를 활용하여 버튼클릭 이벤트를 아래와 같이 수정합니다.

        private void button1_Click(object sender, EventArgs e)
        {
            OpenFileDialog openFileDialog1 = new OpenFileDialog(); // OpenFileDialog 생성합니다.
            openFileDialog1.Multiselect = false; // 여러개 선택 못하게 합니다.
            if (openFileDialog1.ShowDialog() == DialogResult.OK) // 파일이 선택된 경우에만 실행되게 합니다.
            {
                label4.Text = openFileDialog1.FileName; // 선택한 폴더 이름을 label4에 출력합니다.
                DataTable dt_filelistinfo = GetResultsFromTridCMDStrings(openFileDialog1.FileName);
                ShowDataFromDataTableToDataGridView(dt_filelistinfo, dataGridView1);
            }
        }

전체 코드는 다음과 같습니다.

using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System; using System.Windows.Forms; using System.Data; // DataTable 사용 using System.IO; // Path 사용 using System.Reflection; // Assembly 사용 using System.Diagnostics; // Process 사용 namespace WindowsFormFileIdentifier { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { OpenFileDialog openFileDialog1 = new OpenFileDialog(); // OpenFileDialog 생성합니다. openFileDialog1.Multiselect = false; // 여러개 선택 못하게 합니다. if (openFileDialog1.ShowDialog() == DialogResult.OK) // 파일이 선택된 경우에만 실행되게 합니다. { label4.Text = openFileDialog1.FileName; // 선택한 폴더 이름을 label4에 출력합니다. DataTable dt_filelistinfo = GetResultsFromTridCMDStrings(openFileDialog1.FileName); ShowDataFromDataTableToDataGridView(dt_filelistinfo, dataGridView1); } } private DataTable GetResultsFromTridCMDStrings(string FileName) {             생략(매서드1) } private void ShowDataFromDataTableToDataGridView(DataTable dt1, DataGridView dgv1) {             생략(매서드2) } } }

이제 실행해 보겠습니다.
실행하면 다음과 같이 나타납니다.

파일 선택 버튼을 클릭하고 예제 파일에 있던 "unknownfile" 을 선택하면 다음과 같이 결과가 출력됩니다.

이제 위의 내용을 활용해서 확장자가 변경되었거나 확실하지 않은 파일이 있다면 이 프로그램으로 찾아서 바꿔주는 프로그래밍을 할 수 있습니다.

감사합니다.

이 글은 제가 검색하는 과정도 포함되어 있습니다.

윈도우에서 파일의 정보를 가져오기 위해서 기본적으로 사용하고 있는 클래스는 FileInfo 입니다.
하지만 어느 카메라로 찍었는지, 어디서 찍었는지 등에 대한 정보를 확인하기 위해서는 MetaData를 확인해야 합니다.

그래서 구글에서 검색을 시작하였습니다. 처음으로 검색한 단어는 "read image metadata c#" 입니다.
관련 코드를 쉽게 찾을 수 있었습니다.

출처: Reading data metadata from JPEG, XMP or EXIF in C#
주소: https://stackoverflow.com/questions/2280948/reading-data-metadata-from-jpeg-xmp-or-exif-in-c-sharp?utm_medium=organic&utm_source=google_rich_qa&utm_campaign=google_rich_qa

위 제공된 코드는 아래와 같습니다.

    public string GetDate(FileInfo f)
    {
        using(FileStream fs = new FileStream(f.FullName, FileMode.Open, FileAccess.Read, FileShare.Read))
        {
            BitmapSource img = BitmapFrame.Create(fs);
            BitmapMetadata md = (BitmapMetadata)img.Metadata;
            string date = md.DateTaken;
            Console.WriteLine(date);
            return date;
        }
    }

그래서 Visual Studio 에서 바로 실행해 보기로 했습니다.

1. Visual Studio(2017 기준) 를 실행하고 새로운 프로젝트를 생성합니다.
상단 메뉴의 파일(F) - 새로 만들기(N) - 프로젝트(P) 를 선택합니다.

좌측 메뉴에 Visual C# - Windows 클래식 바탕화면을 선택하고 가운데 메뉴에 Windows Forms 앱(,net Framework)를 선택합니다.
앱 이름은 WindowsFormsGetMetaData 로 정하겠습니다. 폴더는 원하는 위치를 지정해 주세요. 아래 그림과 같이 설정이 끝났으면 확인 버튼을 클릭합니다.

폼 이름 및 크기를 바꿔볼께요.
폼을 선택하고 속성 도구를 열고 Text와 Size 속성을 바꿉니다.
(Name): Form1 - Text: 메타데이터 읽기 / Size: 400, 600

다음에 컨트톨을 추가해 보겠습니다.
도구 상자탭을 선택하고 원하는 도구 상자를 드래그해서 폼 안에 넣으면 됩니다.

저는 아래와 같이 넣었습니다.

각 도구의 주요 속성은 다음과 같습니다.

버튼(Button) - (Name): button1 / Location: 20, 20 / AutoSize: False / Size: 75, 23 / Text: 파일 선택
라벨(Label) - (Name): label1 / Location: 20, 60 / AutoSize: True / Size: 73, 12(자동으로 설정됨) / Text: 선택된 파일:
라벨(Label) - (Name): label2 / Location: 100, 60 / AutoSize: True / Size: 29, 12(자동으로 설정됨) / Text: 없음
자료보기창(DataGridView) - (Name): dataGridView1 / Location: 20, 90 / AutoSize: False / Size: 350, 450

외형을 완성했으면 이제 프로그래밍을 해보겠습니다.
폴더 선택 버튼을 더블클릭하면 자동으로 이벤트가 추가되고 코드보기 화면으로 전환됩니다.

우선 버튼 클릭 부분에는 OpenFileDialog 를 생성해서 파일이 있으면 파일명을 MessageBox에서 보여주도록 코드를 작성하였습니다.

버튼클릭 이벤트 아래쪽에 위에서 찾은 코드를 복사합니다. 우선 FileInfo 는 using System.IO; 를 활용해서 불러옵니다.
이렇게 하면 아래 그림과 같이 오류가 발생합니다.

이제부터 오류가 발생하는 부분을 찾아보겠습니다.

BitmapSource 를 구글에서 찾아보니 아래 링크에서 해당 클래스 정보를 확인할 수 있습니다.
제목: BitmapSource 클래스
네임스페이스:   System.Windows.Media.Imaging
어셈블리:  PresentationCore(PresentationCore.dll에 있음)
https://msdn.microsoft.com/ko-kr/library/system.windows.media.imaging.bitmapsource(v=vs.110).aspx

위 내용을 보면 PresentationCore 어셈블리를 추가하면 될 것으로 보입니다.
아래 그림과 같이 솔루션 탐색기에서 참조에 마우스를 대고 오른쪽 버튼을 클릭한 후에 참조 추가 메뉴를 클릭합니다.

오른쪽 어셈블리에서 프레임워크를 선택하고 오른쪽 검색창에 "presentationcore" 를 검색하면 결과가 하나만 나타납니다.
추가하려면 이름 옆에 있는 체크박스를 클릭해서 체크표시 한 후에 확인 버튼을 클릭하면 PresentationCore 어셈블리를 사용할 수 있습니다.

그리고 코딩 파일에 "using System.Windows.Media.Imaging;" 을 입력해서 해당 네임 스페이스를 불러옵니다.
그러면 BitmapSource, BitmapFrame, BitmapMetadata 사용이 가능합니다. 하지만 여전히 "BitmapFrame.Create" 부분에서 오류가 발생하네요.
오류 내용은 다음과 같습니다.

'Freezable' 형식이 참조되지 않은 어셈블리에 정의되었습니다. 'WindowsBase, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' 어셈블리에 참조를 추가해야 합니다.

이 부분도 동일하게 해결 가능합니다.

솔루션 탐색기에서 참조에 마우스를 대고 오른쪽 버튼을 클릭한 후에 참조 추가 메뉴를 클릭합니다.
오른쪽 어셈블리에서 프레임워크를 선택하고 오른쪽 검색창에 "windowsbase" 를 검색하면 결과가 하나만 나타납니다.
추가하려면 이름 옆에 있는 체크박스를 클릭해서 체크표시 한 후에 확인 버튼을 클릭하면 WindowsBase 어셈블리를 사용할 수 있습니다.

이제 오류는 다 잡았습니다. 지금부터는 원하는 정보를 가져와서 DataGridView에 보여주면 되겠네요.
메서드1. 위에 제공된 코드를 아래와 같이 수정합니다. 기존 코드는 파일을 만든 날짜만 확인하였는데 전 확인 가능한 모든 속성을 가져오겠습니다.

        /// <summary>
        /// 선택한 파일의 메타데이터를 DataTable 형식으로 보냅니다.
        /// </summary>
        /// <param name="f">자료를 가져올 파일의 FileInfo를 입력합니다.</param>
        /// <returns></returns>
        private DataTable GetDate(FileInfo f)
        {
            using (FileStream fs = new FileStream(f.FullName, FileMode.Open, FileAccess.Read, FileShare.Read)) // 선택된 파일의 FileStream 을 생성합니다. 
            {
                DataTable dt1 = new DataTable(); // 새로운 DataTable을 생성합니다.
                dt1.Columns.Add("attribute"); // 속성 이름을 저장합니다.
                dt1.Columns.Add("value"); // 속성 값을 저장합니다.

                BitmapSource img = BitmapFrame.Create(fs); // 선택된 파일의 FileStream 를 활용하여 BitmapSource 를 생성합니다.
                BitmapMetadata md = (BitmapMetadata)img.Metadata; // 

                // BitmapMetadata 에서 제공하는 모든 속성 값을 불러옵니다. 시작
                // https://msdn.microsoft.com/ko-kr/library/system.windows.media.imaging.bitmapmetadata(v=vs.110).aspx
                dt1.Rows.Add("ApplicationName", md.ApplicationName);
                dt1.Rows.Add("Author", md.Author);
                dt1.Rows.Add("CameraManufacturer", md.CameraManufacturer);
                dt1.Rows.Add("CameraModel", md.CameraModel);
                dt1.Rows.Add("CanFreeze", md.CanFreeze);
                dt1.Rows.Add("Comment", md.Comment);
                dt1.Rows.Add("Copyright", md.Copyright);
                dt1.Rows.Add("DateTaken", md.DateTaken);
                dt1.Rows.Add("DependencyObjectType", md.DependencyObjectType);
                dt1.Rows.Add("Dispatcher", md.Dispatcher);
                dt1.Rows.Add("Format", md.Format);
                dt1.Rows.Add("IsFixedSize", md.IsFixedSize);
                dt1.Rows.Add("IsFrozen", md.IsFrozen);
                dt1.Rows.Add("IsReadOnly", md.IsReadOnly);
                dt1.Rows.Add("IsSealed", md.IsSealed);
                dt1.Rows.Add("Keywords", md.Keywords);
                dt1.Rows.Add("Location", md.Location);
                dt1.Rows.Add("Rating", md.Rating);
                dt1.Rows.Add("Subject", md.Subject);
                dt1.Rows.Add("Title", md.Title);
                // BitmapMetadata 에서 제공하는 모든 속성 값을 불러옵니다. 끝

                return dt1;
            }
        }


매서드2. 위에서 제공된 결과를 DataGridView 컨트롤에서 볼 수 있도록 가져옵니다.

        /// <summary>
        /// 선택한 폴더의 파일 목록을 가져와서 DataGridView 도구에 보여줍니다.
        /// </summary>
        /// <param name="dt1">선택한 폴더의 파일 목록이 들어있는 DataTable을 입력합니다.</param>
        /// <param name="dgv1">결과를 출력할 DataGridView를 선택합니다.</param>
        private void ShowDataFromDataTableToDataGridView(DataTable dt1, DataGridView dgv1)
        {
            dgv1.Rows.Clear(); // 이전 정보가 있을 경우, 모든 행을 삭제합니다.
            dgv1.Columns.Clear(); // 이전 정보가 있을 경우, 모든 열을 삭제합니다.

            foreach (DataColumn dc1 in dt1.Columns) // 선택한 파일 목록이 들어있는 DataTable의 모든 열을 스캔합니다.
            {
                dgv1.Columns.Add(dc1.ColumnName, dc1.ColumnName); // 출력할 DataGridView에 열을 추가합니다.
            }

            int row_index = 0; // 행 인덱스 번호(초기 값)
            foreach (DataRow dr1 in dt1.Rows) // 선택한 파일 목록이 들어있는 DataTable의 모든 행을 스캔합니다.
            {
                dgv1.Rows.Add(); // 빈 행을 하나 추가합니다.
                foreach (DataColumn dc1 in dt1.Columns) // 선택한 파일 목록이 들어있는 DataTable의 모든 열을 스캔합니다.
                {
                    dgv1.Rows[row_index].Cells[dc1.ColumnName].Value = dr1[dc1.ColumnName]; // 선택 행 별로, 스캔하는 열에 해당하는 셀 값을 입력합니다.
                }
                row_index++; // 다음 행 인덱스를 선택하기 위해 1을 더해줍니다.
            }

            foreach (DataGridViewColumn drvc1 in dgv1.Columns) // 결과를 출력할 DataGridView의 모든 열을 스캔합니다.
            {
                drvc1.AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells; // 선택 열의 너비를 자동으로 설정합니다.
            }
        }

위에서 만든 2개의 매서드를 활용하여 버튼클릭 이벤트를 아래와 같이 수정합니다.

        private void button1_Click(object sender, EventArgs e)
        {
            OpenFileDialog openFileDialog1 = new OpenFileDialog(); // 새로운 OpenFileDialog 를 생성합니다.
            if (openFileDialog1.ShowDialog() == DialogResult.OK) // 파일이 정상적으로 선택되었을 경우에 동작합니다.
            {
                label2.Text = openFileDialog1.FileName; // 선택된 파일을 label2에 출력합니다.
                FileInfo f = new FileInfo(openFileDialog1.FileName); // 파일 전체 경로로 해당 파일의 FileInfo를 생성합니다.
                DataTable dt_metadata = GetDate(f);
                ShowDataFromDataTableToDataGridView(dt_metadata,dataGridView1);
            }
        }

전체 코드는 아래와 같습니다.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

using System.IO;
using System.Windows.Media.Imaging;

namespace WindowsFormsGetMetaData
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            OpenFileDialog openFileDialog1 = new OpenFileDialog(); // 새로운 OpenFileDialog 를 생성합니다.
            if (openFileDialog1.ShowDialog() == DialogResult.OK) // 파일이 정상적으로 선택되었을 경우에 동작합니다.
            {
                label2.Text = openFileDialog1.FileName; // 선택된 파일을 label2에 출력합니다.
                FileInfo f = new FileInfo(openFileDialog1.FileName); // 파일 전체 경로로 해당 파일의 FileInfo를 생성합니다.
                DataTable dt_metadata = GetDate(f);
                ShowDataFromDataTableToDataGridView(dt_metadata,dataGridView1);
            }
        }

        /// <summary>
        /// 선택한 파일의 메타데이터를 DataTable 형식으로 보냅니다.
        /// </summary>
        /// <param name="f">자료를 가져올 파일의 FileInfo를 입력합니다.</param>
        /// <returns></returns>
        private DataTable GetDate(FileInfo f)
        {
            생략(매서드1)
        }

        /// <summary>
        /// 선택한 폴더의 파일 목록을 가져와서 DataGridView 도구에 보여줍니다.
        /// </summary>
        /// <param name="dt1">선택한 폴더의 파일 목록이 들어있는 DataTable을 입력합니다.</param>
        /// <param name="dgv1">결과를 출력할 DataGridView를 선택합니다.</param>
        private void ShowDataFromDataTableToDataGridView(DataTable dt1, DataGridView dgv1)
        {
            생략(매서드2)
        }

    }
}

이제 실행해 보겠습니다.
실행하면 다음과 같이 나타납니다.

메타데이터가 있는 그림파일을 선택하면 다음과 같이 읽어오는 것을 볼 수 있습니다.

하지만 윈도우 탐색기에서 파일 선택해서 마우스 오른쪽 버튼 클릭 후 속성 클릭 후 자세히 보기에 나타나는 정보는 기본적으로 제공하는 MetaData 보다 많은 것을 확인할 수 있습니다. 이 부분에 대해 아시는 분 있으면 댓글 남겨주세요. 저도 관련 정보를 더 찾아보도록 하겠습니다.

감사합니다.

안녕하세요. 윈도우 폼에서 폴더를 선택했을 때 파일 목록을 가져오는 방법에 대해 알아보겠습니다.

우선 프로그래밍을 하기 전에 어떤 내용을 만들지 정리해 볼께요.

1. 윈도우 폼에 하위폴더 포함 여부를 선택할 수 있는 체크박스를 추가한다
2. 버튼을 추가하여 버튼을 클릭하면 폴더를 선택할 수 있는 창이 나타나도록 설정한다.
3. 폴더 선택을 완료하면 하위폴더 포함 여부에 따라 파일 리스트를 출력한다.

그럼 위 내용대로 진행해 보겠습니다.

1. Visual Studio(2017 기준) 를 실행하고 새로운 프로젝트를 생성합니다.
상단 메뉴의 파일(F) - 새로 만들기(N) - 프로젝트(P) 를 선택합니다.

좌측 메뉴에 Visual C# - Windows 클래식 바탕화면을 선택하고 가운데 메뉴에 Windows Forms 앱(,net Framework)를 선택합니다.
앱 이름은 WindowsFormsFileList 로 정하겠습니다. 폴더는 원하는 위치를 지정해 주세요. 아래 그림과 같이 설정이 끝났으면 확인 버튼을 클릭합니다.

그러면 다음과 같은 화면이 나타납니다.(Visual Studio 설정여부에 따라 화면이 다르게 나타납니다.)

폼 이름 및 크기를 바꿔볼께요.
폼을 선택하고 속성 도구를 열고 Text와 Size 속성을 바꿉니다.
(Name): Form1 - Text: 선택 폴더의 파일 목록 가져오기 / Size: 800, 600

다음에 컨트톨을 추가해 보겠습니다.
도구 상자탭을 선택하고 원하는 도구 상자를 드래그해서 폼 안에 넣으면 됩니다.

저는 아래와 같이 넣었습니다.

각 도구의 주요 속성은 다음과 같습니다.

버튼(Button) - (Name): button1 / Location: 20, 20 / AutoSize: False / Size: 70, 20 / Text: 폴더 선택
확인상자(CheckBox) - (Name): checkBox1 / Location: 100, 22 / AutoSize: True / Size: 104, 16(자동으로 설정됨) / Text: 하위 폴더 포함
라벨(Label) - (Name): label1 / Location: 20, 50 / AutoSize: True / Size: 73, 12(자동으로 설정됨) / Text: 선택된 폴더:
라벨(Label) - (Name): label2 / Location: 100, 50 / AutoSize: True / Size: 29, 12(자동으로 설정됨) / Text: 없음
자료보기창(DataGridView) - (Name): dataGridView1 / Location: 20, 80 / AutoSize: False / Size: 750, 460

외형을 완성했으면 이제 프로그래밍을 해보겠습니다.
폴더 선택 버튼을 더블클릭하면 아래 그림과 같이 자동으로 이벤트가 추가되고 코드보기 화면으로 전환됩니다.

버튼 클릭 이벤트에 추가하기 전에 필요한 함수를 미리 만들어 보겠습니다.

시작하기 전에... 아래 코드를 작성하기 위해서 아래 클래스를 추가로 불러와야 합니다.

using System.IO;
using Microsoft.WindowsAPICodePack.Dialogs;

using Microsoft.WindowsAPICodePack.Dialogs; 을 불러오는 방법은 아래 글을 참고해 주세요.
글 제목: FolderBrowserDialog 보다 괜찮은 폴더 선택 화면 - CommonOpenFileDialog
링크: http://ilbbang.tistory.com/22

매서드1: 선택한 목록의 파일 및 정보를 DataTable 형식으로 보낼 수 있는 매서드를 아래와 같이 추가합니다.

        /// <summary>
        /// 선택한 폴더의 파일 목록을 DataTable형식으로 내보냅니다.
        /// </summary>
        /// <param name="FolderName">선택한 폴더의 전체 경로를 입력합니다.</param>
        /// <returns></returns>
        private DataTable GetFileListFromFolderPath(string FolderName)
        {
            DirectoryInfo di = new DirectoryInfo(FolderName); // 해당 폴더 정보를 가져옵니다.

            DataTable dt1 = new DataTable(); // 새로운 테이블 작성합니다.(FileInfo 에서 가져오기 원하는 속성을 열로 추가합니다.)
            dt1.Columns.Add("Folder", typeof(string)); // 파일의 폴더
            dt1.Columns.Add("FileName", typeof(string)); // 파일 이름(확장자 포함)
            dt1.Columns.Add("Extension", typeof(string)); // 확장자
            dt1.Columns.Add("CreationTime", typeof(DateTime)); // 생성 일자
            dt1.Columns.Add("LastWriteTime", typeof(DateTime)); // 마지막 수정 일자
            dt1.Columns.Add("LastAccessTime", typeof(DateTime)); // 마지막 접근 일자

            foreach (FileInfo File in di.GetFiles()) // 선택 폴더의 파일 목록을 스캔합니다.
            {
                dt1.Rows.Add(File.DirectoryName, File.Name, File.Extension, File.CreationTime, File.LastWriteTime, File.LastAccessTime); // 개별 파일 별로 정보를 추가합니다.
            }

            if(checkBox1.Checked == true) // 하위 폴더 포함될 경우
            {
                DirectoryInfo[] di_sub = di.GetDirectories(); // 하위 폴더 목록들의 정보 가져옵니다.
                foreach (DirectoryInfo di1 in di_sub) // 하위 폴더목록을 스캔합니다.
                {
                    foreach (FileInfo File in di1.GetFiles()) // 선택 폴더의 파일 목록을 스캔합니다.
                    {
                        dt1.Rows.Add(File.DirectoryName, File.Name, File.Extension, File.CreationTime, File.LastWriteTime, File.LastAccessTime); // 개별 파일 별로 정보를 추가합니다.
                    }
                }
            }
            
            return dt1;
        }

FileInfo 클래스에서 가져올 수 있는 속성은 아래 링크를 확인해 주세요.
https://msdn.microsoft.com/ko-kr/library/system.io.fileinfo(v=vs.110).aspx

매서드2: 위의 결과를 컨트롤에 보여줄 수 있는 매서드를 아래와 같이 추가합니다.

        /// <summary>
        /// 선택한 폴더의 파일 목록을 가져와서 DataGridView 도구에 보여줍니다.
        /// </summary>
        /// <param name="dt1">선택한 폴더의 파일 목록이 들어있는 DataTable을 입력합니다.</param>
        /// <param name="dgv1">결과를 출력할 DataGridView를 선택합니다.</param>
        private void ShowDataFromDataTableToDataGridView(DataTable dt1, DataGridView dgv1)
        {
            dgv1.Rows.Clear(); // 이전 정보가 있을 경우, 모든 행을 삭제합니다.
            dgv1.Columns.Clear(); // 이전 정보가 있을 경우, 모든 열을 삭제합니다.

            foreach (DataColumn dc1 in dt1.Columns) // 선택한 파일 목록이 들어있는 DataTable의 모든 열을 스캔합니다.
            {
                dgv1.Columns.Add(dc1.ColumnName, dc1.ColumnName); // 출력할 DataGridView에 열을 추가합니다.
            }

            int row_index = 0; // 행 인덱스 번호(초기 값)
            foreach(DataRow dr1 in dt1.Rows) // 선택한 파일 목록이 들어있는 DataTable의 모든 행을 스캔합니다.
            {
                dgv1.Rows.Add(); // 빈 행을 하나 추가합니다.
                foreach (DataColumn dc1 in dt1.Columns) // 선택한 파일 목록이 들어있는 DataTable의 모든 열을 스캔합니다.
                {
                    dgv1.Rows[row_index].Cells[dc1.ColumnName].Value = dr1[dc1.ColumnName]; // 선택 행 별로, 스캔하는 열에 해당하는 셀 값을 입력합니다.
                }
                row_index++; // 다음 행 인덱스를 선택하기 위해 1을 더해줍니다.
            }

            foreach(DataGridViewColumn drvc1 in dgv1.Columns) // 결과를 출력할 DataGridView의 모든 열을 스캔합니다.
            {
                drvc1.AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells; // 선택 열의 너비를 자동으로 설정합니다.
            }
        }

위 두개의 매서드가 포함된 버튼 클릭 이벤트를 다음과 같이 추가합니다.

        private void button1_Click(object sender, EventArgs e)
        {
            CommonOpenFileDialog dialog = new CommonOpenFileDialog(); // 새로운 폴더 선택 Dialog 를 생성합니다.
            dialog.IsFolderPicker = true; // 
            if (dialog.ShowDialog() == CommonFileDialogResult.Ok) // 폴더 선택이 정상적으로 되면 아래 코드를 실행합니다.
            {
                label2.Text = dialog.FileName; // 선택한 폴더 이름을 label2에 출력합니다.
                DataTable dt_filelistinfo = GetFileListFromFolderPath(dialog.FileName);
                ShowDataFromDataTableToDataGridView(dt_filelistinfo, dataGridView1);
            }
        }

전체 코드가 포함된 화면은 다음과 같습니다.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

using Microsoft.WindowsAPICodePack.Dialogs;
using System.IO;

namespace WindowsFormsFileList
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            CommonOpenFileDialog dialog = new CommonOpenFileDialog(); // 새로운 폴더 선택 Dialog 를 생성합니다.
            dialog.IsFolderPicker = true; // 
            if (dialog.ShowDialog() == CommonFileDialogResult.Ok) // 폴더 선택이 정상적으로 되면 아래 코드를 실행합니다.
            {
                label2.Text = dialog.FileName; // 선택한 폴더 이름을 label2에 출력합니다.
                DataTable dt_filelistinfo = GetFileListFromFolderPath(dialog.FileName);
                ShowDataFromDataTableToDataGridView(dt_filelistinfo, dataGridView1);
            }
        }

        private DataTable GetFileListFromFolderPath(string FolderName)
        {
            생략(매서드1)
        }

        private void ShowDataFromDataTableToDataGridView(DataTable dt1, DataGridView dgv1)
        {
            생략(매서드2)
        }
    }
}

실행하면 다음과 같이 나타납니다.

우선 하위 폴더 포함이 안되어 있을 경우에는 아래 그림과 같이 결과가 출력됩니다.

파위폴더 포함된 경우에는  아래 그림과 같이 결과가 출력됩니다.

감사합니다.

+ Recent posts