I am using the below function to import a csv file into a datatable object csvData, however i face an oject reference issue that i'd like to understand more while using Regex.Replace to remove quote marks from the data:
private static DataTable Gettabledata(string cpath)
{
DataTable csvData = new DataTable();
try
{
using (TextFieldParser csvReader = new TextFieldParser(cpath))
{
csvReader.SetDelimiters(new string[] { "," });
csvReader.HasFieldsEnclosedInQuotes = true;
string[] colFields = csvReader.ReadFields();
foreach (string column in colFields)
{
DataColumn datecolumn = new DataColumn(column);
datecolumn.AllowDBNull = true;
csvData.Columns.Add(datecolumn);
}
while (!csvReader.EndOfData)
{
string[] fieldData = csvReader.ReadFields();
string pattern="\""; % remove quotation mark "
string replacement=""; % replace by empty.(eg "a", a)
Regex rgx = new Regex(pattern);
for (int i = 0; i < fieldData.Length; i++)
fieldData[i] = Regex.Replace(fieldData[i],pattern, replacement); %object reference issue
{
if (fieldData[i] == "")
{
fieldData[i] = null;
}
}
csvData.Rows.Add(fieldData);
}
}
}
catch (Exception ex)
{
}
return csvData;
}
The fieldData[i] = Regex.Replace(fieldData[i],pattern, replacement); is outside the {...} block. It should be inside it.
for (int i = 0; i < fieldData.Length; i++)
{
if (fieldData[i] == "")
{
fieldData[i] = null;
}
else
{
fieldData[i] = Regex.Replace(fieldData[i],pattern, replacement);
}
}
Related
I have a txt file:
LoginId; No_Intervenant
EF2KBT0; 1003820030
ENHD0KE; 1003820129
E9PM7EP; 1003820153
EFT10OO; 1003820218
I need to create another txt file, that contains an sql UPDATE script from this information like:
UPDATE Contact
Set
Contact.No_Intervenant = '1003820030'
where
ISNULL (Contact.LoginId, '') = 'ER7OZXZ';
I only got this result using a Stringbuilder method, but performing hardcode. What I would like is for the header to be added automatically.
public Form1()
{
InitializeComponent();
}
private static void AddSqlCommand(StringBuilder sql, string[] columns, string[] types, string[] values)
{
sql.AppendLine("UPDATE Contact");
sql.AppendLine("SET");
//skip LoginId columns
for (int i = 1; i < columns.Length; i++)
{
switch (types[i].Trim())
{
case "int":
sql.Append($" Contact.{columns[i].Trim()} = {values[i]}");
//sql.Append($" Contact.{columns[0].TrimStart() } = {values[i]}");
break;
default:
sql.Append($" Contact.No_Intervenant = '{values[i]}'");
break;
}
if (columns.Length > 1 && i != columns.Length - 1)
{
sql.Append(",");
}
sql.AppendLine();
}
sql.AppendLine("WHERE");
sql.AppendLine($" ISNULL(Contact.LoginId, '') = '{values[0]}';");
sql.AppendLine();
}
private static StringBuilder GenerateSqlScript(string[] fileContent)
{
var sqlCommand = new StringBuilder();
string[] types = fileContent[0].Split(';');
string[] columns = fileContent[1].Split(';');
//skip the first line (header)
for (int i = 2; i < fileContent.Length; i++)
{
string[] values = fileContent[i].Split(';');
if (values.Length >= 1)
{
AddSqlCommand(sqlCommand, columns, types, values);
}
}
return sqlCommand;
}
How could I get and Add the header automaticaly? Because I'll probably have to do this for longer files, with more columns and more Update lines for other files, and I would not like to hardcode all the headers of the files, like the example I'll have to do next:
Header:
No_Intervenant;First_Name;Last_Name;Role_SE;EMail;Phone;Extension;Statut;Address_1;Address_2;Zip;CPF;Inscription_Particulier;DHM_Stat_Part;Date_via_ClicSeQur;Last_Update;
Data:
1003820030;NOEL;SANTOS;Particulier;;;;Actif;1528 STREET;VAL-D''OR CA;AAA 5T9;123456789;Actif;;2016-07-19 09:49:43;2019-02-08 14:24:19;
I believe you only need a couple of simple changes to your string interpolation, see below. If you have a update that affects multiple tables you should append your table name to the column in the array.
Here is how I tested, according to your logic the first row of the file should contain your data types (the example you posted doesn't). So either your logic is wrong or the data sample is wrong. It works with the test code.
private void button4_Click(object sender, EventArgs e)
{
var line = new List<string>();
line.Add("string;string");
line.Add("LoginId; No_Intervenant");
line.Add("EF2KBT0; 1003820030");
line.Add("ENHD0KE; 1003820129");
line.Add("E9PM7EP; 1003820153");
line.Add("EFT10OO; 1003820218");
var fileContent = line.ToArray();
var sqlCommand = new StringBuilder();
string[] types = fileContent[0].Split(';');
string[] columns = fileContent[1].Split(';');
//skip the first line (header)
for (int i = 2; i < fileContent.Length; i++)
{
string[] values = fileContent[i].Split(';');
if (values.Length >= 1)
{
AddSqlCommand(sqlCommand, columns, types, values, "client");
}
}
}
Edited Fuction:
private static void AddSqlCommand(StringBuilder sql, string[] columns, string[] types, string[] values, string table)
{
sql.AppendLine($"UPDATE {table}");
sql.AppendLine("SET");
//skip LoginId columns
for (int i = 1; i < columns.Length; i++)
{
switch (types[i].Trim())
{
case "int":
sql.Append($" {columns[i].Trim()} = {values[i]}");
break;
default:
sql.Append($" {columns[i].Trim()} = '{values[i]}'");
break;
}
if (columns.Length > 1 && i != columns.Length - 1)
{
sql.Append(",");
}
sql.AppendLine();
}
sql.AppendLine("WHERE");
sql.AppendLine($" ISNULL({columns[0].Trim()}, '') = '{values[0]}';");
sql.AppendLine();
}
}
I believe in this case the 'MERGE' will be a perfect solution.
It could be something like:
-- HEADER --
MERGE [your table] as trg
USING (VALUES
-- DATA FROM THE FILE --
(id, intervenant),
(id, intervenant)
-- FOOTER
) as src(id, intervenant)
ON [your logic from the WHERE statement]
WHEN MATCHED UPDATE SET
trg.[your column] = src.[your column];
The data from the source file can be loaded into a DataTable object, with UPDATE statements then constructed from this. The header names from the file are obtained from the Columns property of the DataTable, then used to specify the columns used in the UPDATE script. In the example below, additional lines and the GO separator are added in the script for formatting. These aren't essential and can be removed if you prefer to.
using System.Linq;
using System.Data;
using System.IO;
using System.Text;
//get source file
string fullFileName = #"C:\Input Folder\SourceFile.txt";
DataTable dt = new DataTable();
StringBuilder sb = new StringBuilder();
//output .sql script
string sqlScript = #"C:\Output Folder\UpdateScript.SQL";
using (StreamReader sr = new StreamReader(fullFileName))
{
string firstLine = sr.ReadLine();
string[] headers = firstLine.Split(';');
//define columns for data table
foreach (string h in headers)
{
dt.Columns.Add(h);
}
int columnCount = dt.Columns.Count;
string line = sr.ReadLine();
while (line != null)
{
string[] fields = line.Split(';');
int currentLength = fields.Count();
if (currentLength < columnCount)
{
while (currentLength < columnCount)
{
line += sr.ReadLine();
currentLength = line.Split(';').Count();
}
fields = line.Split(';');
}
//load data table
dt.Rows.Add(fields);
line = sr.ReadLine();
}
foreach (DataRow dr in dt.Rows)
{
sb.AppendLine("UPDATE Contact SET " + dt.Columns[1] + " = '" + dr[1] +
"' WHERE ISNULL(" + dt.Columns[0] + ", '') = '" + dr[0] + "'");
//extra lines and GO batch separator added between UPDATE statements for formating
sb.AppendLine(Environment.NewLine);
sb.AppendLine("GO");
sb.AppendLine(Environment.NewLine);
}
//output UPDATE commands as .sql script file
File.WriteAllText(sqlScript, sb.ToString());
}
Just to post an update of the code that I updated and that at the moment works perfectly. Thank you all for the answers and for helping me.
using System;
using System.IO;
using System.Text;
using System.Windows.Forms;
namespace GenererScriptSQL
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
}
private static void AddSqlCommand(StringBuilder sql, string[] columns, string[] types, string[] values)
{
sql.AppendLine("UPDATE Contact");
sql.AppendLine("SET");
//skip LoginId columns
for (int i = 1; i < columns.Length; i++)
{
switch (types[i].Trim())
{
case "int":
sql.Append($" Contact.{columns[i].Trim()} = {values[i]}");
break;
default:
sql.Append($" Contact.{columns[i].Trim()} = '{values[i]}'");
break;
}
if (columns.Length > 1 && i != columns.Length - 1)
{
sql.Append(",");
}
sql.AppendLine();
}
sql.AppendLine();
sql.AppendLine("WHERE");
sql.AppendLine();
sql.AppendLine($" Contact.{columns[0].Trim()} = '{values[0]}'");
sql.AppendLine();
}
private static StringBuilder GenerateSqlScript(string[] fileContent)
{
var sqlCommand = new StringBuilder();
string[] types = fileContent[0].Split(';');
string[] columns = fileContent[0].Split(';');
//skip the first line(header)
for (int i = 1; i < fileContent.Length; i++)
{
string[] values = fileContent[i].Split(';');
if (values.Length >= 1)
{
AddSqlCommand(sqlCommand, columns, types, values);
}
}
return sqlCommand;
}
private void buttonCreateSqlFile_Click(object sender, EventArgs e)
{
try
{
if (IsFileSelected())
{
string[] fileContent = File.ReadAllLines(textBoxFile.Text);
if (fileContent != null)
{
StringBuilder sqlCommand = GenerateSqlScript(fileContent);
if (!string.IsNullOrWhiteSpace(sqlCommand.ToString()))
{
WriteSqlFile(sqlCommand);
}
}
}
else
{
MessageBox.Show("Sélectionner le fichier de chargement.");
}
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
private void buttonSelectFile_Click(object sender, EventArgs e)
{
try
{
using (var fileBrowser = new OpenFileDialog())
{
if (fileBrowser.ShowDialog() == DialogResult.OK)
{
textBoxFile.Text = fileBrowser.FileName;
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
private bool IsFileSelected()
{
return !string.IsNullOrWhiteSpace(textBoxFile.Text) && File.Exists(textBoxFile.Text);
}
private void WriteSqlFile(StringBuilder sqlCommand)
{
var fileInfo = new FileInfo(textBoxFile.Text);
string BackupDate = fileInfo.Name + "_" + DateTime.Now.ToString("yyyy-MM-dd_HH-mm") + "_Update" + ".sql";
string sqlFilePath = Path.Combine(fileInfo.Directory.FullName, BackupDate);
if (File.Exists(sqlFilePath))
{
File.Delete(sqlFilePath);
}
File.WriteAllText(sqlFilePath, sqlCommand.ToString());
MessageBox.Show($#" Le fichier sql a été générée! {sqlFilePath}");
}
}
}
My csv file contains 8 columns and 300k rows.Here is an example of my csv file
"0195153448";"Classical Mythology";"Mark P. O. Morford";"2002";"Oxford University Press";"http://images.amazon.com/images/P/0195153448.01.THUMBZZZ.jpg";"http://images.amazon.com/images/P/0195153448.01.MZZZZZZZ.jpg";"http://images.amazon.com/images/P/0195153448.01.LZZZZZZZ.jpg"
"0002005018";"Clara Callan";"Richard Bruce Wright";"2001";"HarperFlamingo Canada";"http://images.amazon.com/images/P/0002005018.01.THUMBZZZ.jpg";"http://images.amazon.com/images/P/0002005018.01.MZZZZZZZ.jpg";"http://images.amazon.com/images/P/0002005018.01.LZZZZZZZ.jpg"
Now i have this code for reading
string path = #"C:\Users\SEMRUK\Desktop\exceller\kitaplik.csv";
public DataTable GetDataTabletFromCSVFile(string PathFile)
{
DataTable csvData = new DataTable();
TextFieldParser csvReader = new TextFieldParser(PathFile);
csvReader.SetDelimiters(new string[] {";"});
csvReader.HasFieldsEnclosedInQuotes = true;
string[] colFields = csvReader.ReadFields();
foreach (string column in colFields)
{
DataColumn datecolumn = new DataColumn(column);
datecolumn.AllowDBNull = true;
csvData.Columns.Add(datecolumn);
}
string[] fieldData = csvReader.ReadFields();
while (!csvReader.EndOfData)
{
for (int i = 0; i < fieldData.Length; i++)
{
if (fieldData[i] == "")
{
fieldData[i] = null;
}
MessageBox.Show(fieldData[i]);
}
csvData.Rows.Add(fieldData);
}
return csvData;
}
This way i can read the first 8 rows.But i can't read anything after that.It just reads first 8.How can i tell the code that it should read after tab too.I tried adding \t to the setdelimiters but didn't work.Any suggestions?
static void Main(string[] args)
{
string path = "your_file_path";
string text = System.IO.File.ReadAllText(path);
string[] parsedText= text.Split(';');
foreach (var item in parsedText)
{
//do some
}
}
I'm trying to add a user to a sharepoint group based on data from a csv file. I hope that the code marked in bold might be the error.
1.User x=web.Ensureuser("domain\logonname") function--> shows the following error when tried to print any of its file like (x.Title, x.email) --> "The fiels is not assigned" error.
2.Execytequery()--> "The given key is not fount in the dictionary" error.
Please help me with this.
static void Main(string[] args)
{
DataTable dtErrors = new DataTable();
dtErrors.Columns.Add("Links");
dtErrors.Columns.Add("Message");
DataRow drOutputError = dtErrors.NewRow();
DataTable dtCsv = csvToDataTable(System.Configuration.ConfigurationSettings.AppSettings["FilePath"].ToString(), true);
string url = string.Empty;
try
{
foreach (DataRow drCSV in dtCsv.Rows)
{
try
{
url = drCSV[0].ToString();
string grpName = drCSV[1].ToString();
string users = drCSV[2].ToString();
string[] users1 = users.Split(';');
Console.WriteLine("URL picked from CSV: " + url);
using (ClientContext context = new ClientContext(url))
{
Web web = context.Web;
GroupCollection groupColl = web.SiteGroups;
context.Load(groupColl, groups => groups.Include(group => group.Title, group => group.Id));
context.ExecuteQuery();
Console.WriteLine("Groups Count: " + groupColl.Count);
foreach (Group grp in groupColl)
{
try
{
int grpId = grp.Id;
Console.WriteLine("SiteURL: " + url);
Console.WriteLine("Group Name: " + grpName);
//For test purpose
Console.WriteLine(grp.Title);
if (grpName == grp.Title)
{
Console.WriteLine("Match found");
for (int i = 1; i < users1.Length; i++)
{
string temp = users1[i].Remove(0,8);
Console.WriteLine(temp);
**User user = web.EnsureUser(temp);**
Console.WriteLine(user);
addUsersToGroup(grpId, url, user);
}
break;
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message.ToString());
drOutputError["Links"] = url;
drOutputError["Message"] = ex.Message.ToString();
dtErrors.Rows.Add(drOutputError);
drOutputError = dtErrors.NewRow();
}
}
}
}
catch (Exception ex)
{
drOutputError["Links"] = url;
drOutputError["Message"] = ex.Message.ToString();
dtErrors.Rows.Add(drOutputError);
drOutputError = dtErrors.NewRow();
}
}
}
catch (Exception ex)
{
drOutputError["Links"] = url;
drOutputError["Message"] = ex.Message.ToString();
dtErrors.Rows.Add(drOutputError);
drOutputError = dtErrors.NewRow();
}
ToCSVError(dtErrors, ",", true);
Console.WriteLine("=======================Completed==================");
Console.ReadLine();
}
public static void addUsersToGroup(int grpId, string url,User user)
{
try
{
using (ClientContext clientContext = new ClientContext(url))
{
Web web = clientContext.Web;
Group testingOwnersGroup = web.SiteGroups.GetById(grpId);
clientContext.Load(testingOwnersGroup);
clientContext.ExecuteQuery();
Console.WriteLine(testingOwnersGroup.Title);
UserCollection collUser = testingOwnersGroup.Users;
collUser.AddUser(user);
clientContext.Load(collUser);
clientContext.Load(testingOwnersGroup);
**clientContext.ExecuteQuery();**
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message.ToString());
}
}
public static DataTable csvToDataTable(string file, bool isRowOneHeader)
{
DataTable csvDataTable = new DataTable();
//no try/catch - add these in yourselfs or let exception happen
String[] csvData = System.IO.File.ReadAllLines(file);
//if no data in file ‘manually’ throw an exception
if (csvData.Length == 0)
{
// throw new Exception(CSV File Appears to be Empty”);
}
String[] headings = csvData[0].Split(',');
int index = 0; //will be zero or one depending on isRowOneHeader
if (isRowOneHeader) //if first record lists headers
{
index = 1; //so we won’t take headings as data
//for each heading
for (int i = 0; i < headings.Length; i++)
{
//replace spaces with underscores for column names
headings[i] = headings[i].Replace(" ", "_");
//add a column for each heading
csvDataTable.Columns.Add(headings[i], typeof(string));
}
}
else //if no headers just go for col1, col2 etc.
{
for (int i = 0; i < headings.Length; i++)
{
//create arbitary column names
csvDataTable.Columns.Add("col" + (i + 1).ToString(), typeof(string));
}
}
//populate the DataTable
for (int i = index; i < csvData.Length; i++)
{
//create new rows
DataRow row = csvDataTable.NewRow();
for (int j = 0; j < headings.Length; j++)
{
//fill them
row[j] = csvData[i].Split(',')[j];
}
//add rows to over DataTable
csvDataTable.Rows.Add(row);
}
//return the CSV DataTable
return csvDataTable;
}
static void ToCSVError(DataTable table, string delimiter, bool includeHeader)
{
StringBuilder result = new StringBuilder();
if (includeHeader)
{
foreach (DataColumn column in table.Columns)
{
result.Append(column.ColumnName);
result.Append(delimiter);
}
result.Remove(--result.Length, 0);
result.Append(Environment.NewLine);
}
foreach (DataRow row in table.Rows)
{
foreach (object item in row.ItemArray)
{
if (item is System.DBNull)
result.Append(delimiter);
else
{
string itemAsString = item.ToString();
// Double up all embedded double quotes
itemAsString = itemAsString.Replace("\"", "\"\"");
// To keep things simple, always delimit with double-quotes
// so we don't have to determine in which cases they're necessary
// and which cases they're not.
itemAsString = "\"" + itemAsString + "\"";
result.Append(itemAsString + delimiter);
}
}
result.Remove(--result.Length, 0);
result.Append(Environment.NewLine);
}
using (StreamWriter writer = new StreamWriter(System.Configuration.ConfigurationSettings.AppSettings["ErrorLog"].ToString(), true))
{
writer.Write(result.ToString());
}
}
}
}
I am trying to convert string to DataTable using the ffollowing method , But It did"nt work
public static DataTable convertStringToDataTable(string data)
{
DataTable dataTable = new DataTable();
bool columnsAdded = false;
foreach (string row in data.Split('\n'))
{
DataRow dataRow = dataTable.NewRow();
foreach (string cell in row.Split(','))
{
string[] keyValue = cell.Split('"');
if (!columnsAdded)
{
DataColumn dataColumn = new DataColumn(keyValue[0]);
dataTable.Columns.Add(dataColumn);
}
dataRow[keyValue[0]] = keyValue[1];
}
columnsAdded = true;
dataTable.Rows.Add(dataRow);
}
return dataTable;
}
Code that contains data string :
StringWriter sw = new StringWriter();
sw.WriteLine("\"NumClient\",\"Raisons Sociale\",\"DateDocument\",\"NumCommandeNAV\",\"Réference\",\"Designation\",\"QteCommandée\",\"QteLivrée\",\"QteAnnulée\",\"Reste à Livrer\",\"Type Disponibilite\",\"DateDisponibilite\"");
var EnTete =
db.AURES_GROS_EnTeteCommande.Where(e => e.NumCommandeNAV != " " && e.NumCommandeNAV != "_")
.OrderBy(x => x.CodeMagasin)
.ThenBy(s => s.NumClient)
.ThenBy(c => c.DateDocument)
.OrderByDescending(x => x.NumCommandeNAV)
.ToList();
foreach (var element in EnTete)
{
string statut = RecuperStatut(element.NumCommandeNAV);
if (statut == "A livrer")
{
Raison = context.Users.First(x => x.No_ == element.NumClient).RaisonSociale;
lignes = db.AURES_GROS_LigneCommande.Where(x => x.NumDocument == element.NumDocument).ToList();
foreach (var elt in lignes)
{
sw.WriteLine(string.Format("\"{0}\",\"{1}\",\"{2}\",\"{3}\",\"{4}\",\"{5}\",\"{6}\",\"{7}\",\"{8}\",\"{9}\",\"{10}\",\"{11}\"",
element.NumClient,
Raison,
element.DateDocument,
element.NumCommandeNAV,
elt.CodeArticle,
elt.Designation,
elt.Quantite,
0,
elt.QteANNULEE,
elt.Quantite,
element.Couleur,
elt.DateDisponibilite
));
}
}
}
DataTable t = convertStringToDataTable(sw.ToString());
Response.ClearContent();
Response.ClearHeaders();
Response.BufferOutput = true;
Response.ContentType = "text/excel";
Response.AddHeader("Content-Disposition", "attachment; filename=Reliquat" + DateTime.Now.ToString("yyyy_MM_dd") + ".csv");
Response.Write(t);
Response.Flush();
Response.Close();
//Response.End();
In this code I want I wnat to export data to Excel file
Any one have solutions
Thanks,
I think you want to create a DataTable from a string. So first split the "rows" and then the "columns". You are adding the DataColumns in the row-loop. You need that only once before the loop. Here is another implementation which handles this and other edge cases you haven't considered yet:
public static DataTable ConvertStringToDataTable(string data)
{
DataTable dataTable = new DataTable();
// extract all lines:
string[] lines = data.Split(new string[] { "\r\n", "\n" }, StringSplitOptions.RemoveEmptyEntries);
string header = lines.FirstOrDefault();
if (header == null)
return dataTable;
// first create the columns:
string[] columns = header.Split(','); // using commas as delimiter is brave ;)
foreach (string col in columns)
dataTable.Columns.Add(col.Trim());
foreach (string line in lines.Skip(1))
{
string[] fields = line.Split(',');
if(fields.Length != dataTable.Columns.Count)
continue; // should not happen
DataRow dataRow = dataTable.Rows.Add();
for (int i = 0; i < fields.Length; i++)
dataRow.SetField(i, fields[i]);
}
return dataTable;
}
You can convert your column foreach to a for loop.
public static DataTable convertStringToDataTable(string data)
{
DataTable dataTable = new DataTable();
bool columnsAdded = false;
foreach (string row in data.Split('\n'))
{
DataRow dataRow = dataTable.NewRow();
string[] cell = row.Split(',');
for (int i = 0; i < cell.Length; i++)
{
string[] keyValue = cell[i].Split('"');
if (!columnsAdded)
{
DataColumn dataColumn = new DataColumn();
dataTable.Columns.Add(dataColumn);
}
dataRow[i] = keyValue[1];
}
columnsAdded = true;
dataTable.Rows.Add(dataRow);
}
return dataTable;
}
However if your split string[] keyValue = cell.Split('"'); is not returning what you are expecting you may need to investigate further.
Want to create a generic text file parser in c# for any find of text file.Actually i have 4 application all 4 getting input data from txt file format but text files are not homogeneous in nature.i have tried fixedwithdelemition.
private static DataTable FixedWidthDiliminatedTxtRead()
{
string[] fields;
StringBuilder sb = new StringBuilder();
List<StringBuilder> lst = new List<StringBuilder>();
DataTable dtable = new DataTable();
ArrayList aList;
using (TextFieldParser tfp = new TextFieldParser(testOCC))
{
tfp.TextFieldType = FieldType.FixedWidth;
tfp.SetFieldWidths(new int[12] { 2,25,8,12,13,5,6,3,10,11,10,24 });
for (int col = 1; col < 13; ++col)
dtable.Columns.Add("COL" + col);
while (!tfp.EndOfData)
{
fields = tfp.ReadFields();
aList = new ArrayList();
for (int i = 0; i < fields.Length; ++i)
aList.Add(fields[i] as string);
if (dtable.Columns.Count == aList.Count)
dtable.Rows.Add(aList.ToArray());
}
}
return dtable;
}
but i feel its very rigid one and really varies application to application making it configgurable .any better way ..
tfp.SetFieldWidths(new int[12] { 2,25,8,12,13,5,6,3,10,11,10,24 });
File nature :
Its a report kind of file .
position of columns are very similar
row data of file id different .
I get this as a reference
http://www.codeproject.com/Articles/11698/A-Portable-and-Efficient-Generic-Parser-for-Flat-F
any other thoughts ?
If the only thing different is the field widths, you could just try sending the field widths in as a parameter:
private static DataTable FixedWidthDiliminatedTxtRead(int[] fieldWidthArray)
{
string[] fields;
StringBuilder sb = new StringBuilder();
List<StringBuilder> lst = new List<StringBuilder>();
DataTable dtable = new DataTable();
ArrayList aList;
using (TextFieldParser tfp = new TextFieldParser(testOCC))
{
tfp.TextFieldType = FieldType.FixedWidth;
tfp.SetFieldWidths(fieldWidthArray);
for (int col = 1; col < 13; ++col)
dtable.Columns.Add("COL" + col);
while (!tfp.EndOfData)
{
fields = tfp.ReadFields();
aList = new ArrayList();
for (int i = 0; i < fields.Length; ++i)
aList.Add(fields[i] as string);
if (dtable.Columns.Count == aList.Count)
dtable.Rows.Add(aList.ToArray());
}
}
return dtable;
}
If you will have more logic to grab the data, you might want to consider defining an interface or abstract class for a GenericTextParser and create concrete implementations for each other file.
Hey I made one of these last week.
I did not write it with the intentions of other people using it so I appologize in advance if its not documented well but I cleaned it up for you. ALSO I grabbed several segments of code from stack overflow so I am not the original author of several pieces of this.
The places you need to edit are the path and pathout and the seperators of text.
char[] delimiters = new char[]
So it searches for part of a word and then grabs the whole word. I used a c# console application for this.
Here you go:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
namespace UniqueListofStringFinder
{
class Program
{
static void Main(string[] args)
{
string path = #"c:\Your Path\in.txt";
string pathOut = #"c:\Your Path\out.txt";
string data = "!";
Console.WriteLine("Current Path In is set to: " + path);
Console.WriteLine("Current Path Out is set to: " + pathOut);
Console.WriteLine(Environment.NewLine + Environment.NewLine + "Input String to Search For:");
Console.Read();
string input = Console.ReadLine();
// Delete the file if it exists.
if (!File.Exists(path))
{
// Create the file.
using (FileStream fs = File.Create(path))
{
Byte[] info =
new UTF8Encoding(true).GetBytes("This is some text in the file.");
// Add some information to the file.
fs.Write(info, 0, info.Length);
}
}
System.IO.StreamReader file = new System.IO.StreamReader(path);
List<string> Spec = new List<string>();
using (StreamReader sr = File.OpenText(path))
{
while (!file.EndOfStream)
{
string s = file.ReadLine();
if (s.Contains(input))
{
char[] delimiters = new char[] { '\r', '\n', '\t', ')', '(', ',', '=', '"', '\'', '<', '>', '$', ' ', '#', '[', ']' };
string[] parts = s.Split(delimiters,
StringSplitOptions.RemoveEmptyEntries);
foreach (string word in parts)
{
if (word.Contains(input))
{
if( word.IndexOf(input) == 0)
{
Spec.Add(word);
}
}
}
}
}
Spec.Sort();
// Open the stream and read it back.
//while ((s = sr.ReadLine()) != null)
//{
// Console.WriteLine(s);
//}
}
Console.WriteLine();
StringBuilder builder = new StringBuilder();
foreach (string s in Spec) // Loop through all strings
{
builder.Append(s).Append(Environment.NewLine); // Append string to StringBuilder
}
string result = builder.ToString(); // Get string from StringBuilder
Program a = new Program();
data = a.uniqueness(result);
int i = a.writeFile(data,pathOut);
}
public string uniqueness(string rawData )
{
if (rawData == "")
{
return "Empty Data Set";
}
List<string> dataVar = new List<string>();
List<string> holdData = new List<string>();
bool testBool = false;
using (StringReader reader = new StringReader(rawData))
{
string line;
while ((line = reader.ReadLine()) != null)
{
foreach (string s in holdData)
{
if (line == s)
{
testBool = true;
}
}
if (testBool == false)
{
holdData.Add(line);
}
testBool = false;
// Do something with the line
}
}
int i = 0;
string dataOut = "";
foreach (string s in holdData)
{
dataOut += s + "\r\n";
i++;
}
// Write the string to a file.
return dataOut;
}
public int writeFile(string dataOut, string pathOut)
{
try
{
System.IO.StreamWriter file = new System.IO.StreamWriter(pathOut);
file.WriteLine(dataOut);
file.Close();
}
catch (Exception ex)
{
dataOut += ex.ToString();
return 1;
}
return 0;
}
}
}
private static DataTable FixedWidthTxtRead(string filename, int[] fieldWidths)
{
string[] fields;
DataTable dtable = new DataTable();
ArrayList aList;
using (TextFieldParser tfp = new TextFieldParser(filename))
{
tfp.TextFieldType = FieldType.FixedWidth;
tfp.SetFieldWidths(fieldWidths);
for (int col = 1; col <= fieldWidths.length; ++col)
dtable.Columns.Add("COL" + col);
while (!tfp.EndOfData)
{
fields = tfp.ReadFields();
aList = new ArrayList();
for (int i = 0; i < fields.Length; ++i)
aList.Add(fields[i] as string);
if (dtable.Columns.Count == aList.Count) dtable.Rows.Add(aList.ToArray());
}
}
return dtable;
}
Here's what I did:
I built a factory for the type of processor needed (based on file type/format), which abstracted the file reader.
I then built a collection object that contained a set of triggers for each field I was interested in (also contained the property name for which this field is destined). This settings collection is loaded in via an XML configuration file, so all I need to change are the settings, and the base parsing process can react to how the settings are configured. Finally I built a reflection wrapper wherein once a field is parsed, the corresponding property on the model object is set.
As the file flowed through, the triggers for each setting evaluated each lines value. When it found what it was set to find (via pattern matching, or column length values) it fired and event that bubbled up and set a property on the model object. I can show some pseudo code if you're interested. It needs some work for efficiency's sake, but I like the concept.