Hello! In my program, the search for a string in a file is organized, I would like to improve the search and make it possible to search for a given column. How best to implement this feature?

//Дерректива переменной static string path = @"F:\test21.csv"; //Задаем переменную "х" строкового типа static string x = ""; static void Main(string[] args) { try { //Заносим значение csv-файла в массив string[] sr = new StreamReader(Search.path).ReadToEnd().Split(new string[] { ";", """, ":", "\r" }, StringSplitOptions.None); Console.Write("Введите значение: "); x = Console.ReadLine(); foreach (string stroka in sr) { if (stroka == x) { Console.WriteLine("Результат поиска: {0}",stroka); break; } } } catch (Exception ex) { Console.WriteLine(ex.Message); } Console.WriteLine("Press Key to Exit..."); Console.ReadKey(); } } 
  • under question there is a button Править , to edit the text of the question, please use it and add what kind of search is needed. 1. What we are looking for - the row number in which there is a match with the sample, the column number or both, or just the fact of the match. 2. Ideal - attach a minimal example of the source csv-file (no huge one is needed, 3x3 is enough), a sample for the search and the expected result. Then I can quickly complete the answer. - rdorn

3 answers 3

make it possible to search for a given column

There are several options to implement a search in a CSV file by column.

1. Use DataTable

 private DataTable CsvToDataTable(string fileName) { var dt = new DataTable("FileData"); //Если первая строка содержит заголовки столбцов, формируем из нее столбцы таблицы, если нет, придется делать вручную. var header = File.ReadLines(fileName).First(); var colHeaders = header.Split(';'); foreach(var hdr in colHeaders) { dt.Columns.Add(hdr); } //Все строки файла кроме первой заносим в качестве строк таблицы foreach(var row in File.ReadLines(fileName).Skip(1)) { var values = row.Split(';'); dt.Rows.Add(values); } return dt; } 

The table is formed, now you can perform a search, for example:

 var dt = CsvToDataTable("C:\\test.csv"); var findResult = dt.Select("ColName = 'searchText'"); 

As a result, we obtain an array from DataRow for which the given condition is fulfilled. Of course, the condition must be written using real column names.

2. We are looking for on the fly without full file download

 var colIndex = x;//x - номер интересующего столбца, нумерация с 0 var searchText = "searchText"; //пропускаем первую строку, если в ней заголовки с помощью Skip foreach(var row in File.ReadLines(fileName).Skip(1)) { var values = row.Split(';'); if(values[colIndex] == searchText) { Console.WriteLine("Результат поиска: {0}",stroka); break; } } 

In both cases, the trick is that when splitting a string from a CSV file, you cannot use StringSplitOptions.RemoveEmptyEntries so that the column indexes do not change if individual values ​​in the string are omitted, and the source CSV file format must be correct.

3. Is it possible somehow?

Can. There are many different options, these are just examples of a possible implementation, which particular option of all possible uses depends on the specific task.

  • You gave the correct answer, I just wanted to implement it a little differently, that is, so that the value of colIndex would not be static, such as 0,1,2,3, but equal to the value found in the array, that is, if using a for loop we determined that the value we need is in the i-th value, so we substitute i. Below, in the code, it is visible, but it does not work quite correctly. - Tibomso
  • deleted your comments as little informative - rdorn
  • @Tibomso is not surprising, you read the entire file in one line and split it. As a result, you get a one-dimensional array instead of a table. - rdorn
  • @Tibomso File.ReadLines is Enuberable, it reads one line at a time. If you really want everything at once in memory, then ReadAllLines - look, it returns an array of strings. The string is counted up to the newline character ("\ n" or "\ r \ n"). The csv is a two-dimensional format and cannot be read in a single line, or rather, you can, but not necessary. - rdorn
  • @Tibomso I said about him, you are reading a two-dimensional table in a one-dimensional array, hence the problems - rdorn
  try { //Заносим значение csv-файла в массив string[] sr = new StreamReader(path).ReadToEnd().Split(new string[] { ";", "\"", ":", "\r" }, StringSplitOptions.None); Console.Write("Введите значение колонки: "); x = Console.ReadLine(); Console.Write("Введите значение поиска: "); y = Console.ReadLine(); //создаем переменную для сортировки int strIndex = 0; //выполняем поиск строки for (int i = 0; i < sr.Length; i++) { strIndex = sr[i].IndexOf(x); //если strIndex не отрицательное, то выполняем поиск if (strIndex >= 0) { foreach (string col in File.ReadAllLines(path)) { var values = col.Split(';'); if (values[i] == y) { Console.WriteLine("Результат поиска: {0} = {1}", x, y); } } break; } } } catch (Exception ex) { Console.WriteLine(ex.Message); } Console.WriteLine("Press any key to exit..."); Console.ReadKey(); 

    Answers rdorn and Tibomso will not work in all cases. Because Answers support far not full CSV. Namely:

    • There is no support for reading tsv when there can be many lines in one cell
    • There is no support for reading tsv when inside the cell there is a separating character itself (then the cell is quoted in quotes)

    If you use this reader of CSV files: How easy it is to work with / open / change / save Excel / CSV files

    That search on a specific column of the first value that appears will look like this:

     Csv csv = new Csv(); csv.FileOpen(someFilePath); foreach (rowCell in csv.Rows) { //поиск по второму столбцу if( rowCell[1].Contains( valueToSearch) ) { //сделать что нужно } } 

    which is quite easy to modify to the needs