전산업무

[C#] 대용량 TEXT 파일 내 특정 열 DATA 추출 프로그램

소스코드 요리사 2018. 2. 4. 19:16

몇 일전 스팸서버 관련 로그를 협력업체로부터 CSV 파일을 받았습니다.


이 CSV 파일은 ID, 메일 송신자, 메일 수신자, 제목, 수신DATE 순으로 ' , ' 로 구분되어 있는 CSV 파일이었습니다.

근데, 문제는 이 파일이 50 GB 가 넘는 다는 거 였고 파일 수가 6개가 된다는 거였습니다.


그래서, 구글, 네이버 등의 검색사이트를 찾아서 대용량의 파일을 열 수 있는 프로그램을 찾았지만 마땅한 것이 없었습니다.

GNU 코어 유틸의 split 으로 파일을 짤라 편집을 하려하다가 편집시간도 많이 걸릴 것 같고 어짜피 일자별 메일 수신자만 추릴 필요가 있어서 C#으로 console 프로그램을 짜서 수신자만 추출해서 사용했습니다.


인터넷에서 마땅한 대용량 txt 파일 편집 에디터를 못찾으셨거나 대용량 txt 파일을 짜르거나 추출해야할 경우 

제가 첨부한 소스파일을 보시고 응용하시면 금방 원하시는대로(대용량파일을 쪼개서 저장하거나 특정 데이터를 추출한다던지 등) 

프로그램을 만들어 사용하실 수 있을 것으로 생각됩니다. 



using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace ConsoleApplication3
{
    class Program
    {
        static void Main(string[] args)
        {
            int counter = 0;
            int fileCounter = 0;
            string readLine, writeLine;
          
            // 파라메터가 있는 지 확인 : 파라메터는 읽어들일 '파일경로\파일명.확장자' 임.
            if (args.Length < 1)
            {
                System.Console.WriteLine("needs file name for reading.");
                return;
            }

            string readFileName = @args[0];  
            System.Console.WriteLine("read file : " + readFileName);

            string[] temp; 
            System.IO.StreamReader readFile = new System.IO.StreamReader(readFileName);

            // 편집 후 저장될 파일명 초기화
            string writeFileName = readFileName + fileCounter; 
            
            // 수신 이메일을 읽을 경우 리스트에 저장
            // 중복처리를 위함.
            List writedEmailList = new List();
                       
            int index = -1;
            string saveEmail = "";
            string[] temp2;

            // 파일 끝까지 라인단위로 Read.
            while ((readLine = readFile.ReadLine()) != null)
            {
                // 읽어들인 라인을 구분자(',') 로 쪼갬
                temp = readLine.Split(',');

                // 쪼갠 각 항목이 따옴표("")로 싸여있음. 따옴표를 삭제
                saveEmail = temp[2].Replace('"',' ').Trim();
              
                // 수신된 이메일이 이전에 수신한 적이 있는지 search
                index = writedEmailList.BinarySearch(saveEmail);

                if (index < 0)
                {
                    // write 할 라인을 저장
                    writeLine = saveEmail + "\r\n";
                    
                    // 50000줄을 write 하면 새롭게 파일을 만듦.
                    if (counter % 50000 == 0)
                    {
                        counter = 0;
                        writeFileName = readFileName + fileCounter;
                        System.IO.File.WriteAllText(writeFileName, writeLine);
                        writedEmailList.Insert(~index, saveEmail);

                        System.Console.WriteLine("Create file : " + writeFileName);
                        System.Console.WriteLine("=======================================================");

                        counter++;
                        fileCounter++;
                    }
                    else
                    {
                        System.IO.File.AppendAllText(writeFileName, writeLine);
                        writedEmailList.Insert(~index, saveEmail);
                        counter++;
                    }
                        System.Console.Write(writeLine);
                }
            }
         

            readFile.Close();
            System.Console.WriteLine("End read file!!! press enter key!!");
            System.Console.ReadLine();  
        }
    }
}