【CSV 로딩】TextFieldParser 대신 CsvParser 사용
2020/02/19 추가
CsvParser를 사용하지 않고 CsvReader에서 가능했습니다.
CSV 해설과 각 프로그래밍 언어의 구현 예
CSV 퍼스시 우려점
CSV를 퍼스 할 때, 단순히 1행씩 읽어들여, 콤마 「,」로 Split 하는 것만으로 부족한 데이터이면 좋지만, 실제로는 그렇게 할 수 없기 때문에, 이하와 같은 고려가 필요하게 된다 라고 생각합니다.
※전제 구분자:쉼표「,」
둘러싸는 문자:더블 쿼테이션 「"」
각 행의 열 수는 동일
CSV를 퍼스 할 때, 단순히 1행씩 읽어들여, 콤마 「,」로 Split 하는 것만으로 부족한 데이터이면 좋지만, 실제로는 그렇게 할 수 없기 때문에, 이하와 같은 고려가 필요하게 된다 라고 생각합니다.
※전제 구분자:쉼표「,」
둘러싸는 문자:더블 쿼테이션 「"」
각 행의 열 수는 동일
"a","b","c,d,e"
"a","""b","c"
"a","b
ccc","d"
"a",b,"c,d,e"
그 외에는, 데이터중에 탭 「\t」가 존재하는 등・・・
먼저 TextFieldParser를 사용해 보았습니다 ...
이런 데이터를 고려하면서 자전으로 퍼스 해 나가는 것은 꽤 힘들기 때문에, 라고 할까 나는 생각하는 것조차 그만뒀기 때문에···
(언젠가 도전하고 싶다)
유용한 클래스가 없거나 옛날 넷에서 찾았는데, TextFieldParser가 좋은 것 같았습니다.
TextFiledParser
.Net의 클래스이므로, 다른 오픈 소스의 파서와 비교해, 동작에 신뢰가 갖고, 컴플라이언스적으로 봐도 좋다고 생각했습니다.
실제로 상기 데이터를 읽어 보면 깨끗하게 퍼스 할 수 있습니다.
사용할 CSV
"ヘッダー1","ヘッダー2","ヘッダー3"
"a","b","c,d,e"
"a","""b","c"
"a","b
ccc","d"
"a",b,"c,d,e"
코드
using Microsoft.VisualBasic.FileIO;
using System;
using System.Linq;
using System.Text;
namespace TestProject.CSVParseTest
{
public class CSVParseTest
{
public void ReadCsv()
{
using (var parser = new TextFieldParser(@".\test.csv", Encoding.UTF8))
{
// 区切り文字
parser.Delimiters = new string[] { "," };
// 囲み文字あり
parser.HasFieldsEnclosedInQuotes = true;
while (!parser.EndOfData)
{
var values = parser.ReadFields();
values.ToList().ForEach(v =>
{
// わかりやすいようにパイプを入れる
Console.Write(v + "|");
});
// わかりやすいように改行
Console.WriteLine();
}
}
}
}
}
using System;
namespace TestProject.CSVParseTest
{
public class Program
{
public static void Main(string[] args)
{
try
{
var pTest = new CSVParseTest();
pTest.ReadCsv();
}
catch(Exception err)
{
Console.WriteLine(err.Message);
}
finally
{
Console.Read();
}
}
}
}
상기의 결과에 만족하고 있었습니다만, 다음과 같은 데이터의 경우에, 의도하지 않은 움직임이 되어 버렸습니다.
사용하는 CSV ※데이터중에 하늘의 개행이 들어간다
"ヘッダー1","ヘッダー2","ヘッダー3"
"a","b","c,d,e"
"a","""b","c"
"a","b
gggg
ffff
ccc","d"
"a",b,"c,d,e"
결과
데이터 중에도 빈 줄이 삭제되는 것 같습니다.
게시판 등의 비고란 등의 텍스트에는, 자주(잘) 공행을 넣어 본 눈을 정돈하는 일이 있을까라고 생각합니다.
그러한 데이터를 취급할 수 없게 되는 것은 곤란하기 때문에 불채용으로 했습니다.
CsvHelper의 CsvParser 클래스 사용
그 외를 맞이하게 되어, 인기의 CsvHelper를 검토하고 있었습니다.
CsvHelper
다만, 이것을 이용하는 경우, CSV의 포맷에 따른 엔티티의 클래스를 준비할 필요가,
CSV의 열수가 나중에 변경이 되거나 하면, 매번 프로그램 소스도 수정해야 한다고 생각했기 때문에 주저하고 있었습니다.
TextFiledParser와 같이 1행분의 문자를 단락 문자로 split해 배열로 돌려주면...
또한, 공행도 재현해 주면 ...
그렇다고 생각하면 CsvHelper.CsvParser의 Read 메서드가 그것이었습니다.
using CsvHelper;
using System;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
namespace TestProject.CSVParseTest
{
public class CSVParseTest2
{
public void ReadCsv()
{
using(var stream = new StreamReader(@".\test.csv", Encoding.UTF8))
using (var parser = new CsvParser(stream, CultureInfo.InvariantCulture))
{
string[] line;
while ((line = parser.Read()) != null)
{
line.ToList().ForEach(v =>
{
// わかりやすいようにパイプを入れる
Console.Write(v + "|");
});
// わかりやすいように改行
Console.WriteLine();
}
}
}
}
}
"TextFieldParser + 빈 줄이 삭제되지 않음"이 실현되었습니다.
결론
CsvHelper안은 아마 1문자씩 처리해, 퍼스하고 있다고 생각합니다.
언젠가 내용을 보고 공부하고 싶습니다.
오인이나, 다른 방법으로 해결할 수 있는 등, 있으면 지적해 주시면 고맙습니다.
Reference
이 문제에 관하여(【CSV 로딩】TextFieldParser 대신 CsvParser 사용), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/GodPhwng/items/603814493d853a5f1ff6
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
"ヘッダー1","ヘッダー2","ヘッダー3"
"a","b","c,d,e"
"a","""b","c"
"a","b
ccc","d"
"a",b,"c,d,e"
using Microsoft.VisualBasic.FileIO;
using System;
using System.Linq;
using System.Text;
namespace TestProject.CSVParseTest
{
public class CSVParseTest
{
public void ReadCsv()
{
using (var parser = new TextFieldParser(@".\test.csv", Encoding.UTF8))
{
// 区切り文字
parser.Delimiters = new string[] { "," };
// 囲み文字あり
parser.HasFieldsEnclosedInQuotes = true;
while (!parser.EndOfData)
{
var values = parser.ReadFields();
values.ToList().ForEach(v =>
{
// わかりやすいようにパイプを入れる
Console.Write(v + "|");
});
// わかりやすいように改行
Console.WriteLine();
}
}
}
}
}
using System;
namespace TestProject.CSVParseTest
{
public class Program
{
public static void Main(string[] args)
{
try
{
var pTest = new CSVParseTest();
pTest.ReadCsv();
}
catch(Exception err)
{
Console.WriteLine(err.Message);
}
finally
{
Console.Read();
}
}
}
}
"ヘッダー1","ヘッダー2","ヘッダー3"
"a","b","c,d,e"
"a","""b","c"
"a","b
gggg
ffff
ccc","d"
"a",b,"c,d,e"
그 외를 맞이하게 되어, 인기의 CsvHelper를 검토하고 있었습니다.
CsvHelper
다만, 이것을 이용하는 경우, CSV의 포맷에 따른 엔티티의 클래스를 준비할 필요가,
CSV의 열수가 나중에 변경이 되거나 하면, 매번 프로그램 소스도 수정해야 한다고 생각했기 때문에 주저하고 있었습니다.
TextFiledParser와 같이 1행분의 문자를 단락 문자로 split해 배열로 돌려주면...
또한, 공행도 재현해 주면 ...
그렇다고 생각하면 CsvHelper.CsvParser의 Read 메서드가 그것이었습니다.
using CsvHelper;
using System;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
namespace TestProject.CSVParseTest
{
public class CSVParseTest2
{
public void ReadCsv()
{
using(var stream = new StreamReader(@".\test.csv", Encoding.UTF8))
using (var parser = new CsvParser(stream, CultureInfo.InvariantCulture))
{
string[] line;
while ((line = parser.Read()) != null)
{
line.ToList().ForEach(v =>
{
// わかりやすいようにパイプを入れる
Console.Write(v + "|");
});
// わかりやすいように改行
Console.WriteLine();
}
}
}
}
}
"TextFieldParser + 빈 줄이 삭제되지 않음"이 실현되었습니다.
결론
CsvHelper안은 아마 1문자씩 처리해, 퍼스하고 있다고 생각합니다.
언젠가 내용을 보고 공부하고 싶습니다.
오인이나, 다른 방법으로 해결할 수 있는 등, 있으면 지적해 주시면 고맙습니다.
Reference
이 문제에 관하여(【CSV 로딩】TextFieldParser 대신 CsvParser 사용), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/GodPhwng/items/603814493d853a5f1ff6
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
Reference
이 문제에 관하여(【CSV 로딩】TextFieldParser 대신 CsvParser 사용), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/GodPhwng/items/603814493d853a5f1ff6텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)