[C#] C #에서 CSV 파일로 데이터 쓰기

csvC # 언어를 사용하여 행 단위로 파일 에 쓰려고 합니다. 여기 내 기능이 있습니다

string first = reader[0].ToString();
string second=image.ToString();
string csv = string.Format("{0},{1}\n", first, second);
File.WriteAllText(filePath, csv);

전체 함수는 루프 내에서 실행되며 모든 행을 csv파일에 기록해야 합니다. 필자의 경우 다음 행이 기존 행을 덮어 쓰고 마지막으로 csv 파일에 마지막 레코드 인 단일 레코드를 얻습니다. csv파일의 모든 행을 어떻게 쓸 수 있습니까?



답변

최신 정보

순진한 시절에, 나는 이것을 수동으로 제안하는 것이 좋습니다 (단순한 질문에 대한 간단한 해결책이었습니다). 그러나 이것이 점점 더 인기를 끌기 때문에 모든 안전 점검 등을 수행 하는 라이브러리 CsvHelper 를 사용하는 것이 좋습니다 .

CSV는 질문 / 답변이 제안하는 것보다 훨씬 복잡합니다.

원래 답변

이미 루프가 있으므로 다음과 같이하십시오.

//before your loop
    var csv = new StringBuilder();

//in your loop
    var first = reader[0].ToString();
    var second = image.ToString();
    //Suggestion made by KyleMit
    var newLine = string.Format("{0},{1}", first, second);
    csv.AppendLine(newLine);

//after your loop
    File.WriteAllText(filePath, csv.ToString());

또는이 효과에 뭔가. 내 추론은 : 모든 항목에 대해 파일에 쓸 필요가 없으며 스트림을 한 번만 연 다음 쓸 것입니다.

교체 가능

File.WriteAllText(filePath, csv.ToString());

File.AppendAllText(filePath, csv.ToString());

이전 버전의 csv를 동일한 파일에 유지하려는 경우

C # 6

c # 6.0을 사용하는 경우 다음을 수행 할 수 있습니다.

var newLine = $"{first},{second}"

편집하다

다음은 무엇을 설명하는 질문에 대한 링크Environment.NewLine 입니다.


답변

더 지루한 길을가는 것이 좋습니다. 특히 파일 크기가 큰 경우.

using(var w = new StreamWriter(path))
{
    for( /* your loop */)
    {
        var first = yourFnToGetFirst();
        var second = yourFnToGetSecond();
        var line = string.Format("{0},{1}", first, second);
        w.WriteLine(line);
        w.Flush();
    }
}

File.AppendAllText()새 파일을 열고 내용을 쓴 다음 파일을 닫습니다. 파일을 여는 것은 데이터를 열린 스트림에 쓰는 것보다 많은 리소스가 필요한 작업입니다. 루프 내에서 파일을 열거 나 닫으면 성능이 저하됩니다.

Johan이 제안한 접근 방식은 모든 출력을 메모리에 저장 한 다음 한 번 작성하여이 문제를 해결합니다. 그러나 (큰 파일의 경우) 프로그램은 많은 양의 RAM을 소비하며OutOfMemoryException

내 솔루션의 또 다른 장점은 입력 데이터에 현재 위치를 저장하여 일시 중지 / 다시 시작을 구현할 수 있다는 것입니다.

올라 갔다. 올바른 장소에 배치


답변

데이터에 쉼표와 줄 바꿈이 포함될 수 있으므로 CSV 파일을 직접 작성하는 것은 어려울 수 있습니다. 기존 라이브러리를 대신 사용하는 것이 좋습니다.

이 질문에는 몇 가지 옵션이 언급되어 있습니다.

C #에 CSV 리더 / 라이터 라이브러리가 있습니까?


답변

유지 관리가 매우 쉬운 두 가지 구문 분석 솔루션을 사용합니다.

// Prepare the values
var allLines = (from trade in proposedTrades
                select new object[]
                {
                    trade.TradeType.ToString(),
                    trade.AccountReference,
                    trade.SecurityCodeType.ToString(),
                    trade.SecurityCode,
                    trade.ClientReference,
                    trade.TradeCurrency,
                    trade.AmountDenomination.ToString(),
                    trade.Amount,
                    trade.Units,
                    trade.Percentage,
                    trade.SettlementCurrency,
                    trade.FOP,
                    trade.ClientSettlementAccount,
                    string.Format("\"{0}\"", trade.Notes),
                }).ToList();

// Build the file content
var csv = new StringBuilder();
allLines.ForEach(line =>
{
    csv.AppendLine(string.Join(",", line));
});

File.WriteAllText(filePath, csv.ToString());


답변

매번 전화하는 대신 AppendAllText()파일을 한 번 열어서 전체 내용을 한 번 작성하는 것을 생각할 수 있습니다.

var file = @"C:\myOutput.csv";

using (var stream = File.CreateText(file))
{
    for (int i = 0; i < reader.Count(); i++)
    {
        string first = reader[i].ToString();
        string second = image.ToString();
        string csvRow = string.Format("{0},{1}", first, second);

        stream.WriteLine(csvRow);
    }
}


답변

AppendAllText를 대신 사용하십시오.

File.AppendAllText(filePath, csv);

AppendAllText의 유일한 단점은 파일이 존재하지 않을 때 오류가 발생한다는 것입니다.

문서 를 읽기 전에 금발의 순간이 있습니다 . 어쨌든 WriteAllText 메서드는 파일이 존재하는 경우 파일에 이전에 작성된 내용을 덮어 씁니다.

현재 코드는 올바른 줄 바꿈을 사용하지 않습니다. 예를 들어 메모장에서는 모두 한 줄로 표시됩니다. 적절한 새 줄을 갖도록 코드를 다음과 같이 변경하십시오.

string csv = string.Format("{0},{1}{2}", first, image, Environment.NewLine);


답변

바퀴를 재창조하는 대신 라이브러리를 사용할 수 있습니다. CsvHelperCSV 파일을 만들고 읽는 데 좋습니다. 읽기 및 쓰기 작업은 스트림 기반이므로 대량의 데이터가있는 작업도 지원합니다.


다음과 같이 CSV를 작성할 수 있습니다.

using(var textWriter = new StreamWriter(@"C:\mypath\myfile.csv"))
{
    var writer = new CsvWriter(textWriter, CultureInfo.InvariantCulture);
    writer.Configuration.Delimiter = ",";

    foreach (var item in list)
    {
        writer.WriteField( "a" );
        writer.WriteField( 2 );
        writer.WriteField( true );
        writer.NextRecord();
    }
}

라이브러리는 리플렉션을 사용하므로 모든 유형을 취하고 직접 구문 분석합니다.

public class CsvRow
{
    public string Column1 { get; set; }
    public bool Column2 { get; set; }

    public CsvRow(string column1, bool column2)
    {
        Column1 = column1;
        Column2 = column2;
    }
}

IEnumerable<CsvRow> rows = new [] {
    new CsvRow("value1", true),
    new CsvRow("value2", false)
};
using(var textWriter = new StreamWriter(@"C:\mypath\myfile.csv")
{
    var writer = new CsvWriter(textWriter, CultureInfo.InvariantCulture);
    writer.Configuration.Delimiter = ",";
    writer.WriteRecords(rows);
}

value1, true

값 2, 거짓


라이브러리 구성 및 가능성에 대한 자세한 내용을 보려면 여기를 클릭하십시오 .