Exception when creating a Stream from csv file - c#

I have a csv file in the same project with a Build Action of "Embedded Resource". When I try to create a stream using this file I get the following error:
system.io.stream.null.readtimeout threw an exception of type system.invalidoperationexception
When I let it run I catch an exception that says:
Value cannot be null.\r\nParameter name: stream
I am not sure what is causing this? Is it possible that it's not picking up my file for some reason and therefore nothing gets passed into the stream?
internal static void InsertPropertyDefinitions()
{
DataTable csvData = null;
string[] columnNames = null;
int rowCount = 0;
string[] streamDataValues = null;
try {
using (Stream stream = System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream(
"My csv file path"))
{
StreamReader streamReader = new StreamReader(stream);
while (!streamReader.EndOfStream)
{
String streamRowData = streamReader.ReadLine().Trim();
if (streamRowData.Length > 0)
{
streamDataValues = streamRowData.Split(',');
if (rowCount == 0)
{
rowCount = 1;
columnNames = streamRowData.Split(',');
csvData = new DataTable();
foreach (string csvColumn in columnNames)
{
DataColumn dataColumn = new DataColumn(csvColumn.ToUpper(), typeof(string));
dataColumn.DefaultValue = string.Empty;
csvData.Columns.Add(dataColumn);
}
}
else
{
DataRow dataRow = csvData.NewRow();
for (int i = 0; i < columnNames.Length; i++)
{
dataRow[columnNames[i]] = streamDataValues[i] == null ? string.Empty : streamDataValues[i].ToString();
}
csvData.Rows.Add(dataRow);
}
}
}
streamReader.Close();
streamReader.Dispose();
foreach (DataRow dataRow in csvData.Rows)
{
string rowValues = string.Empty;
foreach (string csvColumn in columnNames)
{
rowValues += csvColumn + "=" + dataRow[csvColumn].ToString() + "; ";
}
}
}
}

Try by resourceName :
var assembly = Assembly.GetExecutingAssembly();
var resourceName = "MyCompany.MyProduct.MyFile.csv";
using (Stream stream = assembly.GetManifestResourceStream(resourceName))
using (StreamReader reader = new StreamReader(stream))
{
...
}
The resource name is not necessarily equal to the name of the file. You can check using Assembly.GetManifestResourceNames();
Usually VS add namespace to resource name. Then MyList.csv -> NS.MyList.csv
To get names
var assembly = System.Reflection.Assembly.GetExecutingAssembly();
var lst = assembly.GetManifestResourceNames();
Console.WriteLine("Files");
Console.WriteLine(string.Join(", ", lst));

Related

System.indexoutofrangeexception: 'cannot find column 1'

I have a program to parse a CSV file from local filesystem to a specified SQL Server table.
Now when i execute the program i get error :
System.IndexOutOfRangeException: 'Cannot find column 1' exception on the line where i the program attempts to populate the datatable.
On closer inspection the error shows that its emanating from row number 3 as shown on this link :
CSV_ERROR
This is how i am reading and saving the CSV file :
static void Main(string[] args)
{
var absPath = #"C:\Users\user\Documents\Projects\MastercardSurveillance\fbc_mc_all_cards.csv";
ProcessFile();
void ProcessFile()
{
string realPath = #"C:\Users\user\Documents\CSV";
string appLog = "CSVERRORS";
var logPath = realPath + Convert.ToString(appLog) + DateTime.Today.ToString("dd -MM-yy") + ".txt";
if (!File.Exists(logPath))
{
File.Create(logPath).Dispose();
}
var dt = GetDATATable();
if (dt == null)
{
return;
}
if (dt.Rows.Count == 0)
{
using (StreamWriter sw = File.AppendText(logPath))
{
sw.WriteLine("No rows imported after reading file " + absPath);
sw.Flush();
sw.Close();
}
return;
}
ClearData();
InsertDATA();
}
DataTable GetDATATable()
{
var FilePath = absPath;
string TableName = "Cards";
string realPath = #"C:\Users\user\Documents\CSV";
string appLog = "CSVERRORS";
var logPath = realPath + Convert.ToString(appLog) + DateTime.Today.ToString("dd -MM-yy") + ".txt";
if (!File.Exists(logPath))
{
File.Create(logPath).Dispose();
}
var dt = new DataTable(TableName);
using (var csvReader = new TextFieldParser(FilePath))
{
csvReader.SetDelimiters(new string[] { "," });
csvReader.HasFieldsEnclosedInQuotes = true;
var readFields = csvReader.ReadFields();
if (readFields == null)
{
using (StreamWriter sw = File.AppendText(logPath))
{
sw.WriteLine("Could not read header fields for file " + FilePath);
sw.Flush();
sw.Close();
}
return null;
}
foreach (var dataColumn in readFields.Select(column => new DataColumn(column, typeof(string)) { AllowDBNull = true, DefaultValue = string.Empty }))
{
dt.Columns.Add(dataColumn);
}
while (!csvReader.EndOfData)
{
var data = csvReader.ReadFields();
if (data == null)
{
using (StreamWriter sw = File.AppendText(logPath))
{
sw.WriteLine(string.Format("Could not read fields on line {0} for file {1}", csvReader.LineNumber, FilePath));
sw.Flush();
sw.Close();
}
continue;
}
var dr = dt.NewRow();
for (var i = 0; i < data.Length; i++)
{
if (!string.IsNullOrEmpty(data[i]))
{
dr[i] = data[i];
}
}
dt.Rows.Add(dr);
}
}
return dt;
}
void ClearData()
{
string SqlSvrConn = #"Server=XXXXXX-5QFK4BL\MSDEVOPS;Database=McardSurveillance;Trusted_Connection=True;MultipleActiveResultSets=true;";
using (var sqlConnection = new SqlConnection(SqlSvrConn))
{
sqlConnection.Open();
// Truncate the live table
using (var sqlCommand = new SqlCommand(_truncateLiveTableCommandText, sqlConnection))
{
sqlCommand.ExecuteNonQuery();
}
}
}
void InsertDATA()
{
string SqlSvrConn = #"Server=XXXXXX-5QFK4BL\MSDEVOPS;Database=McardSurveillance;Trusted_Connection=True;MultipleActiveResultSets=true;";
DataTable table = GetDATATable();
using (var sqlBulkCopy = new SqlBulkCopy(SqlSvrConn))
{
sqlBulkCopy.DestinationTableName = "dbo.Cards";
for (var count = 0; count < table.Columns.Count; count++)
{
sqlBulkCopy.ColumnMappings.Add(count, count);
}
sqlBulkCopy.WriteToServer(table);
}
}
}
How can i identify and possibly exclude the extra data columns being returned from the CSV file?
It appears there is a mismatch between number of columns in datatable and number of columns being read from the CSV file.
Im not sure however how i can account for this with my logic. For now i did not want to switch to using a CSV parse package but rather i need insight on how i can remove the extra column or rather ensure that the splitting takes account of all possible dubious characters.
For clarity i have a copy of the CSV file here :
CSV_FILE

How to access csv file and insert data into csv

I am trying to insert data into csv file. I tried using XLWorkbook reference to access and insert data but I know that XLWorkbook can only support extension which are xlsx,xslm,xltx and xltm.
I am trying to find something similar to what I am trying to achieve through which I can insert data into specified column in csv file. I have used XLWorkbook for some other purpose but I am not aware to what I can use when I have to use csv.
//Accessing the csv file where I am trying to insert data.
string rootPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().CodeBase);
string filelocation = #"\csv\TestData.csv";
string location = rootPath + filelocation;
XLWorkbook workbook = new XLWorkbook(pathfile);
IXLWorksheet worksheet = workbook.Worksheet("Sheet1");
//Insert data after first row as first row contains column header
int lastrow = worksheet.LastRowUsed().RowNumber() + 1;
//through previous function I am trying get data from database and insert those data into csv cells
worksheet.Cell(String.Format("B{0}", lastrow)).Value = dummydata.FirstName;
worksheet.Cell(String.Format("C{0}", lastrow)).Value = dummydata.LastName;
worksheet.Cell(String.Format("D{0}", lastrow)).Value = dummydata.Address1;
worksheet.Cell(String.Format("E{0}", lastrow)).Value = dummydata.Address2;
worksheet.Cell(String.Format("F{0}", lastrow)).Value = dummydata.City;
worksheet.Cell(String.Format("G{0}", lastrow)).Value = dummydata.StateProvinceCode;
worksheet.Cell(String.Format("H{0}", lastrow)).Value = dummydata.ZipCode;
worksheet.Cell(String.Format("I{0}", lastrow)).Value = dummydata.Country;
worksheet.Cell(String.Format("J{0}", lastrow)).Value = dummydata.HomePhone;
worksheet.Cell(String.Format("L{0}", lastrow)).Value = dummydata.HomePhone;
worksheet.Cell(String.Format("M{0}", lastrow)).Value = dummydata.CellPhone;
worksheet.Cell(String.Format("T{0}", lastrow)).Value = dummydata.Email;
worksheet.Cell(String.Format("U{0}", lastrow)).Value = dummydata.Country;
//After inserting save the file
workbook.Save();
You can simply copy and use this code as is. It should resolve your issues.
Here's the class I developed to replace and/or add csv cells:
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
namespace CSVManager
{
public class CSVWorker
{
private string m_FileName = string.Empty;
public CSVWorker(string fileName)
{
m_FileName = fileName;
}
public void AddCells(int row, int column, string newValue)
{
var encoding = Encoding.GetEncoding("iso-8859-1");
var csvLines = File.ReadAllLines(m_FileName, encoding);
if (row < csvLines.Length)
{
ReplaceCells(row, column, newValue);
}
else
{
using (FileStream stream = new FileStream(m_FileName, FileMode.Create))
{
using (StreamWriter writer = new StreamWriter(stream, encoding))
{
foreach (var line in csvLines)
{
writer.WriteLine(line);
}
int blankLines = row - csvLines.Length - 1;
for (int i = 0; i < blankLines; i++)
{
writer.WriteLine("");
}
string blankCols = string.Empty;
for (int i = 0; i < column-1; i++)
{
blankCols += ',';
}
writer.WriteLine(blankCols + newValue);
}
}
}
}
public void ReplaceCells(int row, int column, string newValue)
{
var encoding = Encoding.GetEncoding("iso-8859-1");
var csvLines = File.ReadAllLines(m_FileName, encoding);
for (int i = 0; i < csvLines.Length; i++)
{
//var values = csvLines[i].Split(',');
List <string> values = csvLines[i].Split(',').ToList();
if (i == row)
{
if (column < values.Count)
{
values[column] = newValue;
}
else
{
while (values.Count < column - 1)
{
values.Append(",");
}
values.Append(newValue);
}
using (FileStream stream = new FileStream(m_FileName, FileMode.Create))
{
using (StreamWriter writer = new StreamWriter(stream, encoding))
{
for (int currentLine = 0; currentLine < csvLines.Length; ++currentLine)
{
if (currentLine == i)
{
writer.WriteLine(string.Join(",", values));
}
else
{
writer.WriteLine(csvLines[currentLine]);
}
}
writer.Close();
}
stream.Close();
break;
}
}
}
}
}
}
Here's how I used it:
namespace CSVManager
{
class Program
{
static void Main(string[] args)
{
string fileName = #"C:\Users\mklig\Documents\TestCsv.csv";
CSVWorker csvWorker = new CSVWorker(fileName);
int row = 4;
int col = 4;
string newVal = "success";
//csvWorker.ReplaceCells(row, col, newVal);
csvWorker.AddCells(row, col, newVal);
}
}
}

How to add a column checkbox in a datagriview with data of csv file using c#

I want to add a new column with checkbox, my data is from a csv file and showed it in a datagridview with this code:
DataTable dtDataSource = new DataTable();
string[] fileContent = File.ReadAllLines(\data.csv);
if (fileContent.Count() > 0)
{
//Create data table columns
dtDataSource.Columns.Add("ID);
dtDataSource.Columns.Add("Data 1");
dtDataSource.Columns.Add("Data 2");
dtDataSource.Columns.Add("Status");
//Add row data dynamically
for (int i = 1; i < fileContent.Count(); i++)
{
string[] rowData = fileContent[i].Split(',');
dtDataSource.Rows.Add(rowData);
}
if (dtDataSource != null)
{
dataGridView1.DataSource = dtDataSource;
}
}
But also I need to validate if checkbox is checked, the column ¨Status¨, their value must be changed by 1 or if is it unchecked the value must be 0 in every row of datagridview.
Example:
ID,Data1,Data2,Status,checkbox
1,aaa,bbb,0,✓
2,ccc,ddd,1,(unchecked)
3,eee,fff,1,(unchecked)
When you click the save button, the csv file should looks like this:
ID,Data1,Data2,Status
1,aaa,bbb,1
2,ccc,ddd,0
3,eee,fff,0
What I should do? Any ideas? CSV file is a little difficult for me.
Thank you!
I resolved this, thanks anyway..
This is the code:
string id;
for (int i = 0; i < dataGridView1.RowCount; i++) {
String path = "\\registros.csv";
List<String> lines = new List<String>();
if (File.Exists(path))
{
using (StreamReader reader = new StreamReader(path))
{
String line;
while ((line = reader.ReadLine()) != null)
{
id = (string)dataGridView1.Rows[i].Cells[2].Value;
if (line.Contains(","))
{
String[] split = line.Split(',');
if (split[1].Equals(id) && (bool)dataGridView1.Rows[i].Cells[0].FormattedValue == true)
{
split[10] = "" + 1;
line = String.Join(",", split);
}
if (split[1].Equals(id) && (bool)dataGridView1.Rows[i].Cells[0].FormattedValue == false)
{
split[10] = "" + 0;
line = String.Join(",", split);
}
}
lines.Add(line);
}
}
using (StreamWriter writer = new StreamWriter(path, false))
{
foreach (String line in lines)
writer.WriteLine(line);
}
}
}

Upload CSV data into SQL Database using MVC and EF

I am new MVC framework and trying to figure out on how to Parse the CSV file in such a way that only data from certain columns are saved to the database.
I am able to select the CSV file and upload it via the View and pass it to my controller using the following code as mentioned here Codelocker
public ActionResult UploadMultipleFiles(FileUploadViewModel fileModel)
{
//open file
if (Request.Files.Count == 1)
{
//get file
var postedFile = Request.Files[0];
if (postedFile.ContentLength > 0)
{
//read data from input stream
using (var csvReader = new System.IO.StreamReader(postedFile.InputStream))
{
string inputLine = "";
//read each line
while ((inputLine = csvReader.ReadLine()) != null)
{
//get lines values
string[] values = inputLine.Split(new char[] { ',' });
for (int x = 0; x < values.Length; x++)
{
//do something with each line and split value
}
}
csvReader.Close();
}
}
}
return View("Index");
}
However, I am not really sure as how to only select the required columns in CSV file and store it to the database?
Any suggestions guys?
Solved the problem by creating a DataTable method where by creating required columns and then using StreamReader and looping through the lines and selecting the required columns
[HttpPost]
public ActionResult UploadMultipleFiles()
{
FileUploadService service = new FileUploadService();
var postedFile = Request.Files[0];
StreamReader sr = new StreamReader(postedFile.InputStream);
StringBuilder sb = new StringBuilder();
DataTable dt = CreateTable();
DataRow dr;
string s;
int j = 0;
while (!sr.EndOfStream)
{
while ((s = sr.ReadLine()) != null)
{
//Ignore first row as it consists of headers
if (j > 0)
{
string[] str = s.Split(',');
dr = dt.NewRow();
dr["Postcode"] = str[0].ToString();
dr["Latitude"] = str[2].ToString();
dr["Longitude"] = str[3].ToString();
dr["County"] = str[7].ToString();
dr["District"] = str[8].ToString();
dr["Ward"] = str[9].ToString();
dr["CountryRegion"] = str[12].ToString();
dt.Rows.Add(dr);
}
j++;
}
}
service.SaveFilesDetails(dt);
sr.Close();
return View("Index");
}

How can I read the Uploaded CSV file without saving it to Server?

Hi all, I have CSV files which are in this format:
**CSV Format1**
||OrderGUID||OrderItemID||Qty||SKUID||TrackingNumber||TotalWeight||DateShipped||DateDelivered||ShippingStatusId||OrderShippingAddressId
||5 ||3 ||2 ||12312||aasdasd ||24 ||2012-12-2010|| || 10025 ||10028
||5 ||4 ||3 ||113123||adadasdasd ||22 ||2012-12-2012|| ||10026 ||10028
**CSV Format2**
||"OrderGUID"||"OrderItemID"||"Qty"||"SKUID"||"TrackingNumber"||"TotalWeight"||"DateShipped"||"DateDelivered"||"ShippingStatusId"||"OrderShippingAddressId"||
||"5" ||"3" ||"2" ||"12312"||"aasdasd" ||"24" ||"2012-12-2010"||"" || "10025" ||"10028"||
||"5" ||"4" ||"3" ||"113123"||"adadasdasd" ||"22" ||"2012-12-2012"|| "2012-12-2010" ||"10026" ||"10028"||
I have to read these files without saving them on the server. Can anyone help me? How can I read this files and insert in my db? How can I trim the special characters from the files?
This is what I am trying to do for the file upload:
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult ImportTrackingNumber(FormCollection form,HttpPostedFileBase UploadedFile,TrackingNumbersModel Trackingnumbers)
{
if (UploadedFile != null)
{
var allowedExtensions = new[] {".xlsx", ".csv"};
if (UploadedFile.ContentLength > 0)
{
var extension = Path.GetExtension(UploadedFile.FileName);
if (extension == ".xlsx")
{
//Need To code For Excel Files Reading
}
else if (extension == ".csv")
{
//string filename = Path.GetFileName(UploadedFile.PostedFile.InputStream);
StreamReader csvreader = new StreamReader(UploadedFile.FileName);
DataTable dt;
}
}
}
return View();
}
Just an example on how you can read the uploaded file without saving it on the server:
// Use the InputStream to get the actual stream sent.
using (StreamReader csvReader = new StreamReader(UploadedFile.InputStream))
{
while (!csvReader.EndOfStream)
{
var line = csvReader.ReadLine();
var values = line.Split(';');
}
}
This is my code:
public static DataTable GetDataTabletFromCSVFile(HttpPostedFileBase file)
{
DataTable csvDataTable = new DataTable();
// Read bytes from http input stream
var csvBody = string.Empty;
using (BinaryReader b = new BinaryReader(file.InputStream))
{
byte[] binData = b.ReadBytes(file.ContentLength);
csvBody = Encoding.UTF8.GetString(binData);
}
var memoryStream = new MemoryStream();
var streamWriter = new StreamWriter(memoryStream);
streamWriter.Write(csvBody);
streamWriter.Flush();
memoryStream.Position = 0;
using (TextFieldParser csvReader = new TextFieldParser(memoryStream))
{
csvReader.SetDelimiters(new string[] { "," });
csvReader.HasFieldsEnclosedInQuotes = true;
string[] colFields = csvReader.ReadFields();
foreach (string column in colFields)
{
DataColumn datecolumn = new DataColumn(column);
datecolumn.AllowDBNull = true;
csvDataTable.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;
}
}
csvDataTable.Rows.Add(fieldData);
}
}
return csvDataTable;
}

Categories