Loop through sub directories in directory - c#

I have a directory 'Folder' with many subdirectories inside this directory. Inside every subdirectory there are many images. I want to loop through subdirectories in the 'Folder' directory, then loop through all images in every directory to export the images out to Excel, with images from each subdirectory in one Excel worksheet.
For e.g. if I have ten subdirectories, I should have one Excel workbook with ten Excel worksheets, then in each Excel worksheet there will be images from each subdirectory.
This is what I have tried but images only appeared on Worksheet1 instead of all the worksheets:
public void ExportToExcel()
{
//for export
ExcelPackage objExcelPackage = new ExcelPackage(); //create new workbook
string[] filesindirectory = Directory.GetDirectories(Server.MapPath("~/Folder"));
int count = 0;
int count1 = 0;
int x = 25;
int finalValue = 0;
foreach (string subdir in filesindirectory)
{
count++;
ExcelWorksheet ws = objExcelPackage.Workbook.Worksheets.Add("Worksheet" + count); //create new worksheet
foreach (string img in Directory.GetFiles(subdir))
{
count1++;
System.Web.UI.WebControls.Image TEST_IMAGE = new System.Web.UI.WebControls.Image();
System.Drawing.Image myImage = System.Drawing.Image.FromFile(img);
var pic = ws.Drawings.AddPicture(count1.ToString(), myImage);
// Row, RowoffsetPixel, Column, ColumnOffSetPixel
if (count1 > 1)
{
pic.SetPosition(finalValue, 0, 2, 0);
finalValue += (x + 1); // Add 1 to have 1 row of empty row
}
else
{
pic.SetPosition(count1, 0, 2, 0);
finalValue = (count1 + x) + 1; // Add 1 to have 1 row of empty
}
}
}
var filepath = new FileInfo(#"C:\Users\user\Desktop\Test\" + datetime.ToString("dd-MM-yyyy_hh-mm-ss") + ".xlsx");
objExcelPackage.SaveAs(filepath);
}
How to loop through each sub directories in a directory, then loop through all images from each sub directory using C#?

Janne Matikainen answer is correct but you need to know how to modify in your code...
First change your code this line
string[] filesindirectory = Directory.GetFiles(Server.MapPath("~/Folder"));
to
string[] filesindirectory = Directory.GetDirectories(Server.MapPath("~/Folder"));
Secondly you need to search file in your sub folder path which is your
foreach (string subdir in filesindirectory)
subdir is your path for your directory.
Just do back the same thing what you did to get the files
foreach (string img in Directory.GetFiles(subdir))
After you finish the foreach subdirectory
foreach (string img in Directory.GetFiles(subdir))
{
// Your Code
}
// Reset the Count1
count1 = 0;
Reset it because you are increasing for dynamic row generating for each sheet.
Then you at new sheet and you didn't reset it. It will continue the count as per previous sheet.
To get the folder name you can easily get it by split.
Before you create the worksheet you do as per below.
string[] splitter = subdir.Split('\\');
string folderName = splitter[splitter.Length - 1];
Take NOTES if the folderName contain some symbol it might not able to set it to excel worksheet and also the name cannot be too long.
Please ensure that you replace with supportable symbol for excel worksheet

This should list all files starting from C:\Images and go through all subdirs and their subdirs as well.
public void ExportToExcel()
{
//for export
var objExcelPackage = new ExcelPackage(); //create new workbook
this.ListFiles(objExcelPackage, 0, Server.MapPath("~/Folder"));
var filepath = new FileInfo(#"C:\Users\user\Desktop\Test\" + datetime.ToString("dd-MM-yyyy_hh-mm-ss") + ".xlsx");
objExcelPackage.SaveAs(filepath);
}
public void ListFiles(ExcelPackage objExcelPackage, int worksheetIndex, string path)
{
var imageCount = 0;
var x = 25;
var finalValue = 0;
var files = Directory.GetFiles(path).Select(s => new FileInfo(s));
if (files.Any())
{
//create new worksheet
var ws = objExcelPackage.Workbook.Worksheets.Add("Worksheet" + (++worksheetIndex));
foreach (var file in files)
{
imageCount++;
var TEST_IMAGE = new System.Web.UI.WebControls.Image();
var myImage = System.Drawing.Image.FromFile(img);
var pic = ws.Drawings.AddPicture(imageCount.ToString(), myImage);
// Row, RowoffsetPixel, Column, ColumnOffSetPixel
if (imageCount > 1)
{
pic.SetPosition(finalValue, 0, 2, 0);
finalValue += (x + 1); // Add 1 to have 1 row of empty row
}
else
{
pic.SetPosition(imageCount, 0, 2, 0);
finalValue = (imageCount + x) + 1; // Add 1 to have 1 row of empty
}
}
}
foreach (var dir in Directory.GetDirectories(path))
{
this.ListFiles(objExcelPackage, worksheetIndex, dir);
}
}

Directory.GetFiles(dir) returns all files in dir, without folders
you should use Directory.EnumerateDirectories(dir)
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
class Program
{
private static void Main(string[] args)
{
try
{
string dirPath = #"\\archives\2009\reports";
List<string> dirs = new List<string>(Directory.EnumerateDirectories(dirPath));
foreach (var dir in dirs)
{
Console.WriteLine("{0}", dir.Substring(dir.LastIndexOf("\\") + 1));
}
Console.WriteLine("{0} directories found.", dirs.Count);
}
catch (UnauthorizedAccessException UAEx)
{
Console.WriteLine(UAEx.Message);
}
catch (PathTooLongException PathEx)
{
Console.WriteLine(PathEx.Message);
}
}
}

The Composite Pattern fits your problem here.
public interface IExcelWorksheetAdapter
{
//todo: implement this method, here you have everything you need for an image file
void AddPicture(FileSystemItem aFile);
}
public class FileSystemItem
{
public virtual string FullPath { get; protected set; }
public virtual int Level { get; set; }
public virtual string Name
{
get
{
if (string.IsNullOrWhiteSpace(FullPath)) return string.Empty;
return FullPath.Split('\\').Last();
}
}
public virtual void Operation(IExcelWorksheetAdapter ws) { }
}
public class FolderItem : FileSystemItem
{
public FolderItem(string fullPath)
{
Items = new List<FileSystemItem>();
if (!Directory.Exists(fullPath)) return;
FullPath = fullPath;
var files = Directory.GetFiles(FullPath).Select(p => new FileItem(p) { Level = this.Level + 1 }).ToList();
Items.AddRange(files);
var subFolders = Directory.GetDirectories(fullPath).Select(p => new FolderItem(p) {Level = this.Level + 1}).ToList();
Items.AddRange(subFolders);
}
public List<FileSystemItem> Items { get; set; }
public override void Operation(IExcelWorksheetAdapter ws)
{
Items.ForEach(x => x.Operation(ws));
}
}
public class FileItem : FileSystemItem
{
public FileItem(string path)
{
if (File.Exists(path))
{
FullPath = path;
}
}
public override void Operation(IExcelWorksheetAdapter ws)
{
ws.AddPicture(this);
}
}
[TestFixture]
public class DirectoryCompositeTest
{
[Test]
public void Operation_for_a_directory_files()
{
var directory = new FolderItem(AppDomain.CurrentDomain.BaseDirectory);
directory.Operation(new Sample()); // give your IExcelWorksheetAdapter implementation here.
}
}
public class Sample : IExcelWorksheetAdapter
{
public void AddPicture(FileSystemItem aFile)
{
Console.WriteLine(Indent(aFile.Level) + aFile.Name);
}
private string Indent(int level)
{
string result = "";
for (int i = 0; i < level; i++)
{
result += "-";
}
return result;
}
}

Related

Read lines of data from CSV then display data

I have to read info from a txt file, store it in a manner (array or list), then display the data. Program must include at least one additional class.
I've hit a wall and can't progress.
string, string, double, string
name,badge,salary,position
name,badge,salary,position
name,badge,salary,position
I'm sorry and I know the code below is disastrous but I'm at a loss and am running out of time.
namespace Employees
{
class Program
{
static void Main()
{
IndividualInfo collect = new IndividualInfo();
greeting();
collect.ReadInfo();
next();
for (int i = 0; i < 5; i++)
{
displayInfo(i);
}
exit();
void greeting()
{
Console.WriteLine("\nWelcome to the Software Development Company\n");
}
void next()
{
Console.WriteLine("\n*Press enter key to display information . . . *");
Console.Read();
}
void displayInfo(int i)
{
Console.WriteLine($"\nSoftware Developer {i + 1} Information:");
Console.WriteLine($"\nName:\t\t\t{collect.nameList[i]}");
}
void exit()
{
Console.WriteLine("\n\n*Press enter key to exit . . . *");
Console.Read();
Console.Read();
}
}
}
}
class IndividualInfo
{
public string Name { get; set; }
//public string Badge{ get; set; }
//public string Position{ get; set; }
//public string Salary{ get; set; }
public void ReadInfo()
{
int i = 0;
string inputLine;
string[] eachLine = new string[4];
string[,] info = new string[5, 4]; // 5 developers, 4x info each
StreamReader file = new StreamReader("data.txt");
while ((inputLine = file.ReadLine()) != null)
{
eachLine = inputLine.Split(',');
for (int x = 0; x < 5; x++)
{
eachLine[x] = info[i, x];
x++;
}
i++;
}
string name = info[i, 0];
string badge = info[i, 1];
string position = info[i, 2];
double salary = Double.Parse(info[i, 3]);
}
public List<string> nameList = new List<string>();
}
So far I think I can collect it with a two-dimensional array, but a List(s) would be better. Also, the code I've posted up there won't run because I can't yet figure out a way to get it to display. Which is why I'm here.
using System.IO;
static void Main(string[] args)
{
using(var reader = new StreamReader(#"C:\test.csv"))
{
List<string> listA = new List<string>();
List<string> listB = new List<string>();
while (!reader.EndOfStream)
{
var line = reader.ReadLine();
var values = line.Split(';');
listA.Add(values[0]);
listB.Add(values[1]);
}
}
}
https://www.rfc-editor.org/rfc/rfc4180
or
using Microsoft.VisualBasic.FileIO;
var path = #"C:\Person.csv"; // Habeeb, "Dubai Media City, Dubai"
using (TextFieldParser csvParser = new TextFieldParser(path))
{
csvParser.CommentTokens = new string[] { "#" };
csvParser.SetDelimiters(new string[] { "," });
csvParser.HasFieldsEnclosedInQuotes = true;
// Skip the row with the column names
csvParser.ReadLine();
while (!csvParser.EndOfData)
{
// Read current line fields, pointer moves to the next line.
string[] fields = csvParser.ReadFields();
string Name = fields[0];
string Address = fields[1];
}
}
http://codeskaters.blogspot.ae/2015/11/c-easiest-csv-parser-built-in-net.html
or
LINQ way:
var lines = File.ReadAllLines("test.txt").Select(a => a.Split(';'));
var csv = from line in lines
select (from piece in line
select piece);
^^Wrong - Edit by Nick
It appears the original answerer was attempting to populate csv with a 2 dimensional array - an array containing arrays. Each item in the first array contains an array representing that line number with each item in the nested array containing the data for that specific column.
var csv = from line in lines
select (line.Split(',')).ToArray();
This question was fully addressed here:
Reading CSV file and storing values into an array

How read and search multiple txt files in listBox with (in) one button c#?

private void btnOpen_Click(object sender, EventArgs e)
{
FolderBrowserDialog fbd = new FolderBrowserDialog();
if (fbd.ShowDialog() == DialogResult.OK)
{
listBox1.Items.Clear();
string[] allfiles = Directory.GetFiles(fbd.SelectedPath, "*.txt*",
SearchOption.AllDirectories);
foreach (string file in allfiles)
{
FileInfo info = new FileInfo(file);
listBox1.Items.Add(Path.GetFileName(file));
}
}
}
There is listbox1 with all .txt files from direcory and subfolder...
Now I need from this listBox all files and search by some string.
Can I iterate loop and read file by file?
I don't have an idea how read and search files, need I open first, then store a data of file somewhere, maybe list or listView?
First, I would use a class of its own to store your search results. When we search files, and if we find the keyword we're searching for, we'd create an object of this class and at it to a list. Something like this:
public class SearchResults
{
public string FilePath { get; set; }
public string SearchWord { get; set; }
public int Occurences { get; set; }
}
Then you can use the System.IO.File class to read your files. Remember this is not the only way, but merely one way of doing it. Here I have a list of file names, which is equivalent to the array you have in your program.
var searchTerm = "Hello";
var fileList = new List<string>() { "A.txt", "B.txt", "C.txt" };
var resultList = new List<SearchResults>();
// Iterate through files. You already are doing this.
foreach (var file in fileList)
{
// Check to see if file exists. This is a second line of defense in error checking, not really necessary but good to have.
if (File.Exists(file))
{
// Read all lines in the file into an array of strings.
var lines = File.ReadAllLines(file);
// In this file, extract the lines contain the keyword
var foundLines = lines.Where(x => x.Contains(searchTerm));
if (foundLines.Count() > 0)
{
var count = 0;
// Iterate each line that contains the keyword at least once to see how many times the word appear in each line
foreach (var line in foundLines)
{
// The CountSubstring helper method counts the number of occurrences of a string in a string.
var occurences = CountSubstring(line, searchTerm);
count += occurences;
}
// Add the result to the result list.
resultList.Add(new SearchResults() { FilePath = file, Occurences = count, SearchWord = searchTerm });
}
}
}
The CountSubstring() helper method.
public static int CountSubstring(string text, string value)
{
int count = 0, minIndex = text.IndexOf(value, 0);
while (minIndex != -1)
{
minIndex = text.IndexOf(value, minIndex + value.Length);
count++;
}
return count;
}

List values are not being stored

Can someone please tell me what I'm missing, the class reads values from a text file and should store them for other use, I can see the values with
Console.Write(eachCell[0]) but I can't save the values. I've tried using
string[] and List<string> but no luck. It should store the values being read to a list or array but so far it is not. Nothing shows on the console.
class test
{
public void tryOut()
{
#region file.read
try
{
string fileLocation = #"shelfInfo.txt";
List<string> cells = File.ReadAllLines(fileLocation).ToList();
aray(cells);
}
catch
{
new FileNotFoundException();
}
#endregion
}
public void aray(List<string> cells)
{
string[] t = new string[20];
string[] k = new string[20];
string a = "", b = "", c = "", d = "";
int i = 0;
foreach (string cell in cells)
{
string[] eachCell = cell.Split('#', '\t', '\n');
a = t[0] = eachCell[0].ToString(); //Consol.Write on eachCell directly shows the right values.
b = t[1] = eachCell[1].ToString();
c = t[2] = eachCell[2].ToString();
d = t[3] = eachCell[3].ToString();
for (; i < eachCell.Length; i++)
{
k[i] = a; //should store the values from eachCell
}
}
Console.Write(" " + a + " " + b + " " + " " + c + " " + d); //means the value are being receivedbut no stored
}
}
// contents of text file
//A11[1]# A12[0]# A13[1]# A14[1]#
//A21[1]# A21[1]# A23[0]# A24[0]#
//A31[1]# A32[0]# A33[1]# A34[1]#
//A41[1]# A41[1]# A43[0]# A44[0]#
I'd also, appreciate any tips on exception handling.
Your program doesn't return anything because you use the following code.
catch { new FileNotFoundException(); }
Console.Write return nothing just because the exception is caught but it doesn't throw a new exception. There is an exception because eachCell doesn't contain 4 elements and you try to access the element. In fact, you don't have to do the try-catch unless you want to handle this exception manually. If the file isn't there, a FileNotFoundException would already be thrown automatically. Change the tryOut method as the following.
public void tryOut()
{
#region file.read
var fileLocation = #"Path";
aray(File.ReadAllLines(fileLocation).ToList());
#endregion
}
public static void aray(List<string> cells)
{
List<string> t = new List<string>();
foreach (string cell in cells)
{
string[] eachCell = cell.Split('#', '\t');
foreach (var e in eachCell)
{
t.Add(e);
}
}
foreach (var e in t)
{
Console.WriteLine(e);
}
}

c# How to iterate through the file system and assign numbering

I have a problem that is doing my head in.
I want to iterate through the local PC folders, including directories, and calculate a numbering system against each folder in the file system hierarchy.
The root folders should calculate as 1,2,3 etc.
If there were three sub-folders in folder one the calculated numbers should be:
1.1, 1.2,1.3
If there were three sub-folders in the sub-folder above then the calculated numbers should be:
1.1.1, 1.1.2, 1.1.3
If there were three sub-folders in folder two (a root folder) the calculated numbers should be:
2.1, 2.2, 2.3
Or expressed in another way:
1 Root Folder
1.1 Root Sub Folder 1
1.1.1 Sub Folder
1.1.2 Sub Folder
1.2 Root Sub Folder 2
1.2.1 List item
1.2.2 List item
etc. etc.
This logic should then be applied to all folders and sub-folders.
Output Example
1.1.1 | "c:\Root\Folder1\Folder1\"
What I have so far appears to work ok in some situations but can fail in other situations:
private string rootpath = #"C:\FolderHierarchy\";
private string FolderSequenceCountBase = "";
private int CurrentRootPathCount = 0;
private int Counter = 0;
private void CalculateFolderHierarchyNumbers()
{
//Get First List of Folders
string[] Dirs = Directory.GetDirectories(rootpath, "*.*", SearchOption.TopDirectoryOnly);
for (int i = 0; i < Dirs.Count(); i++)
{
FolderSequenceCountBase = (i + 1).ToString();
CurrentRootPathCount = i + 1;
Console.WriteLine("Processed folder '{0}'.", Dirs[i] + " = " + (i + 1));
GetSubDirs(Dirs[i]);
}
}
private void GetSubDirs(string item)
{
//Get next list of folders in the folder hierarchy
string[] SubDirs = Directory.GetDirectories(item, "*.*", SearchOption.TopDirectoryOnly);
foreach (var DirPath in SubDirs)
{
//Increment count of folders within the current folder list
Counter += 1;
Console.WriteLine("Processed folder '{0}'.", DirPath + " = " + FolderSequenceCountBase + "." + Counter);
}
Counter = 0;
//Get next list of folders in the folder hierarchy
foreach (var DirPath in SubDirs)
{
FolderSequenceCountBase += ".1";
GetSubDirs(DirPath);
}
}
Hope this is clear.
Thanks
Rick
So you want to find a file and get it's the number of it in the of directory and all of it's parent directories? Since i found it interesting i've written something from scratch. Note that it's currently not tested but it might give you an idea anyway:
public static IEnumerable<FileEntryInfo> EnumerateFindFiles(string fileToFind, StringComparison comparison = StringComparison.CurrentCultureIgnoreCase, DirectoryInfo rootDir = null, string[] drivesToSearch = null)
{
IEnumerable<FileEntryInfo> foundEntries = Enumerable.Empty<FileEntryInfo>();
if (rootDir != null && drivesToSearch != null)
throw new ArgumentException("Specify either the root-dir or the drives to search, not both");
else if (rootDir != null)
{
foundEntries = EnumerateFindEntryRoot(fileToFind, rootDir, comparison);
}
else
{
if (drivesToSearch == null) // search the entire computer
drivesToSearch = System.Environment.GetLogicalDrives();
foreach (string dr in drivesToSearch)
{
System.IO.DriveInfo di = new System.IO.DriveInfo(dr);
if (!di.IsReady)
{
Console.WriteLine("The drive {0} could not be read", di.Name);
continue;
}
rootDir = di.RootDirectory;
foundEntries = foundEntries.Concat(EnumerateFindEntryRoot(fileToFind, rootDir, comparison));
}
}
foreach (FileEntryInfo entry in foundEntries)
yield return entry;
}
public class FileEntryInfo
{
public FileEntryInfo(string path, int number)
{
this.Path = path;
this.Number = number;
}
public int Number { get; set; }
public string Path { get; set; }
public FileEntryInfo Root { get; set; }
public IEnumerable<int> GetNumberTree()
{
Stack<FileEntryInfo> filo = new Stack<FileEntryInfo>();
FileEntryInfo entry = this;
while (entry.Root != null)
{
filo.Push(entry.Root);
entry = entry.Root;
}
while(filo.Count > 0)
yield return filo.Pop().Number;
yield return this.Number;
}
public override bool Equals(object obj)
{
FileEntryInfo fei = obj as FileEntryInfo;
if(obj == null) return false;
return Number == fei.Number && Path == fei.Path;
}
public override int GetHashCode()
{
return Path.GetHashCode();
}
public override string ToString()
{
return Path;
}
}
private static IEnumerable<FileEntryInfo> EnumerateFindEntryRoot(string fileNameToFind, DirectoryInfo rootDir, StringComparison comparison = StringComparison.CurrentCultureIgnoreCase)
{
Queue<FileEntryInfo> queue = new Queue<FileEntryInfo>();
FileEntryInfo root = new FileEntryInfo(rootDir.FullName, 1);
queue.Enqueue(root);
while (queue.Count > 0)
{
FileEntryInfo fe = queue.Dequeue();
List<FileEntryInfo> validFiles = new List<FileEntryInfo>();
try
{ // you cannot yield from try-catch, hence this approach
FileAttributes attr = File.GetAttributes(fe.Path);
//detect whether its a directory or file
bool isDirectory = (attr & FileAttributes.Directory) == FileAttributes.Directory;
if (isDirectory)
{
int entryCount = 0;
foreach (string entry in Directory.EnumerateFileSystemEntries(fe.Path))
{
entryCount++;
FileEntryInfo subEntry = new FileEntryInfo(entry, entryCount);
subEntry.Root = fe;
queue.Enqueue(subEntry);
attr = File.GetAttributes(entry);
isDirectory = (attr & FileAttributes.Directory) == FileAttributes.Directory;
if(!isDirectory)
validFiles.Add(subEntry);
}
}
} catch (Exception ex)
{
Console.Error.WriteLine(ex); // ignore, proceed
}
foreach (FileEntryInfo entry in validFiles)
{
string fileName = Path.GetFileName(entry.Path);
if (fileName.Equals(fileNameToFind, comparison))
yield return entry;
}
}
}
Here's how i tested it:
var allEntriesFound = EnumerateFindFiles("PresentationFramework.dll").ToList();
if(allEntriesFound.Any())
{
foreach (FileEntryInfo entry in allEntriesFound)
Console.WriteLine("{0}: Number: {1}", entry.Path, entry.Number);
// here your exact requirement:
string result = string.Join(".", allEntriesFound[0].GetNumberTree());
Console.WriteLine(result);
}
Added also a way to specify the root directory to prevent that the whole file system is searched, Usage:
var allEntriesFound = EnumerateFindFiles(
"PresentationFramework.dll",
StringComparison.CurrentCultureIgnoreCase,
new DirectoryInfo(#"C:\Windows"))
.ToList();

Performance problems with Linq To CSV

I have found a library which connects csv-files with linq. I understood the principles and my code works well. But i have some problems with big csv files.
http://www.codeproject.com/Articles/25133/LINQ-to-CSV-library
Now i want to access specific single items from my _dataTable object. I get them like this:
public class CsvFile
{
private IEnumerable<DataRow> _dataTable = cc.Read<DataRow>(_filePath, _inputFileDescription);
public string GetItem(int row, int column)
{
return _dataTable.ElementAt<DataRow>(row).ElementAt<DataRowItem>(column).Value;
}
}
When i now call the method like this in a loop:
CsvFile file1 = new CsvFile("C:\\dev_csvcompare\\Master.csv", ';', true);
for(int i = 0; i < 10000; i++)
{
string dummy = file1.GetItem(1, i); //Does not make sense, my loop is a bit more complicated
}
it gets very slow, because the IEnumerable opens the stream every call.
In the documentation(link) under "Deferred Reading" they say i can access the ienumerable "_dataTable" with a foreach loop (this does work fine), but this is in my case no option because i want access to specific items in the csv.
Are there possibilities to keep the filestream open so that the performace increases?
EDIT (My code, maybe a lot of nosense, im not so experienced with .net, c# and oop):
public void Compare(int key1, int key2, int col1, int col2)
{
string lastKeyCol1 = null;
string lastKeyCol2 = null;
List<string> sortedKeyColFile1 = new List<string>();
List<string> sortedKeyColFile2 = new List<string>();
int file1counter = 0;
int file2counter = 0;
int cnt = 0;
sortedKeyColFile1 = _file1.GetCol(key1);
sortedKeyColFile1.Sort();
sortedKeyColFile2 = _file2.GetCol(key2);
sortedKeyColFile2.Sort();
while ((file1counter < sortedKeyColFile1.Count) || (file2counter < sortedKeyColFile2.Count))
{
_outputList.Add(new OutputValues(key1, key2, col1, col2));
//Keys are in both files
if (sortedKeyColFile1[file1counter] == sortedKeyColFile2[file2counter])
{
if (lastKeyCol1 == sortedKeyColFile1[file1counter])
{
//Keys are redundant
_outputList[cnt].RedundantKeyF1 = true;
}
if (lastKeyCol2 == sortedKeyColFile2[file2counter])
{
//Keys are redundant
_outputList[cnt].RedundantKeyF2 = true;
}
lastKeyCol1 = sortedKeyColFile1[file1counter];
lastKeyCol2 = sortedKeyColFile2[file2counter];
_outputList[cnt].ValF1 = _file1.GetItem(file1counter, col1);
_outputList[cnt].ValF2 = _file2.GetItem(file2counter, col2);
_outputList[cnt].LineNumF1 = file1counter;
_outputList[cnt].LineNumF2 = file2counter;
//compare the values (because keys do match at this place)
_outputList[cnt].CompareResult = CompareString(_file1.GetItem(file1counter, col1), _file2.GetItem(file2counter, col2));
if (file1counter < sortedKeyColFile1.Count)
{
file1counter++;
}
if (file2counter < sortedKeyColFile2.Count)
{
file2counter++;
}
}
//Key sortedKeyColFile2[file2counter] is not in file 1
else if (file2counter < sortedKeyColFile2.Count && 0 < (string.Compare(sortedKeyColFile1[file1counter], sortedKeyColFile2[file2counter])))
{
_outputList[cnt].LineNumF2 = file2counter;
if (lastKeyCol2 == sortedKeyColFile2[file2counter])
{
//Keys are redundant
_outputList[cnt].RedundantKeyF2 = true;
}
lastKeyCol2 = sortedKeyColFile2[file2counter];
file2counter++;
}
//Key sortedKeyColFile1[file1counter] is not in file 2
else if (file1counter < sortedKeyColFile1.Count)
{
_outputList[cnt].LineNumF1 = file1counter;
if (lastKeyCol1 == sortedKeyColFile1[file1counter])
{
//Keys are redundant
_outputList[cnt].RedundantKeyF1 = true;
}
lastKeyCol1 = sortedKeyColFile1[file1counter];
file1counter++;
}
cnt++;
}
}
//And here the important part of the csv-file class, maybe not so interesting
public class CsvFile
{
private string _filePath = null;
private char _separator = ',';
private bool _hasHeader = true;
private CsvContext _cc = null;
private CsvFileDescription _inputFileDescription = null;
private List<string> _headers = null;
private IEnumerable<DataRow> _dataTable = null;
/// <summary>
/// Constructor for a new CsvFile object.
/// The Constructor initiates the Object and read the values out of the File
/// </summary>
/// <param name="filePath">Full path of the csv-file</param>
/// <param name="separator">Seperator of the csv-file, eg: ';' or ',' or '\t'</param>
/// <param name="hasHeader">Is true if the first col of the csv-file contains a headers</param>
public CsvFile(string filePath, char separator, bool hasHeader = true)
{
//Throws an exception if something is wrong with the file
File.OpenRead(filePath);
_filePath = filePath;
_separator = separator;
_hasHeader = hasHeader;
_cc = new CsvContext();
_inputFileDescription = new CsvFileDescription
{
SeparatorChar = separator,
FirstLineHasColumnNames = hasHeader
};
_dataTable = _cc.Read<DataRow>(_filePath, _inputFileDescription);
if (hasHeader)
{
ParseHeaders();
}
}
public List<string> GetCol(int col)
{
List<string> column = new List<string>();
int cnt = 0;
foreach(DataRow x in _dataTable)
{
column.Add(x[col].Value);
cnt++;
}
return column;
}
private void ParseHeaders()
{
System.IO.StreamReader file = new System.IO.StreamReader(_filePath);
if (!file.EndOfStream)
{
//_headers = file.ReadLine().Split(_separator);
_headers = new List<string> (file.ReadLine().Split(_separator));
}
file.Close();
}
}
Try this:
public class CsvFile
{
private IEnumerable<DataRow> rows = cc.Read<DataRow>(_filePath, _inputFileDescription);
//...
public IEnumerable<DataRow> Rows { get { return rows; } }
}
And then:
CsvFile file1 = new CsvFile("C:\\dev_csvcompare\\Master.csv", ';', true);
foreach(DataRow row in file1.Rows)
{
string dummy = row[1];
}

Categories