sourcecode

C#을 사용하여 csv 파일을 json으로 변환

codebag 2023. 2. 15. 21:55
반응형

C#을 사용하여 csv 파일을 json으로 변환

C#을 사용하여 CSV 파일을 Json으로 변환하는 유틸리티를 작성한 사람이 있는지 궁금합니다.stackoverflow에 대한 이전 질문에서 이 훌륭한 유틸리티는 알고 있습니다.https://github.com/cparker15/csv-to-json 입니다.현재로서는 이 유틸리티를 참조할 예정입니다만, 기존의 C# 실장은 매우 도움이 됩니다.감사합니다!

사용할 수 있다면System.Web.Extensions, 다음과 같은 기능이 있습니다.

var csv = new List<string[]>(); // or, List<YourClass>
var lines = System.IO.File.ReadAllLines(@"C:\file.txt");
foreach (string line in lines)
    csv.Add(line.Split(',')); // or, populate YourClass          
string json = new 
    System.Web.Script.Serialization.JavaScriptSerializer().Serialize(csv);

csv 파일의 해석 요건이 더 복잡하거나 한 줄의 데이터를 캡슐화하는 클래스가 있을 수 있지만, 중요한 것은 Collection of lines가 있으면 코드 1줄로 JSON에 시리얼화할 수 있다는 것입니다.

Cinchoo ETL - 몇 줄의 코드 없이 CSV에서 JSON으로 쉽게 변환할 수 있는 오픈 소스 라이브러리

샘플 CSV의 경우:

Id, Name, City
1, Tom, NY
2, Mark, NJ
3, Lou, FL
4, Smith, PA
5, Raj, DC

샘플 코드,

string csv = @"Id, Name, City
1, Tom, NY
2, Mark, NJ
3, Lou, FL
4, Smith, PA
5, Raj, DC
";

StringBuilder sb = new StringBuilder();
using (var p = ChoCSVReader.LoadText(csv)
    .WithFirstLineHeader()
    )
{
    using (var w = new ChoJSONWriter(sb))
        w.Write(p);
}

Console.WriteLine(sb.ToString());

출력 JSON:

[
 {
  "Id": "1",
  "Name": "Tom",
  "City": "NY"
 },
 {
  "Id": "2",
  "Name": "Mark",
  "City": "NJ"
 },
 {
  "Id": "3",
  "Name": "Lou",
  "City": "FL"
 },
 {
  "Id": "4",
  "Name": "Smith",
  "City": "PA"
 },
 {
  "Id": "5",
  "Name": "Raj",
  "City": "DC"
 }
]

바이올린 샘플: https://dotnetfiddle.net/pclnsT

기타 도움말은 CodeProject 문서를 참조하십시오.

업데이트: CSV 파일에 중복된 열 이름이 있거나 이름이 없는 경우 다음 단계에 따라 JSON 파일을 생성하십시오.

string csv = @"Id, Name, 
1, Tom, NY
2, Mark, NJ
3, Lou, FL
4, Smith, PA
5, Raj, DC
";

StringBuilder sb = new StringBuilder();
using (var p = ChoCSVReader.LoadText(csv)
    .WithField("Id", position: 1)
    .WithField("Name", position: 2)
    .WithField("City", position: 3)
    .WithFirstLineHeader(true)
    )
{
    using (var w = new ChoJSONWriter(sb))
        w.Write(p);
}

Console.WriteLine(sb.ToString());

바이올린 샘플: https://dotnetfiddle.net/pP5Du6

면책사항:제가 이 도서관의 저자입니다.

사전을 사용하고 뉴턴소프트를 사용하여 json을 반환했습니다.

public string ConvertCsvFileToJsonObject(string path) 
{
    var csv = new List<string[]>();
    var lines = File.ReadAllLines(path);

    foreach (string line in lines)
        csv.Add(line.Split(','));

    var properties = lines[0].Split(',');

    var listObjResult = new List<Dictionary<string, string>>();

    for (int i = 1; i < lines.Length; i++)
    {
        var objResult = new Dictionary<string, string>();
        for (int j = 0; j < properties.Length; j++)
            objResult.Add(properties[j], csv[i][j]);

        listObjResult.Add(objResult);
    }

    return JsonConvert.SerializeObject(listObjResult); 
}
Install Nuget package NewtonSoft.Json
Add reference dll Microsoft.VisualBasic

using System.Linq;
using Newtonsoft.Json;
using Microsoft.VisualBasic.FileIO;
using System.IO;
using System;
using System.Collections.Generic;
using System.Globalization;

namespace Project
{
    public static class Program
    {
        public static void Main(string[] args)
        {
            string CSVpath = @"D:\New Folder\information.csv";
            string analyticsData = ReadFile(CSVpath);
        }

        private static string ReadFile(string filePath)
        {
            string payload = "";
            try
            {
                if (!string.IsNullOrWhiteSpace(filePath) && File.Exists(filePath) && Path.GetExtension(filePath).Equals(".csv", StringComparison.InvariantCultureIgnoreCase))
                {
                    string[] lines = File.ReadAllLines(filePath);

                    if (lines != null && lines.Length > 1)
                    {
                        var headers = GetHeaders(lines.First());
                        payload = GetPayload(headers, lines.Skip(1));
                    }
                }
            }
            catch (Exception exp)
            {
            }
            return payload;
        }

        private static IEnumerable<string> GetHeaders(string data)
        {
            IEnumerable<string> headers = null;

            if (!string.IsNullOrWhiteSpace(data) && data.Contains(','))
            {
                headers = GetFields(data).Select(x => x.Replace(" ", ""));
            }
            return headers;
        }

        private static string GetPayload(IEnumerable<string> headers, IEnumerable<string> fields)
        {
            string jsonObject = "";
            try
            {
                var dictionaryList = fields.Select(x => GetField(headers, x));
                jsonObject = JsonConvert.SerializeObject(dictionaryList);
            }
            catch (Exception ex)
            {
            }
            return jsonObject;
        }

        private static Dictionary<string, string> GetField(IEnumerable<string> headers, string fields)
        {
            Dictionary<string, string> dictionary = null;

            if (!string.IsNullOrWhiteSpace(fields))
            {
                var columns = GetFields(fields);

                if (columns != null && headers != null && columns.Count() == headers.Count())
                {
                    dictionary = headers.Zip(columns, (x, y) => new { x, y }).ToDictionary(item => item.x, item => item.y);
                }
            }
            return dictionary;
        }

        public static IEnumerable<string> GetFields(string line)
        {
            IEnumerable<string> fields = null;
            using (TextReader reader = new StringReader(line))
            {
                using (TextFieldParser parser = new TextFieldParser(reader))
                {
                    parser.TextFieldType = FieldType.Delimited; parser.SetDelimiters(","); fields = parser.ReadFields();
                }
            }
            return fields;
        }
    }
}

뉴턴소프트에 의존해서 말이야Json, 여기 CSV 행 배열이 지정된 도우미 메서드가 있습니다. 첫 번째 방법은 헤더입니다.

    public static IEnumerable<JObject> CsvToJson(IEnumerable<string> csvLines)
    {
        var csvLinesList = csvLines.ToList();

        var header = csvLinesList[0].Split(',');
        for (int i = 1; i < csvLinesList.Count; i++)
        {
            var thisLineSplit = csvLinesList[i].Split(',');
            var pairedWithHeader = header.Zip(thisLineSplit, (h, v) => new KeyValuePair<string, string>(h, v));

            yield return new JObject(pairedWithHeader.Select(j => new JProperty(j.Key, j.Value)));
        }
    }

ChoETL을 사용합니다.

using ChoETL;
using System.IO;

public class FromCSVtoJSON
{
    public FromCSVtoJSON()
    {

    }

    public void convertFile(string inputFile, string outputFile)
    {
        using (var writer = new ChoJSONWriter(outputFile))
        {
            using (var reader = new ChoCSVReader(inputFile).WithFirstLineHeader())
            {
                writer.Write(reader);
            }
        }
    }
}

동일한 SO 답변에서 이 게시물에 대한 링크가 있습니다.

CsvToJson 확장 방식

/// <summary>
/// Converts a CSV string to a Json array format.
/// </summary>
/// <remarks>First line in CSV must be a header with field name columns.</remarks>
/// <param name="value"></param>
/// <returns></returns>
public static string CsvToJson(this string value)
{
    // Get lines.
    if (value == null) return null;
    string[] lines = value.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
    if (lines.Length < 2) throw new InvalidDataException("Must have header line.");

    // Get headers.
    string[] headers = lines.First().SplitQuotedLine(new char[] { ',' }, false);

    // Build JSON array.
    StringBuilder sb = new StringBuilder();
    sb.AppendLine("[");
    for (int i = 1; i < lines.Length; i++)
    {
        string[] fields = lines[i].SplitQuotedLine(new char[] { ',', ' ' }, true, '"', false);
        if (fields.Length != headers.Length) throw new InvalidDataException("Field count must match header count.");
        var jsonElements = headers.Zip(fields, (header, field) => string.Format("{0}: {1}", header, field)).ToArray();
        string jsonObject = "{" + string.Format("{0}", string.Join(",", jsonElements)) + "}";
        if (i < lines.Length - 1)
            jsonObject += ",";
        sb.AppendLine(jsonObject);
    }
    sb.AppendLine("]");
    return sb.ToString();
}

위의 확장자 내에서 호출된 일부 메서드가 존재하는 경우 문제가 있는 것 같습니다(원래 블로그 투고의 코멘트를 참조해 주세요).하지만, 대부분의 경우 그렇게 할 수 있습니다.

편집 CSV 회선 분할에 관한 SO 답변은 다음과 같습니다.권장되는 regex 솔루션 중 하나를 사용하여 사용자 고유의 regex 솔루션을 만들 수 있습니다.SplitQuotedLine방법:

public static string SplitQuotedLine(this string value, char separator, bool quotes) {
    // Use the "quotes" bool if you need to keep/strip the quotes or something...
    var s = new StringBuilder();
    var regex = new Regex("(?<=^|,)(\"(?:[^\"]|\"\")*\"|[^,]*)");
    foreach (Match m in regex.Matches(value)) {
        s.Append(m.Value);
    }
    return s.ToString();
}

상기 테스트는 하지 않았으므로, 실수를 한 점 양해 바랍니다.

또, Zip은 LINQ 확장 방식인 것 같기 때문에, 이것으로 문제가 해결됩니다.

여기 내 것이 있다.수세기 내에 9k CSV 레코드를 해석할 수 있습니다.ㅋㅋㅋ

class CSVTOJSON
{
    public string ConvertToJSON()
    {
        string json = string.Empty;
        string csv = string.Empty;

        using (StreamReader reader = new StreamReader("data.csv"))
        {
            csv = reader.ReadToEnd();
        }

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

        if (lines.Length > 1)
        {
            // parse headers
            string[] headers = lines[0].Split(',');

            StringBuilder sbjson = new StringBuilder();
            sbjson.Clear();
            sbjson.Append("[");

            // parse data
            for (int i = 1; i < lines.Length; i++)
            {
                if (string.IsNullOrWhiteSpace(lines[i])) continue;
                if (string.IsNullOrEmpty(lines[i])) continue;

                sbjson.Append("{");

                string[] data = lines[i].Split(',');

                for (int h = 0; h < headers.Length; h++)
                {
                    sbjson.Append(
                        $"\"{headers[h]}\": \"{data[h]}\"" + (h < headers.Length - 1 ? "," : null)
                    );
                }

                sbjson.Append("}" + (i < lines.Length - 1 ? "," : null));
            }

            sbjson.Append("]");

            json = sbjson.ToString();
        }

        return json;
    }
}

하지만 그것은 효과가 있다.

콘솔 로그:

Converting CSV to JSON
CSV has 9486 data
Total duration converting CSV to JSON: 00:00:00.0775373

bc3tech에 의한 솔루션에 대한 작은 변화(Newtonsoft에 대한 외부 의존성 회피).Json) 대신 시스템을 사용합니다.Text.Json(닷넷 코어 3+)

public static IEnumerable<string> CsvToJson(string fileName, char delim = '|')
{
    var lines = File.ReadLines(fileName); 
    var hdr = new List<string>(lines.First().Trim().Split(delim));
    foreach (var l in lines.Skip(1).Where(l => (l.Trim() != String.Empty))) 
    {
        var val = l.Trim().Split(delim);
        var ds = hdr.Zip(val, (k, v) => new { k, v }).ToDictionary(x => x.k, x => x.v);
        yield return JsonSerializer.Serialize(ds);
    }
}

CSV 파일을 해석하는 것은 단순히 각 컬럼에 콤마 딜리미터를 분할하는 것이라고 생각하는 경우가 많지만 다음 형식은 여전히 유효한 CSV입니다.

"aaa","bbb","ccc"
"z, z",yyy,xxx

마이크로소프트에는 멋진 클래스가 숨겨져 있습니다.Visual Basic.CSV 파일 형식을 올바르게 처리하기 위한 FileIO.이거랑 JSON이랑 합친 거예요.NET은 해결책을 생각해냈다.

   public static string? CsvToJson(string input, string delimiter)
   {
        using (TextFieldParser parser = new TextFieldParser(
                 new MemoryStream(Encoding.UTF8.GetBytes(input))))
        {
            parser.Delimiters = new string[] { delimiter };
            string[]? headers = parser.ReadFields();
            if (headers == null) return null;
            string[]? row;
            string comma = "";
            var sb = new StringBuilder((int)(input.Length * 1.1));
            sb.Append("[");
            while ((row = parser.ReadFields()) != null)
            {
                var dict = new Dictionary<string, object>();
                for (int i = 0; row != null && i < row.Length; i++)
                    dict[headers[i]] = row[i];

                var obj = JsonConvert.SerializeObject(dict);
                sb.Append(comma + obj);
                comma = ",";
            }
            return sb.Append("]").ToString();
        }
    }

사용.

var str = @"Header1,""Header,,2 "",Data3
1,444.00, ""Liang, Jerry""
0,""5,550"",Jerry
";

var json = CsvToJson(str, ",");

결과

[
  {
    "Header1": "1",
    "Header,,2": "444.00",
    "Data3": "Liang, Jerry"
  },
  {
    "Header1": "0441",
    "Header,,2": "5,550",
    "Data3": "Jerry"
  }
]

나는 마침내 이 문제에 대한 답을 찾았고 사전을 사용해서 풀었다.

public static void CreateJsonFromCSV()
{
    string path = "C:\\Users\\xx\\xx\\xx\\xx\\lang.csv";
    string textFilePath = path;
    const Int32 BufferSize = 128;

    using (var fileStream = File.OpenRead(textFilePath))
    using (var streamReader = new StreamReader(fileStream, Encoding.UTF8, true, BufferSize))
    {
        String line;
        Dictionary<string, string> jsonRow = new Dictionary<string, string>();

        while ((line = streamReader.ReadLine()) != null)
        {

            string[] parts = line.Split(',');

            string key_ = parts[0];
            string value = parts[1];


            if (!jsonRow.Keys.Contains(key_))
            {
                jsonRow.Add(key_, value );
            }

        }
        var json = new JavaScriptSerializer().Serialize(jsonRow);
        string path_ = "C:\\XX\\XX\\XX\\XX\\XX.csv";
        File.WriteAllText(path_, json);
    }

} 

큰 CSV 파일을 해석하기 전에 web.config에 다음 항목을 추가해야 합니다.

 <system.web.extensions>
       <scripting>
           <webServices>
               <jsonSerialization maxJsonLength="50000000"/>
           </webServices>
       </scripting>
   </system.web.extensions>

이것을 시험해 보세요.

 StreamReader sr = new StreamReader(filePath);
 while ((line = sr.ReadLine()) != null)
 {
      //Console.WriteLine(line);
      string[] csv = line.Split(',');
      var dictionary = new Dictionary<string, string>();
      dictionary.Add("dispatching_base_number",csv[0]);
      dictionary.Add("available_vehicles", csv[1]);
      dictionary.Add("vehicles_in_trips", csv[2]);
      dictionary.Add("Cancellations", csv[3]);
      string jsonN = new System.Web.Script.Serialization.JavaScriptSerializer().Serialize(dictionary);
      Console.WriteLine("Sending message: {0}",jsonN);
 }

해 보고 변환해 보세요.CSV로로 합니다.JSON★★★★★★★★★★★★★★★★★★:

public static List<object> CsvToJson( string body, string[] column ) {
    if ( string.IsNullOrEmpty( body ) ) return null;
    string[] rowSeparators = new string[] { "\r\n" };
    string[] rows = body.Split( rowSeparators, StringSplitOptions.None );
    body = null;
    if ( rows == null || ( rows != null && rows.Length == 0 ) ) return null;
    string[] cellSeparator = new string[] { "," };
    List<object> data = new List<object>( );
    int clen = column.Length;
    rows.Select( row => {
        if ( string.IsNullOrEmpty( row ) ) return row;
        string[] cells = row.Trim( ).Split( cellSeparator, StringSplitOptions.None );
        if ( cells == null ) return row;
        if ( cells.Length < clen ) return row;
        Dictionary<object, object> jrows = new Dictionary<object, object>( );
        for ( int i = 0; i < clen; i++ ) {
            jrows.Add( column[i], cells[i]?.Trim( ) );
        }
        data.Add( jrows );
        return row;
    } ).ToList( );
    rowSeparators = null; rows = null;
    cellSeparator = null;
    return data;
}

var data = CsvToJson("csv_input_str", new string[]{ "column_map" })
string jsonStr = new JavaScriptSerializer { MaxJsonLength = int.MaxValue }.Serialize( data );

먼저 csv 파일을 데이터 테이블에 로드하고 Json 문서에 직렬화합니다.csv를 현명하게 해석할 수 있는 OLEDB 공급자를 사용합니다.

Jim Scott에게 드리는 예의, https://stackoverflow.com/a/1050278/6928056

K_B님에게 드리는 예의, https://stackoverflow.com/a/2979938/6928056

using System.Data;
using System.Data.OleDb;
using System.Globalization;
using System.IO;
using Newtonsoft.Json;

static string ConvertCsvToJson(string path, bool isFirstRowHeader)
{
    string header = isFirstRowHeader ? "Yes" : "No";

    string pathOnly = Path.GetDirectoryName(path);
    string fileName = Path.GetFileName(path);

    string sql = @"SELECT * FROM [" + fileName + "]";

    using(OleDbConnection connection = new OleDbConnection(
              @"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + pathOnly + 
              ";Extended Properties=\"Text;HDR=" + header + "\""))
    using(OleDbCommand command = new OleDbCommand(sql, connection))
    using(OleDbDataAdapter adapter = new OleDbDataAdapter(command))
    {
        var dataTable = new DataTable();
        dataTable.Locale = CultureInfo.CurrentCulture;
        adapter.Fill(dataTable);
        return JsonConvert.SerializeObject(dataTable, Formatting.Indented);
    }
}

플랫 CSV 파일을 단순 json 형식의 개체 모음으로 변환하는 간단한 방법입니다.첫 번째 줄에 헤더 행이 있는 파일로 작동합니다.이 방법의 일부는 SO의 다른 곳에서 발견되었습니다.Microsoft 에 참조를 추가합니다.Visual Basic.

using Microsoft.VisualBasic.FileIO;
public static StringBuilder ReadCsv()
    {
        var path = @"X:\...\input.csv";
        using (TextFieldParser csvParser = new TextFieldParser(path))
        {
            csvParser.CommentTokens = new string[] { "#" };
            //Remember to use your own separator
            csvParser.SetDelimiters(new string[] { ";" });
            csvParser.HasFieldsEnclosedInQuotes = false;

            StringBuilder json = new StringBuilder();
            string[] colNames = new string[0];
            string[] fields = new string[0];

            json.Append("[");

            int counter = 0;
            while (!csvParser.EndOfData)
            {
                if (counter == 0)
                {
                    //Read properies' names
                    colNames = csvParser.ReadFields();
                    counter++;
                    Console.WriteLine($"{colNames.Length} columns detected!");
                }
                else
                {
                    // Read current line fields, pointer moves to the next line.
                    // Read the properties' values
                    fields = csvParser.ReadFields();

                    json.Append("{");

                    for (int i = 0; i < colNames.Length; i++)
                    {
                        json.Append($"\"{colNames[i]}\":{TryParse(fields[i])}");
                        if (i != colNames.Length - 1)
                        {
                            json.Append(",");
                        }
                    }
                    json.Append("},");
                    Console.WriteLine($"Writing record nr.: {counter}");
                    counter++;
                }
            }
            json.Length--; //Remove trailing comma
            json.Append("]");
            return json;
        }
    }

string TryParse(string s)
    {
        if (string.IsNullOrEmpty(s)) return "null";
        //Remember to set your decimal character here!
        if (s.Contains('.'))
        {
            double dResult;
            //This works on my computer, could be different on your machine
            if (double.TryParse(s, NumberStyles.AllowDecimalPoint,
                                CultureInfo.InvariantCulture, out dResult))
                return dResult.ToString(CultureInfo.InvariantCulture);
        }
        else
        {
            int intResult;
            if (int.TryParse(s, out intResult))
                return intResult.ToString(CultureInfo.InvariantCulture);
        }
        return "\"" + s + "\"";
    }

그러면 json 객체의 간단한 목록이 나타납니다.

C#만의 솔루션을 찾고 있는 경우는, 이 방법이 유효할 가능성이 있습니다.저는 최근에 같은 문제에 직면하여 이 방법을 개발했습니다.

public static string ConvertToJsonStructure(string csvDataAsString, char delimiter = ',', bool hasHeaders = true)
    {
        var output = string.Empty;
        if (string.IsNullOrEmpty(csvDataAsString))
            return "{}";

        var rows = csvDataAsString.Split(new string[] { Environment.NewLine }, StringSplitOptions.None);
        var headers = hasHeaders ? rows[0].Split(delimiter) : null;
        var colCount = headers?.Length;
        var jsonStart = "{";
        var jsonEnd = "}";

        if (rows.Length > (1 + (hasHeaders ? 1 : 0)))
        {
            jsonStart = "[";
            jsonEnd = "]";
        }

        output = output + jsonStart;

        int startIndex = hasHeaders ? 1 : 0;

        for (int i = startIndex; i < rows.Length; i++)
        {
            var cols = rows[i].Split(delimiter);

            if (colCount == null)
                colCount = cols.Length;

            var tempJson = "{";

            for (int j = 0; j < colCount.Value; j++)
            {
                if (hasHeaders)
                    tempJson = tempJson + $"\"{headers[j]}\":";

                var isNumber = Regex.IsMatch(cols[j], @"^\d + $");
                var val = isNumber ? cols[j] : $"\"{cols[j]}\"";
                tempJson = tempJson + val;

                if (j < colCount.Value - 1)
                    tempJson = tempJson + ",";

            }

            tempJson = tempJson + "}";

            if (i < rows.Length - 1)
                tempJson = tempJson + ",";

            output = output + tempJson;
        }

        output = output + jsonEnd;

        return output;
    }
}

이 메서드에 콘텐츠를 문자열로 전달해야 하며 다음과 같은 방법으로 csv를 읽을 수 있습니다.

var csvAsString = File.ReadAllText("TestCsv.csv");

        var result = CsvToJson.ConvertToJsonStructure(csvAsString);

언급URL : https://stackoverflow.com/questions/10824165/converting-a-csv-file-to-json-using-c-sharp

반응형