Read fields in CSV format with C#

Asked

Viewed 472 times

-1

Boas, I am currently developing an app (console app) to read data from a file in CSV format using C#. Right now I’m able to run all the fields without any kind of problem and show all the data. Anyway I’m having trouble reading more specific fields from the file you can see in the following image. Ficheiro CSV At this moment my intention is to make a call to fields using conditional expressions. Examples of what I want the application to return include: All customers between 20 and 30 years. All vehicles registered before 1 January 2010. All vehicles with the enginesize 1100.

Here is the current code:

  public static void ReadRecord()

    {
      Console.WriteLine(string.Join(" ", readRecord ("1190", @"C:\CustomerInformation.csv", 9)));
       Console.ReadLine();
    }



    public static void addRecord(string CustomerID, string Forename, string DateOfBirth, string filepath)

    {
        try
        {
            using (System.IO.StreamWriter file = new System.IO.StreamWriter(filepath, true))
            {
                file.WriteLine(CustomerID + ",                 " + Forename + ",                    " + DateOfBirth);
            }
        }

        catch (Exception ex)
        {
            throw new ApplicationException("This program did an oopsie :", ex);
        }
    }




    public static string[] readRecord(string searchTerm, string filepath, int positionOfSearchTerm)
    {
        positionOfSearchTerm--;
        string[] recordNotFound = { "Record not found" };

        try
        {
            string[] lines = System.IO.File.ReadAllLines(@filepath);

            for (int i = 0; i < lines.Length; i++)
            {
                string[] fields = lines[i].Split(',');
                if (recordMatches(searchTerm, fields, positionOfSearchTerm))
                {
                    Console.WriteLine("Record found");
                    return fields;
                }

            }

            return recordNotFound;


        }

        catch (Exception ex)
        {
            Console.WriteLine("Unknown Error");
            return recordNotFound;
            throw new ApplicationException("Unknown Error:", ex);
        }
    }

    public static bool recordMatches(string searchTerm, string[] record, int positionOfSearchTerm)

    {
        if (record[positionOfSearchTerm].Equals(searchTerm))
        {
            return true;
        }
        return false;
    }

Current Outcome resultado destacado em vermelho

Of course the application only returns a simple value, I have looked for some techniques and ways to be able to return multiple values, but without great success and would appreciate some help if it were possible.

  • There are several things to improve there, I can try to write an example for you, but I would need a template of this CSV file, you can upload one with 10 lines at most?

  • Yes, of course. You can download the file here: https://gofile.io/? c=udpk4D Thanks for the help.

  • Please don’t alter your question to circumvent the system. So you invalidate my answer and, with it, throw away the effort I had to answer it. All right you remove the accept, but don’t change the context of your question...

  • I am sorry, that was not the intention but rather to ask the question in a way that was more understandable in order to avoid repeaters, since the aim of both topics was the same. Greetings.

  • Did the answer meet the request? Need to be added some more detail?

  • Unfortunately no. The program was far from the required standards and it was not possible to provide the required data within the application itself.

Show 1 more comment

1 answer

1

There are some things to tidy up in your code and, in general, the solution as a whole could be a little better. When I started writing the answer I thought about proposing an adapted solution, but that would change your initial code a lot and I don’t know if that would be beneficial now. Therefore, I decided to only adapt your original code to address the issue you report in your publication...

Some points I find interesting to mention before showing the solution:

  • Don’t capture exceptions if you’re not going to do something useful with them, if you need to at least transcribe it somewhere (even if it’s a message box) do it at the code entry point (in the method Main() or something similar). Here on the site there are some publications that talk about it, for example:

  • The return of the method Equals is a boolean, so this:

    if(record[positionOfSearchTerm].Equals(searchTerm)) 
        return true; 
    else 
        return false;
    

    is exactly the same thing as this:

    return record[positionOfSearchTerm].Equals(searchTerm);
    

    and the second way is much more lean and simple to read;

  • The method readRecord should not be responsible for the message "Record not found", it should be in charge of the method that calls it. It would be a good idea if the readRecord just return an empty set to your caller when you find no record that meets the search criteria;;

  • It’s not a rule at all, but there is a nomenclature convention for C#, maybe it’s a nice reference to guide you in your choice of names.

To solve your problem, you need:

  1. Changing the method signature readRecord so that it is possible to return a collection of string[];

    IEnumerable<string[]> ReadRecord(string searchTerm, string filepath, int positionOfSearchTerm)
    
  2. Create a list to add all found items according to the search criteria;

    var retorno = new List<string[]>();
    
  3. Instead of returning the first record found, add it to the created list;

    retorno.Add(fields);
    
  4. Use list as return of method.

See the complete method:

IEnumerable<string[]> ReadRecord(string searchTerm, string filepath, int positionOfSearchTerm)
{
    positionOfSearchTerm--;

    string[] lines = System.IO.File.ReadAllLines(filepath);

    var retorno = new List<string[]>(); // Lista para retornar todos itens encontrados
    for (int i = 0; i < lines.Length; i++)
    {
        string[] fields = lines[i].Split(',');
        if (recordMatches(searchTerm, fields, positionOfSearchTerm))
        {
            Console.WriteLine("Record found");
            retorno.Add(fields); // Adicionar resultados na lista
        }
    }
    return retorno;
}

See working on Repl.it. The code is also on Github.

  • I take this opportunity to thank you for the answer. In fact the use of readRecord is probably what has been most problematic. In fact the application can already read more than one line, which brings me to the second problem. Considering that the account I intend to use operators to do a query for example returns a response from an engineSize larger than 1100 there is some way to adapt to this code? I don’t mind rewriting all this since I know that there are certain limitations in this current context and the program is small.

  • @Rui I’m not sure I understand what you meant. Maybe it’s a case for open a new question and explain what problems you intend to solve... By the way, if the answer met the context of this specific question you can mark it as correct using the left side of the publication.

  • It is simple, in the file that was sent there is a field called "Enginesize": Given the question each car has a size relative to the engine. And basically what I would like the show to do is to show the "Records" for cars that have an engine equal to or greater than 1100. A bit as you do in SQL.

  • @Rui would have to adapt a lot the solution. As I commented, this is the case for another question.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.