Search code examples
c#csvembedded-resource

Exception when creating a Stream from csv file


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() + ";  ";
                        }
                    }
                }
            }

Solution

  • 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));