.NET에서 줄 바꿈으로 문자열을 나누는 가장 쉬운 방법은 무엇입니까?


806

.NET에서 문자열을 줄 바꿈으로 분할해야하며 문자열을 분할하는 유일한 방법은 Split 메서드를 사용하는 것입니다. 그러나 그렇게하면 개행 문자를 (쉽게) 나눌 수 없으므로 최선의 방법은 무엇입니까?


2
왜 그렇지 않습니까? 그냥 System.Environment.NewLine에 분할
aviraldg

16
그러나 당신은 그것을 string []로 감싸서 추가 인자를 추가해야합니다.
RCIX

답변:


1413

문자열을 분할하려면 문자열 배열을 취하는 오버로드를 사용해야합니다.

string[] lines = theText.Split(
    new[] { Environment.NewLine },
    StringSplitOptions.None
);

편집 :
텍스트에서 다른 유형의 줄 바꿈을 처리하려면 둘 이상의 문자열을 일치시키는 기능을 사용할 수 있습니다. 이렇게하면 줄 바꿈 유형 중 하나에서 올바르게 분할되고 텍스트에 빈 줄과 간격이 유지됩니다.

string[] lines = theText.Split(
    new[] { "\r\n", "\r", "\n" },
    StringSplitOptions.None
);

3
@RCIX : 메소드에 올바른 매개 변수를 보내는 것은 가능한 것보다 훨씬 간단한 것에 사용하기 때문에 약간 어색합니다. 적어도 프레임 워크 2 이전에는 정규 표현식을 사용하거나 문자열을 분리하기위한 고유 한 분할 루틴을
만들어야했습니다

4
@Leandro :이 Environment.NewLine속성에는 시스템의 기본 줄 바꿈이 포함되어 있습니다. 예를 들어 Windows 시스템의 경우입니다 "\r\n".
Guffa

3
@Leandro : 하나의 추측은 프로그램 이 각 줄의 끝에 a 를 \n남겨두고 분할 \r한 다음 줄 \r\n사이에 줄을 출력한다는 것입니다.
Guffa

3
@Samuel : ( \r\n다른 것 중에서) 이스케이프 시퀀스는 C # 컴파일러에 특별한 의미가 있습니다. VB에는 이스케이프 시퀀스가 ​​없으므로 대신 상수가 사용됩니다.
Guffa

2
다양한 OS의 파일을 허용하려면 시작 기호에 "\ n \ r"을 추가하고 구분 기호 목록 끝에 "\ r"을 추가 할 수도 있습니다. 그래도 성능에 대한 가치가 있는지 확실하지 않습니다. ( en.wikipedia.org/wiki/Newline )
user420667

121

를 사용하는 것은 StringReader어떻습니까?

using (System.IO.StringReader reader = new System.IO.StringReader(input)) {
    string line = reader.ReadLine();
}

13
이것은 내가 가장 좋아하는 것입니다. 나는 확장 방법으로 싸서 현재 줄을 반환합니다 : gist.github.com/ronnieoverby/7916886
Ronnie

3
이것은 내가 발견 한 유일한 비 정규식 솔루션입니다 .netcf 3.5
Carl

8
입력이 크면 어레이에 복사하는 것이 느리거나 메모리를 많이 사용하는 경우 특히 좋습니다.
Alejandro

1
쓰여진대로이 답변은 첫 번째 줄만 읽습니다. 이 답변에 추가해야하는 루프에 대해서는 Steve Cooper의 답변 을 참조하십시오 while.
ToolmakerSteve

48

다음과 같이 문자열을 아주 쉽게 분리 할 수 ​​있어야합니다.

aString.Split(Environment.NewLine.ToCharArray());

46
* nix 이외의 시스템에서 줄 바꿈 문자열의 개별 문자 (예 : CR 및 LF 문자)로 분할됩니다. 각 줄 사이에 여분의 빈 문자열이 생깁니다.
Guffa

내가 틀렸다면 정정하지만 문자 \와 n에서 분리되지 않습니까?
RCIX

7
@RCIX : 아니요. \ r 및 \ n 코드는 단일 문자를 나타냅니다. 문자열 "\ r \ n"은 4가 아닌 2 자입니다.
Guffa

10
StringSplitOptions.RemoveEmptyEntries 매개 변수를 추가하면 완벽하게 작동합니다.
Ruben

18
@Ruben : 아니요. 그렇지 않습니다. Serge는 그의 답변에서 이미 제안했으며, aldready는 보존해야 할 원본 텍스트의 빈 줄도 제거한다고 설명했습니다.
Guffa

34

문자열을 사용하지 마십시오. 일반 솔루션의 경우, 함수에서 사용하는 모든 위치 (원래 문자열 및 분할 복사본)를 메모리에서 더 많이 사용하므로 일반적인 솔루션으로 분할하십시오. 100MB 문서를 처리하는 32 비트 일괄 처리 응용 프로그램을 실행하면 8 개의 동시 스레드에서 문제가 발생할 수 있습니다. 내가 전에 거기에 있었던 것은 아닙니다 ...

대신 이와 같은 반복자를 사용하십시오.

    public static IEnumerable<string> SplitToLines(this string input)
    {
        if (input == null)
        {
            yield break;
        }

        using (System.IO.StringReader reader = new System.IO.StringReader(input))
        {
            string line;
            while( (line = reader.ReadLine()) != null)
            {
                yield return line;
            }
        }
    }

이를 통해 데이터를보다 효율적으로 메모리 순환 할 수 있습니다.

foreach(var line in document.SplitToLines()) 
{
    // one line at a time...
}

물론 메모리에 모든 것을 원한다면 이것을 할 수 있습니다.

var allTheLines = document.SplitToLines.ToArray();

나는 거기에 있었다 ... (큰 HTML 파일을 파싱하고 메모리가 부족하다). 예, 문자열을 피하십시오. string.Split을 사용하면 LOH ( Large Object Heap )를 사용할 수 있지만 100 % 확신 할 수는 없습니다.
Peter Mortensen

당신이 SplitToLines에 정적 방법 (당신이 dd는 것) 한 경우, 다음 방법을 수행 할 수 있습니다 blah.SplitToLines.. 예를 들면 document.SplitToLines...?
barlop

아, 나는 당신 this이 공식 매개 변수를 확장 방법으로 만드는 것을 보았습니다 .
barlop

26

Guffa의 답변에 따라 확장 클래스에서 다음을 사용하십시오.

public static string[] Lines(this string source) {
    return source.Split(new string[] { "\r\n", "\n" }, StringSplitOptions.None);
}

9

문자열 변수의 경우 s:

s.Split(new string[]{Environment.NewLine},StringSplitOptions.None)

이것은 환경의 줄 끝 정의를 사용합니다. Windows에서 줄 끝은 CR-LF (캐리지 리턴, 줄 바꿈) 또는 C #의 이스케이프 문자 \r\n입니다.

로 줄을 다시 조합하면 String.Join원래 문자열과 같으 므로 신뢰할 수있는 솔루션입니다 .

var lines = s.Split(new string[]{Environment.NewLine},StringSplitOptions.None);
var reconstituted = String.Join(Environment.NewLine,lines);
Debug.Assert(s==reconstituted);

하지 말아야 할 것 :

  • StringSplitOptions.RemoveEmptyEntries빈 줄에 구문상의 목적이있는 Markdown과 같은 마크 업이 중단되므로을 사용하십시오 .
  • new char[]{Environment.NewLine}Windows에서는 각 줄마다 빈 문자열 요소가 하나씩 만들어 지므로 separator 에서 split .

기본적으로 최고 등급의 승인 된 것과 동일한 대답이지만 좋은 단위 테스트와 경고가 있습니다.
vapcguy

8

정규식도 옵션입니다.

    private string[] SplitStringByLineFeed(string inpString)
    {
        string[] locResult = Regex.Split(inpString, "[\r\n]+");
        return locResult;
    }

7
빈 줄을 유지하면서 줄을 정확하게 일치 시키려면이 정규식 문자열이 더 좋습니다 "\r?\n".
Rory O'Kane

7

이 질문에 대한 다른 솔루션은 재사용 가능한 코드 분류에 속하지 않고 편리하지 않기 때문에 2 비트를 추가 할 것이라고 생각했습니다.

다음 코드 블록은 string객체를 확장하여 문자열을 사용할 때 자연스러운 방법으로 사용할 수 있도록합니다.

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

namespace System
{
    public static class StringExtensions
    {
        public static string[] Split(this string s, string delimiter, StringSplitOptions options = StringSplitOptions.None)
        {
            return s.Split(new string[] { delimiter }, options);
        }
    }
}

이제 .Split()다음과 같이 모든 문자열 에서 함수를 사용할 수 있습니다 .

string[] result;

// Pass a string, and the delimiter
result = string.Split("My simple string", " ");

// Split an existing string by delimiter only
string foo = "my - string - i - want - split";
result = foo.Split("-");

// You can even pass the split options parameter. When omitted it is
// set to StringSplitOptions.None
result = foo.Split("-", StringSplitOptions.RemoveEmptyEntries);

개행 문자를 분리하려면 "\n"또는 "\r\n"구분 기호 매개 변수로 전달 하십시오.

의견 : Microsoft가이 과부하를 구현하면 좋을 것입니다.


Environment.Newline\n또는 하드 코딩보다 선호됩니다 \r\n.
Michael Blackburn

3
@MichaelBlackburn-문맥이 없기 때문에 잘못된 문장입니다. Environment.Newline현재 운영 체제와 다른 라인 종료를 사용하는 파일 작업이 아닌 크로스 플랫폼 호환성을위한 것입니다. 자세한 내용은 여기를 참조하십시오 . 따라서 개발자의 작업 내용에 따라 다릅니다. Environment.Newline'하드 코딩'은 개발자에게 모든 권한을 부여하는 OS 간의 라인 리턴 유형에 일관성이 없음 을 보장합니다.
Kraang Prime

2
@MichaelBlackburn-무례 할 필요가 없습니다. 나는 단지 정보를 제공하고있었습니다. .Newline마법이 아니며, 후드 아래에서 유닉스 또는 Windows에서 실행 중인지 여부에 대한 스위치를 기반으로 위에 제공된 문자열 일뿐입니다. 가장 안전한 방법은 먼저 모든 "\ r \ n"에 대한 문자열 교체를 수행 한 다음 "\ n"으로 분할하는 것입니다. 사용 .Newline이 실패한 경우 줄 바꿈에 다른 방법을 사용하는 다른 프로그램에서 저장 한 파일로 작업 할 때입니다. 파일 읽기가 항상 현재 OS의 줄 바꿈을 사용할 때마다 알면 잘 작동합니다.
Kraang Prime

그래서 내가 듣고있는 것은 가장 읽기 쉬운 방법입니다 (아마도 더 많은 메모리 사용) foo = foo.Replace("\r\n", "\n"); string[] result = foo.Split('\n');. 이것이 모든 플랫폼에서 작동한다는 것을 올바르게 이해하고 있습니까?
John Doe

4

나는 현재 VB.NET 에서이 기능을 사용하고 있습니다 (다른 답변을 기반으로).

Private Shared Function SplitLines(text As String) As String()
    Return text.Split({Environment.NewLine, vbCrLf, vbLf}, StringSplitOptions.None)
End Function

먼저 플랫폼 로컬 개행을 분할하려고 시도한 다음 가능한 각 개행으로 폴백합니다.

나는 지금까지 하나의 수업에서만 이것을 필요로했습니다. 그게 바뀌면 아마Public 유틸리티 클래스로 옮기고 확장 메소드로 만들 것입니다.

좋은 측정을 위해 라인을 다시 결합하는 방법은 다음과 같습니다.

Private Shared Function JoinLines(lines As IEnumerable(Of String)) As String
    Return String.Join(Environment.NewLine, lines)
End Function

@Samuel-인용문에 주목하십시오. 그들은 실제로 그 의미를 가지고 있습니다. "\r"= return. "\r\n"= 리턴 + 줄 바꿈 (이 게시물과 승인 된 솔루션을
Kraang Prime

@Kraang Hmm .. 오랫동안 .NET과 함께 일하지 않았습니다. 많은 사람들이 잘못된 답변을 표명했다면 놀랐습니다. 나는 Guffa의 답변에 대해서도 언급했으며 거기에서 설명을 얻었습니다. 이 답변에 대한 내 의견을 삭제했습니다. 고마워요
사무엘

2

실제로 분할은 다음을 수행해야합니다.

//Constructing string...
StringBuilder sb = new StringBuilder();
sb.AppendLine("first line");
sb.AppendLine("second line");
sb.AppendLine("third line");
string s = sb.ToString();
Console.WriteLine(s);

//Splitting multiline string into separate lines
string[] splitted = s.Split(new string[] {System.Environment.NewLine}, StringSplitOptions.RemoveEmptyEntries);

// Output (separate lines)
for( int i = 0; i < splitted.Count(); i++ )
{
    Console.WriteLine("{0}: {1}", i, splitted[i]);
}

2
RemoveEmptyEntries 옵션은 텍스트에서 빈 줄을 제거합니다. 일부 상황에서는 바람직 할 수 있지만 일반 분할은 빈 줄을 유지해야합니다.
Guffa

네, 당신 말이 맞아요, 방금이 가정을 만들었습니다 ... 글쎄, 빈 줄은 흥미롭지 않습니다;)
MaciekTalaska

1
string[] lines = text.Split(
  Environment.NewLine.ToCharArray(), 
  StringSplitOptions.RemoveEmptyStrings);

RemoveEmptyStrings 옵션을 사용하면 \ n 뒤에 \ r로 인해 빈 항목 이 없어야 합니다.

(주석을 반영하도록 편집 :) 텍스트의 빈 줄도 버립니다. 이것은 일반적으로 내가 원하는 것이지만 귀하의 요구 사항이 아닐 수도 있습니다.


RemoveEmptyStrings 옵션은 빈 줄도 제거하므로 텍스트에 빈 줄이 있으면 제대로 작동하지 않습니다.
Guffa 2009

당신은 아마 진짜 빈 줄을 유지하고 싶을 것입니다 : \ r \ n \ r \ n
slim

0

나는 Environment.Newline에 대해 몰랐지만 이것이 매우 좋은 해결책이라고 생각합니다.

내 시도는 :

        string str = "Test Me\r\nTest Me\nTest Me";
        var splitted = str.Split('\n').Select(s => s.Trim()).ToArray();

추가 .Trim은 여전히 ​​존재할 수있는 모든 \ r 또는 \ n을 제거합니다 (예를 들어, 창에 있지만 x 줄 바꾸기 문자로 문자열을 분할하는 경우). 아마도 가장 빠른 방법은 아닙니다.

편집하다:

주석이 올바르게 지적되었으므로 줄의 시작 부분이나 줄 바꿈 전에 공백을 제거합니다. 해당 공백을 유지해야하는 경우 다른 옵션 중 하나를 사용하십시오.


트림은 들여 쓰기와 같이 줄의 시작과 끝에서 공백을 제거합니다.
Guffa

".Trim은 여전히 ​​존재하는 \ r 또는 \ n을 제거합니다"-ouch. 대신 강력한 코드를 작성하지 않겠습니까?
bzlm

어쩌면 나는 질문이 잘못되었지만 공백을 보존해야한다는 것이 분명하지 않았습니다. 물론 당신이 옳습니다. Trim ()도 공백을 제거합니다.
Max

1
@ 맥스 : 와우, 내가 상사에게 코드가 사양에서 특별히 배제되지 않은 것을 할 수 있다고 말할 때까지 기다리십시오 ...;)
Guffa

-2

바보 같은 대답 : 임시 파일에 쓰기 File.ReadLines

var s = "Hello\r\nWorld";
var path = Path.GetTempFileName();
using (var writer = new StreamWriter(path))
{
    writer.Write(s);
}
var lines = File.ReadLines(path);

1
var,이 변수의 유형을 정의하지 않는 한, 그래서 당신은 그 객체, 또는 어떤 객체가 나타내는를 사용하는 방법을 이해하지 않을 수 있습니다. 또한 이것은 줄을 쓰는 것을 보여주고 파일 이름을 지정조차하지 않으므로 작동하지 않을 것입니다. 그런 다음 읽을 때 파일 경로가 다시 지정되지 않습니다. 즉 가정 path이다 C:\Temp\test.txt, 당신은해야한다 string[] lines = File.ReadLines(path);.
vapcguy

1
@vapcguy 방금 무엇을 읽었습니까? -나는 당신이 말한 모든 것이 잘못 되었기 때문에 게시물을 다시 읽거나 콘솔 프로그램에서 디버깅하는 것이 좋습니다 | 경로는 Path.GetTempFileName | var는 C #에서 일반적이고 권장되는 정의입니다-변수의 유형을 정의하는 방식으로 ...... 편집 : 이것이 좋은 해결책이라고 말하지 않습니다
koanbock

@ koanbock 좋아, 그래서 나는 보았다 Path.GetTempFileName msdn.microsoft.com/en-us/library/...을 하고 그것을 말한다 는 0 바이트 파일 및 반환 "해당 파일의 전체 경로"를 만듭니다. 나는 이것을 전에 시도했지만 파일을 찾지 못했지만 대신 폴더 위치로 반환 되었기 때문에 예외가 발생했다고 맹세 할 수있다. 사용에 대한 인수를 알고 var있지만 변수 객체가 무엇인지 표시하지 않으므로 권장하지 않습니다. 난독 화합니다.
vapcguy

-3
using System.IO;

string textToSplit;

if (textToSplit != null)
{
    List<string> lines = new List<string>();
    using (StringReader reader = new StringReader(textToSplit))
    {
        for (string line = reader.ReadLine(); line != null; line = reader.ReadLine())
        {
            lines.Add(line);
        }
    }
}

-5

실제로는 매우 쉽습니다.

VB.NET :

Private Function SplitOnNewLine(input as String) As String
    Return input.Split(Environment.NewLine)
End Function

씨#:

string splitOnNewLine(string input)
{
    return input.split(environment.newline);
}

4
완전히 잘못되어 작동하지 않습니다. 또한 C #에서는 Environment.NewLineVB와 같습니다.
vapcguy

VB.NET의 줄 끝 식별자를 참조하십시오 . 새 줄에 대한 다른 옵션.
Peter Mortensen
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.