상세 컨텐츠

본문 제목

C#으로 텍스트 파일 읽고 문자열 분리하기

컴퓨터 언어/C#

by cepiloth 2021. 4. 29. 16:41

본문

728x90
반응형

 일하다가 1000 라인에 문자열을 파싱 해서 첫 번째 문자열 정보를 prefix를 변경해야 하는 문제가 생겼다. Notepad++ Macro 기능을 사용해서 작업하려다가 그냥 C#으로 홀딱 해버리면 쉬울 거 같아서 시작했다. 역시 C++만 하다가 다른 언어 하니까 신세계 편함.. ㅠ

C++ 무시하지 마 - (Feat. 페이몬 )

 

C#에서는 StreamReader class를 통하여 파일을 읽을 수 있다.

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

namespace ConsoleReadWrite
{
    class Program
    {
        static void Main(string[] args)
        {
            StreamReader sr = new StreamReader("e:test.txt"); 
            while (sr.Peek() >= 0) 
            { 
                Console.WriteLine(sr.ReadLine()); 
            } sr.Close();

            Console.WriteLine("Hello World!");
        }
    }
}


위에 코드에서는 sr.ReadLine() 메서드로 한 줄을 읽고 출력을 하였다. 지역 변수 String를 하나 선언하여서 콘솔(Console)에 출력해보자.

StreamReader sr = new StreamReader("e:test.txt"); 
while (sr.Peek() >= 0) 
{
	String s = sr.ReadLine().ToString();
	Console.WriteLine(s); 
} 
sr.Close();


위 코드의 출력 결과이다.

읽어온 문자열을 " " 기준으로 분리해보자. String Class에서 제공하는 Spilit 메서드로 간단하게 분리할 수 있다.

StreamReader sr = new StreamReader("e:test.txt"); 
while (sr.Peek() >= 0) 
{
	// 1. 첫 라인을 읽어서 문자열로 변환
	String s = sr.ReadLine().ToString();

	// " " 기준으로 문자열 분리
	String[] s2 = s.Split(" ", StringSplitOptions.None);

	Console.WriteLine(s); 
} 
sr.Close();


Spilit 함수는 " " 기준으로 문자열을 분리하다 보니 " " 문자가 이어지는 경우에 아래와 같이 많은 문자 배열을 생성된 것을 확인할 수 있다.

 

입력으로 들어오는 문자열은 아래와 같다.
"_TIFFCleanup 05fa7900 f libtiff:tif_close.obj"
의도한 결과는 아래와 같은 형태를 원했다. 중복되는 공백 문자열 덕분에 위처럼 의도하지 않은 결과가 나왔다. "_TIFFCleanup 05fa7900 f libtiff:tif_close.obj"

연속되는 공백 문자열을 하나로 만드는 함수를 만들어 보자.

/// <summary>
/// ToBlankMerge 메서드
/// </summary>
/// <param name="input">첫번째 인자 </param>
/// <returns> 공백 문자열을 하나로 병합하여 반환
/// </returns>
static String ToBlankMerge(String input)
{
	String result = "";

	bool prevBlank = false;
	for(int i=0; i< input.Length; i++)
	{
		char code = input[i];
		if (code == ' ') {
			
			prevBlank = true;
			continue;
		}
		else {
			
			if(prevBlank == true) {
				prevBlank = false;
				result += " ";
			}
			result += code;
		}
	}
	return result;
}

 

조사식을 확인해 본 결과 필자가 원하는 결과가 나왔다.

읽어오는 문자열에 중복되는 문자열이 있다. C#에서 제공하는 Dictionary를 활용하여 중복된 문자열을 제거하고 출력해보자.

Dictionary<String, int> Dic = new Dictionary<String, int>();
while (sr.Peek() >= 0) 
{
	// 1. 첫 라인을 읽어서 문자열로 변환
	String s = sr.ReadLine().ToString();

	// 2._TIFFCleanup 05fa7900 f libtiff:tif_close.obj 형태로 공백 문자열을 하나로 만들어줌
	s = ToBlankMerge(s);
	
	// 3. " " 기준으로 문자열 분리
	String[] sArray = s.Split(SEPERATOR, StringSplitOptions.None);
	s = sArray[0];

	if(Dic.ContainsKey(s).Equals(false)) {
		Dic.Add(s, 0);
	}
} 


Dictionary<String, int> Dic = new Dictionary<String, int>() 선언을 한다. ContainKey() 메서드를 활용하여 중복되는 원소가 없는 경우에 Dic에 삽입하도록 한다. 중복된 Key 가 있는지 검사하기 때문에 중복된 원소가 삽입되는 것을 방지할 수 있다.

String s = sArray[0];

if(Dic.ContainsKey(s).Equals(false)) {
	Dic.Add(s, 0);
}


Dictionary 를 출력할 때는 KeyValuePair 를 사용하여 출력 하였다.

foreach(KeyValuePair<String, int> pair in Dic)
{
	Console.WriteLine("{0}", pair.Key);
}

503 개의 중복없는 메소드가 출력되었다. 이제 prefix 작업 편하게 할 수 있겠다.

 

이왕 하는김에 파일에다가 다 Write 까지 해보자 StreamWriter Class 를 사용하여 Dictionary 에 있는 데이터와 prefix 를 적용하여 파일에 쓰는 코드이다.

StreamWriter sw = new StreamWriter(new FileStream("e:test_after.txt", FileMode.Create));
foreach (KeyValuePair<String, int> pair in Dic)
{
	//Console.WriteLine("{0}", pair.Key);
	String prefix = "cat_";
	prefix += pair.Key;
	sw.WriteLine("{0}", prefix);
}
sw.Close();

 

원하는 결과가 나왔다 만쉐이~

 

전체 소스 코드

using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.InteropServices.ComTypes;

namespace ConsoleReadWrite
{
    class Program
    {
        /// <summary>
        /// ToBlankMerge 메서드
        /// </summary>
        /// <param name="input">첫번째 인자 </param>
        /// <returns> 공백 문자열을 하나로 병합하여 반환
        /// </returns>
        static String ToBlankMerge(String input)
        {
            String result = "";

            bool prevBlank = false;
            for(int i=0; i< input.Length; i++)
            {
                char code = input[i];
                if (code == ' ') {
                    
                    prevBlank = true;
                    continue;
                }
                else {
                    
                    if(prevBlank == true) {
                        prevBlank = false;
                        result += " ";
                    }
                    result += code;
                }
            }
            return result;
        }

        /// <summary>
        /// Split 메서드에서 문자열을 분리할 기준 문자
        /// </summary>
        static String SEPERATOR = " ";

        static void Main(string[] args)
        {
            StreamReader sr = new StreamReader("e:test.txt");

            Dictionary<String, int> Dic = new Dictionary<String, int>();
            while (sr.Peek() >= 0) 
            {
                // 1. 첫 라인을 읽어서 문자열로 변환
                String s = sr.ReadLine().ToString();

                // 2._TIFFCleanup 05fa7900 f libtiff:tif_close.obj 형태로 공백 문자열을 하나로 만들어줌
                s = ToBlankMerge(s);
                
                // 3. " " 기준으로 문자열 분리
                String[] sArray = s.Split(SEPERATOR, StringSplitOptions.None);
                s = sArray[0];
                if(Dic.ContainsKey(s).Equals(false)) {
                    Dic.Add(s, 0);
                }
            } 
            sr.Close();

            StreamWriter sw = new StreamWriter(new FileStream("e:test_after.txt", FileMode.Create));
            foreach (KeyValuePair<String, int> pair in Dic)
            {
                //Console.WriteLine("{0}", pair.Key);
                String prefix = "cat_";
                prefix += pair.Key;
                sw.WriteLine("{0}", prefix);
            }
            sw.Close();
        }
    }
}


728x90
반응형

관련글 더보기

댓글 영역