파일을 읽으려고합니다 *.csv
.
*.csv
- 파일들은 세미콜론으로 분리 된 두 열의 구성 ( " , ").
*.csv
StreamReader를 사용 하여 -file 을 읽을 수 있으며 Split()
함수 를 사용하여 각 줄을 구분할 수 있습니다. 각 열을 별도의 배열에 저장하고 표시하고 싶습니다.
그렇게 할 수 있습니까?
파일을 읽으려고합니다 *.csv
.
*.csv
- 파일들은 세미콜론으로 분리 된 두 열의 구성 ( " , ").
*.csv
StreamReader를 사용 하여 -file 을 읽을 수 있으며 Split()
함수 를 사용하여 각 줄을 구분할 수 있습니다. 각 열을 별도의 배열에 저장하고 표시하고 싶습니다.
그렇게 할 수 있습니까?
답변:
다음과 같이 할 수 있습니다 :
using System.IO;
static void Main(string[] args)
{
using(var reader = new StreamReader(@"C:\test.csv"))
{
List<string> listA = new List<string>();
List<string> listB = new List<string>();
while (!reader.EndOfStream)
{
var line = reader.ReadLine();
var values = line.Split(';');
listA.Add(values[0]);
listB.Add(values[1]);
}
}
}
using
여기에 절을하거나, 적어도 수동으로 그것을로의 자원. Close()
reader
IDisposible
column1;"Special ; char in string";column3
- tools.ietf.org
내가 좋아하는 CSV 파서는 .NET 라이브러리에 내장 된 것입니다. 이것은 Microsoft.VisualBasic 네임 스페이스의 숨겨진 보물입니다. 다음은 샘플 코드입니다.
using Microsoft.VisualBasic.FileIO;
var path = @"C:\Person.csv"; // Habeeb, "Dubai Media City, Dubai"
using (TextFieldParser csvParser = new TextFieldParser(path))
{
csvParser.CommentTokens = new string[] { "#" };
csvParser.SetDelimiters(new string[] { "," });
csvParser.HasFieldsEnclosedInQuotes = true;
// Skip the row with the column names
csvParser.ReadLine();
while (!csvParser.EndOfData)
{
// Read current line fields, pointer moves to the next line.
string[] fields = csvParser.ReadFields();
string Name = fields[0];
string Address = fields[1];
}
}
참조를 추가해야합니다 Microsoft.VisualBasic
파서에 대한 자세한 내용은 여기에 있습니다 : http://codeskaters.blogspot.ae/2015/11/c-easiest-csv-parser-built-in-net.html
Microsoft.VisualBasic
일반적으로 기본적으로 참조되지 않으므로 프레임 워크 어셈블리에 대한 참조를 포함해야합니다 .
LINQ 방식 :
var lines = File.ReadAllLines("test.txt").Select(a => a.Split(';'));
var csv = from line in lines
select (from piece in line
select piece);
^^ 잘못-Nick이 편집
원래 응답자가 csv
2 차원 배열 (배열을 포함하는 배열) 로 채우려 고 시도한 것 같습니다 . 첫 번째 배열의 각 항목에는 해당 특정 열에 대한 데이터가 포함 된 중첩 배열의 각 항목과 해당 행 번호를 나타내는 배열이 포함됩니다.
var csv = from line in lines
select (line.Split(',')).ToArray();
처음부터 행 수를 알아야하기 때문에 즉시 배열을 만들 수 없습니다 (CSV 파일을 두 번 읽어야 함).
값을 두 개로 저장 List<T>
한 다음 사용하거나 배열을 사용하여 배열로 변환 할 수 있습니다.List<T>.ToArray()
매우 간단한 예 :
var column1 = new List<string>();
var column2 = new List<string>();
using (var rd = new StreamReader("filename.csv"))
{
while (!rd.EndOfStream)
{
var splits = rd.ReadLine().Split(';');
column1.Add(splits[0]);
column2.Add(splits[1]);
}
}
// print column1
Console.WriteLine("Column 1:");
foreach (var element in column1)
Console.WriteLine(element);
// print column2
Console.WriteLine("Column 2:");
foreach (var element in column2)
Console.WriteLine(element);
NB
이것은 매우 간단한 예일 뿐입니다 . string.Split
일부 레코드에는 분리 기호가 포함 된 경우를 사용 하지 않습니다 ;
.
보다 안전한 접근을 위해서는 nuget에서 CsvHelper와 같은 일부 CSV 전용 라이브러리를 사용하십시오.
;
예를 들어 값의 일부가되는 것은 아닙니다 "value with ; inside it"
. 리터럴 문자열을 나타 내기 위해 큰 따옴표가있는 특수 문자를 포함하는 CSV 서라운드 값.
이 라이브러리를 보았습니다 : https://github.com/JoshClose/CsvHelper
매우 직관적이고 사용하기 쉽습니다. 너겟 패키지도 너무 빨리 구현했다 : http://nuget.org/packages/CsvHelper/1.17.0 . 또한 내가 좋아하는 적극적으로 유지되는 것처럼 보입니다.
세미콜론을 사용하도록 쉽게 구성 할 수 있습니다 : https://github.com/JoshClose/CsvHelper/wiki/Custom-Configurations
Microsoft.VisualBasic.FileIO.TextFieldParser
됩니까 (@Habeeb의 답변 참조)?
나는 일반적으로 codeproject 에서이 파서를 사용합니다 . 왜냐하면 많은 문자 이스케이프와 비슷한 것이 있기 때문입니다.
다음은 가장 많이 투표 된 답변의 변형입니다.
var contents = File.ReadAllText(filename).Split('\n');
var csv = from line in contents
select line.Split(',').ToArray();
csv
변수는 다음 예와 같이 사용될 수있다 :
int headerRows = 5;
foreach (var row in csv.Skip(headerRows)
.TakeWhile(r => r.Length > 1 && r.Last().Trim().Length > 0))
{
String zerothColumnValue = row[0]; // leftmost column
var firstColumnValue = row[1];
}
(헤드 라인) 및 / 또는 열을 건너 뛰어야하는 경우이를 사용하여 2 차원 배열을 만들 수 있습니다.
var lines = File.ReadAllLines(path).Select(a => a.Split(';'));
var csv = (from line in lines
select (from col in line
select col).Skip(1).ToArray() // skip the first column
).Skip(2).ToArray(); // skip 2 headlines
이것은 데이터를 더 처리하기 전에 데이터를 구체화 해야하는 경우에 매우 유용합니다 (처음 두 줄이 헤드 라인으로 구성되고 첫 번째 열이 행 제목이라고 가정하면 배열에 없어도됩니다. 데이터를 고려하고 싶습니다).
NB 다음 코드를 사용하여 헤드 라인과 첫 번째 열을 쉽게 얻을 수 있습니다.
var coltitle = (from line in lines
select line.Skip(1).ToArray() // skip 1st column
).Skip(1).Take(1).FirstOrDefault().ToArray(); // take the 2nd row
var rowtitle = (from line in lines select line[0] // take 1st column
).Skip(2).ToArray(); // skip 2 headlines
이 코드 예제는 다음과 같은 *.csv
파일 구조를 가정 합니다.
참고 : 빈 행을 건너 뛸 필요가있는 경우-때로는 편리하게 삽입 할 수 있습니다.
where line.Any(a=>!string.IsNullOrWhiteSpace(a))
위 의 LINQ 코드 예제 에서 from
와 select
문 사이
성능 향상을 위해 C #에서 Microsoft.VisualBasic.FileIO.TextFieldParser dll을 사용할 수 있습니다.
위 기사에서 코드 예제를 얻습니다.
static void Main()
{
string csv_file_path=@"C:\Users\Administrator\Desktop\test.csv";
DataTable csvData = GetDataTabletFromCSVFile(csv_file_path);
Console.WriteLine("Rows count:" + csvData.Rows.Count);
Console.ReadLine();
}
private static DataTable GetDataTabletFromCSVFile(string csv_file_path)
{
DataTable csvData = new DataTable();
try
{
using(TextFieldParser csvReader = new TextFieldParser(csv_file_path))
{
csvReader.SetDelimiters(new string[] { "," });
csvReader.HasFieldsEnclosedInQuotes = true;
string[] colFields = csvReader.ReadFields();
foreach (string column in colFields)
{
DataColumn datecolumn = new DataColumn(column);
datecolumn.AllowDBNull = true;
csvData.Columns.Add(datecolumn);
}
while (!csvReader.EndOfData)
{
string[] fieldData = csvReader.ReadFields();
//Making empty value as null
for (int i = 0; i < fieldData.Length; i++)
{
if (fieldData[i] == "")
{
fieldData[i] = null;
}
}
csvData.Rows.Add(fieldData);
}
}
}
catch (Exception ex)
{
}
return csvData;
}
안녕, 나는 이것을하기위한 정적 클래스를 만들었습니다. + 열 확인 + 할당량 부호 제거
public static class CSV
{
public static List<string[]> Import(string file, char csvDelimiter, bool ignoreHeadline, bool removeQuoteSign)
{
return ReadCSVFile(file, csvDelimiter, ignoreHeadline, removeQuoteSign);
}
private static List<string[]> ReadCSVFile(string filename, char csvDelimiter, bool ignoreHeadline, bool removeQuoteSign)
{
string[] result = new string[0];
List<string[]> lst = new List<string[]>();
string line;
int currentLineNumner = 0;
int columnCount = 0;
// Read the file and display it line by line.
using (System.IO.StreamReader file = new System.IO.StreamReader(filename))
{
while ((line = file.ReadLine()) != null)
{
currentLineNumner++;
string[] strAr = line.Split(csvDelimiter);
// save column count of dirst line
if (currentLineNumner == 1)
{
columnCount = strAr.Count();
}
else
{
//Check column count of every other lines
if (strAr.Count() != columnCount)
{
throw new Exception(string.Format("CSV Import Exception: Wrong column count in line {0}", currentLineNumner));
}
}
if (removeQuoteSign) strAr = RemoveQouteSign(strAr);
if (ignoreHeadline)
{
if(currentLineNumner !=1) lst.Add(strAr);
}
else
{
lst.Add(strAr);
}
}
}
return lst;
}
private static string[] RemoveQouteSign(string[] ar)
{
for (int i = 0;i< ar.Count() ; i++)
{
if (ar[i].StartsWith("\"") || ar[i].StartsWith("'")) ar[i] = ar[i].Substring(1);
if (ar[i].EndsWith("\"") || ar[i].EndsWith("'")) ar[i] = ar[i].Substring(0,ar[i].Length-1);
}
return ar;
}
}
var firstColumn = new List<string>();
var lastColumn = new List<string>();
// your code for reading CSV file
foreach(var line in file)
{
var array = line.Split(';');
firstColumn.Add(array[0]);
lastColumn.Add(array[1]);
}
var firstArray = firstColumn.ToArray();
var lastArray = lastColumn.ToArray();
다음은 데이터 필드 중 하나에 세미콜론 ( ";")이 데이터의 일부로 포함 된 특별한 경우입니다.이 경우 위의 대부분의 답변이 실패합니다.
해결책은 그 경우가 될 것입니다
string[] csvRows = System.IO.File.ReadAllLines(FullyQaulifiedFileName);
string[] fields = null;
List<string> lstFields;
string field;
bool quoteStarted = false;
foreach (string csvRow in csvRows)
{
lstFields = new List<string>();
field = "";
for (int i = 0; i < csvRow.Length; i++)
{
string tmp = csvRow.ElementAt(i).ToString();
if(String.Compare(tmp,"\"")==0)
{
quoteStarted = !quoteStarted;
}
if (String.Compare(tmp, ";") == 0 && !quoteStarted)
{
lstFields.Add(field);
field = "";
}
else if (String.Compare(tmp, "\"") != 0)
{
field += tmp;
}
}
if(!string.IsNullOrEmpty(field))
{
lstFields.Add(field);
field = "";
}
// This will hold values for each column for current row under processing
fields = lstFields.ToArray();
}
오픈 소스 Angara.Table 라이브러리를 사용하면 CSV를 유형이 지정된 열에로드 할 수 있으므로 열에서 배열을 가져올 수 있습니다. 각 열은 이름 또는 색인으로 색인화 할 수 있습니다. http://predictionmachines.github.io/Angara.Table/saveload.html을 참조 하십시오 .
라이브러리는 CSV의 RFC4180을 따릅니다. 형식 유추 및 여러 줄 문자열을 활성화합니다.
예:
using System.Collections.Immutable;
using Angara.Data;
using Angara.Data.DelimitedFile;
...
ReadSettings settings = new ReadSettings(Delimiter.Semicolon, false, true, null, null);
Table table = Table.Load("data.csv", settings);
ImmutableArray<double> a = table["double-column-name"].Rows.AsReal;
for(int i = 0; i < a.Length; i++)
{
Console.WriteLine("{0}: {1}", i, a[i]);
}
열 유형을 사용하여 열 유형을 볼 수 있습니다. 예 :
Column c = table["double-column-name"];
Console.WriteLine("Column {0} is double: {1}", c.Name, c.Rows.IsRealColumn);
라이브러리는 F #에 중점을 두므로 FSharp.Core 4.4 어셈블리에 대한 참조를 추가해야합니다. 프로젝트에서 'Add Reference'를 클릭하고 "Assemblies"-> "Extensions"에서 FSharp.Core 4.4를 선택하십시오.
올바른 라이브러리를 검색하는 데 몇 시간을 소비했지만 마침내 내 코드를 작성했습니다. 원하는 도구를 사용하여 파일 (또는 데이터베이스)을 읽은 다음 각 라인에 다음 루틴을 적용 할 수 있습니다.
private static string[] SmartSplit(string line, char separator = ',')
{
var inQuotes = false;
var token = "";
var lines = new List<string>();
for (var i = 0; i < line.Length; i++) {
var ch = line[i];
if (inQuotes) // process string in quotes,
{
if (ch == '"') {
if (i<line.Length-1 && line[i + 1] == '"') {
i++;
token += '"';
}
else inQuotes = false;
} else token += ch;
} else {
if (ch == '"') inQuotes = true;
else if (ch == separator) {
lines.Add(token);
token = "";
} else token += ch;
}
}
lines.Add(token);
return lines.ToArray();
}
나는 수년간 csvreader.com (유료 구성 요소)을 사용해 왔으며 아무런 문제가 없었습니다. 단단하고 빠르며 빠르지 만 지불해야합니다. 구분 기호를 원하는대로 설정할 수 있습니다.
using (CsvReader reader = new CsvReader(s) {
reader.Settings.Delimiter = ';';
reader.ReadHeaders(); // if headers on a line by themselves. Makes reader.Headers[] available
while (reader.ReadRecord())
... use reader.Values[col_i] ...
}
나는 단지 석사 논문을 연구하는 학생이지만, 이것이 내가 그것을 해결하는 방법이며 그것은 나를 위해 잘 작동했습니다. 먼저 디렉토리에서 파일을 선택하고 (csv 형식으로 만) 데이터를 목록에 넣습니다.
List<float> t = new List<float>();
List<float> SensorI = new List<float>();
List<float> SensorII = new List<float>();
List<float> SensorIII = new List<float>();
using (OpenFileDialog dialog = new OpenFileDialog())
{
try
{
dialog.Filter = "csv files (*.csv)|*.csv";
dialog.Multiselect = false;
dialog.InitialDirectory = ".";
dialog.Title = "Select file (only in csv format)";
if (dialog.ShowDialog() == DialogResult.OK)
{
var fs = File.ReadAllLines(dialog.FileName).Select(a => a.Split(';'));
int counter = 0;
foreach (var line in fs)
{
counter++;
if (counter > 2) // Skip first two headder lines
{
this.t.Add(float.Parse(line[0]));
this.SensorI.Add(float.Parse(line[1]));
this.SensorII.Add(float.Parse(line[2]));
this.SensorIII.Add(float.Parse(line[3]));
}
}
}
}
catch (Exception exc)
{
MessageBox.Show(
"Error while opening the file.\n" + exc.Message,
this.Text,
MessageBoxButtons.OK,
MessageBoxIcon.Error
);
}
}
여전히 틀렸다. 따옴표로 ""를 보완해야합니다. 여기 내 솔루션 Microsoft 스타일 CSV가 있습니다.
/// <summary>
/// Microsoft style csv file. " is the quote character, "" is an escaped quote.
/// </summary>
/// <param name="fileName"></param>
/// <param name="sepChar"></param>
/// <param name="quoteChar"></param>
/// <param name="escChar"></param>
/// <returns></returns>
public static List<string[]> ReadCSVFileMSStyle(string fileName, char sepChar = ',', char quoteChar = '"')
{
List<string[]> ret = new List<string[]>();
string[] csvRows = System.IO.File.ReadAllLines(fileName);
foreach (string csvRow in csvRows)
{
bool inQuotes = false;
List<string> fields = new List<string>();
string field = "";
for (int i = 0; i < csvRow.Length; i++)
{
if (inQuotes)
{
// Is it a "" inside quoted area? (escaped litteral quote)
if(i < csvRow.Length - 1 && csvRow[i] == quoteChar && csvRow[i+1] == quoteChar)
{
i++;
field += quoteChar;
}
else if(csvRow[i] == quoteChar)
{
inQuotes = false;
}
else
{
field += csvRow[i];
}
}
else // Not in quoted region
{
if (csvRow[i] == quoteChar)
{
inQuotes = true;
}
if (csvRow[i] == sepChar)
{
fields.Add(field);
field = "";
}
else
{
field += csvRow[i];
}
}
}
if (!string.IsNullOrEmpty(field))
{
fields.Add(field);
field = "";
}
ret.Add(fields.ToArray());
}
return ret;
}
}
정확히 필요한 일을하는 도서관이 있습니다.
얼마 전에 저는 CSV 파일 작업을위한 간단하고 빠른 라이브러리를 작성했습니다. 다음 링크에서 찾을 수 있습니다 : https://github.com/ukushu/DataExporter
2 차원 배열과 같은 CSV로 작동합니다. 정확히 당신이 필요로합니다.
예를 들어, 세 번째 행의 모든 값이 필요한 경우 다음과 같이 작성하면됩니다.
Csv csv = new Csv();
csv.FileOpen("c:\\file1.csv");
var allValuesOf3rdRow = csv.Rows[2];
또는의 두 번째 셀을 읽으려면
var value = csv.Rows[2][1];
CsvFramework 사용;
System.Collections.Generic 사용;
네임 스페이스 CvsParser {
public class Customer
{
public int Id { get; set; }
public string Name { get; set; }
public List<Order> Orders { get; set; }
}
public class Order
{
public int Id { get; set; }
public int CustomerId { get; set; }
public int Quantity { get; set; }
public int Amount { get; set; }
public List<OrderItem> OrderItems { get; set; }
}
public class Address
{
public int Id { get; set; }
public int CustomerId { get; set; }
public string Name { get; set; }
}
public class OrderItem
{
public int Id { get; set; }
public int OrderId { get; set; }
public string ProductName { get; set; }
}
class Program
{
static void Main(string[] args)
{
var customerLines = System.IO.File.ReadAllLines(@"Customers.csv");
var orderLines = System.IO.File.ReadAllLines(@"Orders.csv");
var orderItemLines = System.IO.File.ReadAllLines(@"OrderItemLines.csv");
CsvFactory.Register<Customer>(builder =>
{
builder.Add(a => a.Id).Type(typeof(int)).Index(0).IsKey(true);
builder.Add(a => a.Name).Type(typeof(string)).Index(1);
builder.AddNavigation(n => n.Orders).RelationKey<Order, int>(k => k.CustomerId);
}, false, ',', customerLines);
CsvFactory.Register<Order>(builder =>
{
builder.Add(a => a.Id).Type(typeof(int)).Index(0).IsKey(true);
builder.Add(a => a.CustomerId).Type(typeof(int)).Index(1);
builder.Add(a => a.Quantity).Type(typeof(int)).Index(2);
builder.Add(a => a.Amount).Type(typeof(int)).Index(3);
builder.AddNavigation(n => n.OrderItems).RelationKey<OrderItem, int>(k => k.OrderId);
}, true, ',', orderLines);
CsvFactory.Register<OrderItem>(builder =>
{
builder.Add(a => a.Id).Type(typeof(int)).Index(0).IsKey(true);
builder.Add(a => a.OrderId).Type(typeof(int)).Index(1);
builder.Add(a => a.ProductName).Type(typeof(string)).Index(2);
}, false, ',', orderItemLines);
var customers = CsvFactory.Parse<Customer>();
}
}
}
";"
구분자로 사용 됩니다. 이렇게하면 CSV가 비표준 imo가되었습니다. (