My application reads .CSV file(which do not having a header in csv file) and converts into XML file.
For existing code wrote as
sr = new StreamReader(fs);
fs = null;
using (CsvReader csvReader = new CsvReader(sr))
{
sr = null;
csvReader.Configuration.HasHeaderRecord = hasHeaderRecord;
csvReader.Configuration.IgnoreBlankLines = false;
csvReader.Configuration.IgnoreReadingExceptions = true;
csvReader.Configuration.WillThrowOnMissingField = false;
csvReader.Configuration.TrimFields = true;
csvReader.Configuration.RegisterClassMap<Class1Map>();
FileRecords = csvReader.GetRecords<Class1>().ToList();
}
public class Class1Map : CsvClassMap<Class1>
{
public Class1Map()
{
Map(m => m.AccountId).Index(0);
Map(m => m.MeterId).Index(1);
.......
.......
}
}
But now for my new requirement, .csv file includes header and column names that are different compared to previous .csv. Somehow I have read the new CSV file and get values present in the csv file and mapped to class1.
Class1 properties are AccountId,MeterId etc.
But in new format the names are different now.
AccountId as AccountRef and MeterId as MeterSerial.
Can any one suggest how to map new file values of AccountRef,MeterSerial to class1 properties AccountId,MeterId
You could just add .Name() to your maps. Your first example with no header will use .Index() and your second example with a header will use .Name() to map the columns.
void Main()
{
var config1 = new CsvConfiguration(CultureInfo.InvariantCulture)
{
HasHeaderRecord = false
};
using (var reader = new StringReader("1,2\n3,4"))
using (var csv = new CsvReader(reader, config1))
{
csv.Context.RegisterClassMap<Class1Map>();
var records = csv.GetRecords<Class1>().Dump();
}
var config2 = new CsvConfiguration(CultureInfo.InvariantCulture)
{
HasHeaderRecord = true
};
using (var reader = new StringReader("MeterSerial,AccountRef\n4,5\n6,7"))
using (var csv = new CsvReader(reader, config2))
{
csv.Context.RegisterClassMap<Class1Map>();
var records = csv.GetRecords<Class1>().Dump();
}
}
public class Class1Map : ClassMap<Class1>
{
public Class1Map()
{
Map(m => m.AccountId).Index(0).Name("AccountRef");
Map(m => m.MeterId).Index(1).Name("MeterSerial");
}
}
public class Class1
{
public int AccountId { get; set; }
public int MeterId { get; set; }
}
Edit, thank you for the suggestion of using csvhelper, this is actually helping quite a lot.
What I have done is create a new method like so:
public static void AppendFile<T>(FileInfo fi, List<T> report)
{
var settings = new CsvConfiguration(new CultureInfo("en-GB"))
{
//Delimiter = ";"
};
using var stream = File.Open(fi.FullName, FileMode.Append);
using var writer = new StreamWriter(stream);
using (var csv = new CsvWriter(writer, settings))
{
csv.WriteRecords(report);
}
}
And gone through the example on the csvhelper site, creating a new class:
public class Foo
{
public int Id { get; set; }
public string Name { get; set; }
}
and then creating a new list:
public class Foo
{
public int Id { get; set; }
public string Name { get; set; }
}
and calling it like so:
AppendToFile.AppendFile(exportFile, records1);
This is working better than what I had before but, instead adding the new columns beside the last column, they are getting added at the bottom of the file.
For clarification,
what I'm trying to do:
what I'm getting:
As you'll be able to see, it's just being added as new rows rather than being separate columns, what do I need to change?
Another way you can accomplish your goal is to write each object to the row by hand using csvWriter.WriteHeader and csvWriter.WriteRecord.
void Main()
{
var settings = new CsvConfiguration(new CultureInfo("en-GB"))
{
Delimiter = ";"
};
var fooList = new List<Foo>()
{
new Foo { Id = 67, Name = "test1,test2"}
};
List<MyClass> records;
using (var reader = new StringReader("Author,Admin Owner\nChris Jones,\nJohn Thompson,\nBrian Oates,"))
using (var csv = new CsvReader(reader, CultureInfo.InvariantCulture))
{
records = csv.GetRecords<MyClass>().ToList();
}
using var csvWriter = new CsvWriter(Console.Out, settings);
csvWriter.WriteHeader<MyClass>();
csvWriter.WriteHeader<Foo>();
csvWriter.NextRecord();
var i = 0;
foreach (var record in records)
{
csvWriter.WriteRecord(record);
if (i < fooList.Count())
{
csvWriter.WriteRecord(fooList[i]);
}
csvWriter.NextRecord();
i++;
}
}
public class MyClass
{
public string Author { get; set; }
[Name("Admin Owner")]
public string AdminOwner { get; set; }
}
public class Foo
{
public int Id { get; set; }
public string Name { get; set; }
}
I managed to figure out a way that worked for me, might not be the most efficient but it does work.
public static void AppendFile(FileInfo fi, List<string> newColumns, DataTable newRows)
{
var settings = new CsvConfiguration(new CultureInfo("en-GB"))
{
Delimiter = ";"
};
var dt = new DataTable();
using (var reader = new StreamReader(fi.FullName))
using (var csv = new CsvReader(reader, CultureInfo.InvariantCulture))
{
using (var dataReader = new CsvDataReader(csv))
{
dt.Load(dataReader);
foreach (var title in newColumns)
{
dt.Columns.Add(title);
}
dt.Rows.Clear();
foreach (DataRow row in newRows.Rows)
{
dt.Rows.Add(row.ItemArray);
}
}
}
using var streamWriter = new StreamWriter(fi.FullName);
using var csvWriter = new CsvWriter(streamWriter, settings);
// Write columns
foreach (DataColumn column in dt.Columns)
{
csvWriter.WriteField(column.ColumnName);
}
csvWriter.NextRecord();
// Write row values
foreach (DataRow row in dt.Rows)
{
for (var i = 0; i < dt.Columns.Count; i++)
{
csvWriter.WriteField(row[i]);
}
csvWriter.NextRecord();
}
}
I start by getting the contents of the csv file into a data table and then adding in the new columns that I need. I then clear all the rows in the datatable and add new ones in (the data that is removed is added back in via the newRows parameter) and then write the datatable to the csv file
I have the following object structure and trying to write to csv using csvhelper. but the filenames column in not getting added.
public class ClusterData
{
public IEnumerable<string> FileName { get; set; }
public int? ClusterNumber { get; set; }
public string TopTerm { get; set; }
}
using (var writer = new StreamWriter(#"C:\Clean.csv"))
{
var csv = new CsvWriter(writer);
csv.WriteHeader<ClusterData>();
foreach (var item in dataToCsv)
{
foreach (var filename in item.FileName)
{
csv.WriteField(filename);
csv.WriteField(item.ClusterNumber);
csv.WriteField(item.TopTerm);
csv.NextRecord();
}
}
writer.Flush();
}
how to achieve with this?i want the outer loop to be repeated once and inner loop to be repeated for each item in filename.
Thanks
Extract the desired data and then use the writer to send it to file
using (var writer = new StreamWriter(#"C:\Clean.csv")) {
var data = new List<ClusterData>();
//...assuming data is poulated
var dataToCsv = data.SelectMany(item => item.FileName.Select(filename => new {
FileName = filename,
ClusterNumber = item.ClusterNumber,
TopTerm = item.TopTerm
}));
var csv = new CsvWriter(writer);
csv.WriteRecords(dataToCsv);
}
A linq query is used to construct the desired object format for each file name in the data.
The data is then converted to CSV as it normally would using a CsvWriter
I've been stuck trying to get the CSV Helper to write to a file. When I run DownloadRegistrantsCsv it downloads the file with the proper name and everything else, but it never writes anything to it.
public async Task<Stream> GetDownloadStreamAsync(int id)
{
var memoryStream = new MemoryStream();
var streamWriter = new StreamWriter(memoryStream);
var streamReader = new StreamReader(memoryStream);
var csvHelper = new CsvHelper.CsvWriter(streamWriter);
csvHelper.WriteRecord(new EventRegistrant { FirstName = "Max" });
await memoryStream.FlushAsync();
memoryStream.Position = 0;
return memoryStream;
}
public async Task<ActionResult> DownloadRegistrantsCsv(int id)
{
var #event = await _service.GetAsync(id, true);
if (#event == null)
return HttpNotFound();
var stream = await _service.GetDownloadStreamAsync(id);
return File(stream, "application/txt", "test" + ".csv");
}
I've also tried just using the documentation for the CSV Helper and I can't even get that to write. Here's what I've got for that...
// Copyright 2009-2015 Josh Close and Contributors
// This file is a part of CsvHelper and is dual licensed under MS-PL and Apache 2.0.
// See LICENSE.txt for details or visit http://www.opensource.org/licenses/ms-pl.html for MS-PL and http://opensource.org/licenses/Apache-2.0 for Apache 2.0.
// http://csvhelper.com
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;
using System.IO;
using System.Web.Script.Serialization;
using CsvHelper.Configuration;
using CsvHelper.TypeConversion;
namespace CsvHelper.Example
{
class Program
{
private const string columnSeparator = ":";
static void Main(string[] args)
{
//ReadRawFieldsByIndex();
//ReadRawFieldsByName();
//ReadFieldsByIndex();
//ReadRecordsNoAttributes();
//ReadRecordsWithAttributes();
//ReadAllRecords();
//WriteRawFields();
//WriteFields();
WriteRecordsNoAttributes();
//WriteRecordsWithAttributes();
WriteAllRecords();
Console.ReadKey();
}
public static void ReadRawFieldsByIndex()
{
Console.WriteLine("Raw fields by index:");
using (var reader = new CsvReader(new StreamReader(GetDataStream(true, true))))
{
while (reader.Read())
{
Console.Write(reader.GetField(0) + columnSeparator);
Console.Write(reader.GetField(1) + columnSeparator);
Console.Write(reader.GetField(2) + columnSeparator);
Console.WriteLine(reader.GetField(3));
}
}
Console.WriteLine();
}
public static void ReadRawFieldsByName()
{
Console.WriteLine("Raw fields by name:");
using (var reader = new CsvReader(new StreamReader(GetDataStream(true, true))))
{
while (reader.Read())
{
Console.Write(reader.GetField("String Column") + columnSeparator);
Console.Write(reader.GetField("Int Column") + columnSeparator);
Console.Write(reader.GetField("Guid Column") + columnSeparator);
Console.Write(reader.GetField("Does Not Exist Column") + columnSeparator);
Console.WriteLine(reader.GetField("Custom Type Column"));
}
}
Console.WriteLine();
}
public static void ReadFieldsByIndex()
{
Console.WriteLine("Fields by index:");
var customTypeTypeConverter = new CustomTypeTypeConverter();
using (var reader = new CsvReader(new StreamReader(GetDataStream(true, true))))
{
while (reader.Read())
{
Console.Write(reader.GetField<string>(0) + columnSeparator);
Console.Write(reader.GetField<int>("Int Column") + columnSeparator);
Console.Write(reader.GetField<Guid>(2) + columnSeparator);
Console.WriteLine(reader.GetField<CustomType>(3, customTypeTypeConverter));
}
}
Console.WriteLine();
}
public static void ReadRecordsNoAttributes()
{
Console.WriteLine("Records no attributes:");
using (var reader = new CsvReader(new StreamReader(GetDataStream(true, false))))
{
while (reader.Read())
{
Console.WriteLine(reader.GetRecord<CustomObject>());
}
}
Console.WriteLine();
}
public static void ReadRecordsWithAttributes()
{
Console.WriteLine("Records with attributes:");
using (var reader = new CsvReader(new StreamReader(GetDataStream(true, true))))
{
reader.Configuration.RegisterClassMap<CustomObjectWithMappingMap>();
while (reader.Read())
{
Console.WriteLine(reader.GetRecord<CustomObjectWithMapping>());
}
}
Console.WriteLine();
}
public static void ReadAllRecords()
{
Console.WriteLine("All records:");
using (var reader = new CsvReader(new StreamReader(GetDataStream(true, false))))
{
var records = reader.GetRecords<CustomObject>();
foreach (var record in records)
{
Console.WriteLine(record);
}
}
Console.WriteLine();
}
public static void WriteRawFields()
{
Console.WriteLine("Write raw fields");
using (var memoryStream = new MemoryStream())
using (var streamWriter = new StreamWriter(memoryStream))
using (var streamReader = new StreamReader(memoryStream))
using (var writer = new CsvWriter(streamWriter))
{
writer.WriteField("String Column");
writer.WriteField("Int Column");
writer.WriteField("Guid Column");
writer.WriteField("Custom Type Column");
writer.NextRecord();
writer.WriteField("one");
writer.WriteField((1).ToString());
writer.WriteField(Guid.NewGuid().ToString());
writer.WriteField((new CustomType { First = 1, Second = 2, Third = 3 }).ToString());
writer.NextRecord();
memoryStream.Position = 0;
Console.WriteLine(streamReader.ReadToEnd());
}
Console.WriteLine();
}
public static void WriteFields()
{
Console.WriteLine("Write fields");
using (var memoryStream = new MemoryStream())
using (var streamWriter = new StreamWriter(memoryStream))
using (var streamReader = new StreamReader(memoryStream))
using (var writer = new CsvWriter(streamWriter))
{
writer.WriteField("String Column");
writer.WriteField("Int Column");
writer.WriteField("Guid Column");
writer.WriteField("Custom Type Column");
writer.NextRecord();
writer.WriteField("one");
writer.WriteField(1);
writer.WriteField(Guid.NewGuid());
writer.WriteField(new CustomType { First = 1, Second = 2, Third = 3 });
writer.NextRecord();
memoryStream.Position = 0;
Console.WriteLine(streamReader.ReadToEnd());
}
Console.WriteLine();
}
public static void WriteRecordsNoAttributes()
{
Console.WriteLine("Write records no attributes:");
var records = new List<CustomObject>
{
new CustomObject
{
CustomTypeColumn = new CustomType
{
First = 1,
Second = 2,
Third = 3,
},
GuidColumn = Guid.NewGuid(),
IntColumn = 1,
StringColumn = "one",
},
new CustomObject
{
CustomTypeColumn = new CustomType
{
First = 4,
Second = 5,
Third = 6,
},
GuidColumn = Guid.NewGuid(),
IntColumn = 2,
StringColumn = "two",
},
};
using (var memoryStream = new MemoryStream())
using (var streamWriter = new StreamWriter(memoryStream))
using (var streamReader = new StreamReader(memoryStream))
using (var writer = new CsvWriter(streamWriter))
{
foreach (var record in records)
{
writer.WriteRecord(record);
}
memoryStream.Position = 0;
Console.WriteLine(streamReader.ReadToEnd());
}
Console.WriteLine();
}
public static void WriteRecordsWithAttributes()
{
Console.WriteLine("Write records with attributes:");
var records = new List<CustomObjectWithMapping>
{
new CustomObjectWithMapping
{
CustomTypeColumn = new CustomType
{
First = 1,
Second = 2,
Third = 3,
},
GuidColumn = Guid.NewGuid(),
IntColumn = 1,
StringColumn = "one",
},
new CustomObjectWithMapping
{
CustomTypeColumn = new CustomType
{
First = 4,
Second = 5,
Third = 6,
},
GuidColumn = Guid.NewGuid(),
IntColumn = 2,
StringColumn = "two",
},
};
using (var memoryStream = new MemoryStream())
using (var streamWriter = new StreamWriter(memoryStream))
using (var streamReader = new StreamReader(memoryStream))
using (var writer = new CsvWriter(streamWriter))
{
foreach (var record in records)
{
writer.WriteRecord(record);
}
memoryStream.Position = 0;
Console.WriteLine(streamReader.ReadToEnd());
}
Console.WriteLine();
}
public static void WriteAllRecords()
{
Console.WriteLine("Write all records with attributes:");
var records = new List<CustomObjectWithMapping>
{
new CustomObjectWithMapping
{
CustomTypeColumn = new CustomType
{
First = 1,
Second = 2,
Third = 3,
},
GuidColumn = Guid.NewGuid(),
IntColumn = 1,
StringColumn = "one",
},
new CustomObjectWithMapping
{
CustomTypeColumn = new CustomType
{
First = 4,
Second = 5,
Third = 6,
},
GuidColumn = Guid.NewGuid(),
IntColumn = 2,
StringColumn = "two",
},
};
using (var memoryStream = new MemoryStream())
using (var streamWriter = new StreamWriter(memoryStream))
using (var streamReader = new StreamReader(memoryStream))
using (var writer = new CsvWriter(streamWriter))
{
writer.Configuration.RegisterClassMap<CustomObjectWithMappingMap>();
writer.WriteRecords(records as IEnumerable);
memoryStream.Position = 0;
Console.WriteLine(streamReader.ReadToEnd());
}
Console.WriteLine();
}
public static MemoryStream GetDataStream(bool hasHeader, bool hasSpacesInHeaderNames)
{
var stream = new MemoryStream();
var writer = new StreamWriter(stream);
if (hasHeader)
{
var header = hasSpacesInHeaderNames
? "String Column,Int Column,Guid Column,Custom Type Column"
: "StringColumn,IntColumn,GuidColumn,CustomTypeColumn";
writer.WriteLine(header);
}
writer.WriteLine("one,1,{0},1|2|3", Guid.NewGuid());
writer.WriteLine("two,2,{0},4|5|6", Guid.NewGuid());
writer.WriteLine("\"this, has a comma\",2,{0},7|8|9", Guid.NewGuid());
writer.WriteLine("\"this has \"\"'s\",4,{0},10|11|12", Guid.NewGuid());
writer.Flush();
stream.Position = 0;
return stream;
}
public class CustomType
{
public int First { get; set; }
public int Second { get; set; }
public int Third { get; set; }
public override string ToString()
{
var serializer = new JavaScriptSerializer();
return serializer.Serialize(this);
}
}
public class CustomTypeTypeConverter : ITypeConverter
{
public string ConvertToString(TypeConverterOptions options, object value)
{
var obj = (CustomType)value;
return string.Format("{0}|{1}|{2}", obj.First, obj.Second, obj.Third);
}
public object ConvertFromString(TypeConverterOptions options, string text)
{
var values = ((string)text).Split('|');
var obj = new CustomType
{
First = int.Parse(values[0]),
Second = int.Parse(values[1]),
Third = int.Parse(values[2]),
};
return obj;
}
public bool CanConvertFrom(Type type)
{
throw new NotImplementedException();
}
public bool CanConvertTo(Type type)
{
throw new NotImplementedException();
}
}
public class CustomObject
{
public CustomType CustomTypeColumn { get; set; }
public Guid GuidColumn { get; set; }
public int IntColumn { get; set; }
public string StringColumn { get; set; }
public override string ToString()
{
var serializer = new JavaScriptSerializer();
return serializer.Serialize(this);
}
}
public class CustomObjectWithMapping
{
public CustomType CustomTypeColumn { get; set; }
public Guid GuidColumn { get; set; }
public int IntColumn { get; set; }
public string StringColumn { get; set; }
public string IgnoredColumn { get; set; }
//public override string ToString()
//{
// var serializer = new JavaScriptSerializer();
// return serializer.Serialize(this);
//}
}
public sealed class CustomObjectWithMappingMap : CsvClassMap<CustomObjectWithMapping>
{
public CustomObjectWithMappingMap()
{
Map(m => m.CustomTypeColumn).Name("Custom Type Column").Index(3).TypeConverter<CustomTypeTypeConverter>();
Map(m => m.GuidColumn).Name("Guid Column").Index(2);
Map(m => m.IntColumn).Name("Int Column").Index(1);
Map(m => m.StringColumn).Name("String Column").Index(0);
}
}
}
}
Can anyone point me to what I might be missing or doing wrong?
If you have a DataTable you can convert it to a Comma Separated Value list of strings like this...
/// <summary>
/// Creates a comma separated value string from a datatable.
/// </summary>
public static string ToCSV(DataTable table)
{
StringBuilder csv = new StringBuilder();
for(int i = 0; i < table.Columns.Count ;i++) // process the column headers
{
if (i > 0)
csv.Append(",");
csv.Append(_FormatToCSVField(table.Columns[i].ColumnName));
}
if (table.Columns.Count > 0)
csv.Append("\r\n");
for (int i = 0; i < table.Rows.Count; i++) // process the row data
{
for (int j = 0; j < table.Columns.Count; j++) // process each field in the data row.
{
if (j > 0)
csv.Append(",");
csv.Append(_FormatToCSVField(table.Rows[i][j].ToString()));
}
csv.Append("\r\n");
}
return csv.ToString();
}
private static string _FormatToCSVField(string unformattedField)
{
return "\"" + unformattedField.Replace("\"", "\"\"") + "\"";
}
Or if you didn't have a DataTable; take take your created comma separated value (CSV) list of string "row1 column 1, row1 column2, row1 column3, \r\n, row2, colum1... etc..."
and save it to a CSV File, like this...
//Your CSV String
string WhatToWrite = "row1 column 1, row1 column2, row1 column3, \r\n";
//Convert your CSV String to byte[]
byte[] PutWhatToWriteIntoBytes = Encoding.GetEncoding("iso-8859-1").GetBytes(WhatToWrite);
//Write the byte[] to CSV readable by excel
string filename = "WhatYouWantToCallYourFile" + ".csv";
Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
Response.AddHeader("content-disposition", filename.ToString());
Response.Clear();
Response.BinaryWrite(PutWhatToWriteIntoBytes);
Response.End();
Its really hard to follow all your code. What exactly is it that you are trying to write to a CSV...Get that; check if it is good. then write to the file. determine if you are writing an empty string, or if the writing is losing the string
Flushing the stream writer worked for me if you still want to use the CSV Helper
Been fighting this one for a while. Can someone tell me what I'm doing wrong?
Here is my C# object:
class FileObject
{
public int LocalInx { get; set; }
public byte[] File { get; set; }
public string FileName { get; set; }
}
Here is how I populate the byte array with a file:
var FO = new FileObject();
FO.LocalInx = LocalInx;
FileInfo fi = new FileInfo(ti.Name);
FO.FileName = fi.Name;
FileStream fs = File.OpenRead(ti.Name);
try
{
byte[] bytes = new byte[fs.Length];
fs.Read(bytes,0,Convert.ToInt32(fs.Length));
fs.Close();
FO.File = bytes;
}
finally
{
fs.Close();
}
And here is how I add the row to the table. This is where I get an error.
if (o is FileObject)
{
var fpc = new SqlCeCommand("insert into Files (File, UtilityMap, NotApplicable, LocalInx, FileName) values (#File, 1, 0, #LocalInx, #FileName)", con);
fpc.Parameters.Add("#File", SqlDbType.VarBinary, 8000).Value = ((FileObject)o).File;
fpc.Parameters.AddWithValue("#LocalInx",((FileObject)o).LocalInx);
fpc.Parameters.AddWithValue("#FileName", ((FileObject)o).FileName);
fpc.ExecuteNonQuery();
}