How to insert database what read four values in txt file? - c#

I'm using c# MVC project.
I have a customer class and customer table.I have a Insert function with four parameter name , surname ,phone,address.I want to read .txt file line by line and split with "," and use this Insert function but I don't know how can create algorithm.
static void AddCustomer(string Name, string Surname, string Phone, string Address)
{
using (var session = NHibernateHelper.OpenSession())
{
using (var transaction = session.BeginTransaction())
{
var customer = new Customer
{
Name = Name,
Surname = Surname,
Phone = Phone,
Address = Address,
};
session.Save(customer);
transaction.Commit();
}
}
}
while ((line = file.ReadLine()) != null)
{
string text = file.ReadToEnd();
string[] lines = text.Split(',');
for (int i = 0; i < lines.Length; i++)
{
//HOW CAN I USER ADDCUSTOMER()
}
counter++;
}

You've almost got it. Assuming file is a StreamReader, you can just split the current line on comma, and pass the separate parts to the AddCustomer method:
while ((line = file.ReadLine()) != null)
{
// Split the line on comma
var lineParts = line.Split(',');
string name = lineParts[0];
string surname = lineParts[1];
string phone = lineParts[2];
string address = lineParts[3];
AddCustomer(name, surname, phone, address);
}
Please note that this does no error checking at all (lineParts[1] will blow up if there's no comma in the given line) and that this is a bad way to parse CSV (if the data contains comma's, which addresses tend to do, it'll not work properly). Use a CSV parsing library.
See Parsing CSV files in C#, with header and plenty of other questions about CSV, where it is suggested that you use the FileHelpers library. Your class that maps to and from the CSV file will look like this:
[DelimitedRecord(",")]
[IgnoreEmptyLines()]
public class MyProduct
{
[FieldOrder(0)]
public string Name { get; set; }
[FieldOrder(1)]
public string Surname { get; set; }
[FieldOrder(2)]
public string Phone { get; set; }
[FieldOrder(3)]
public string Address { get; set; }
}
And the code to read the file:
var engine = new FileHelperEngine<CustomerCsvRecord>();
CustomerCsvRecord[] customers = engine.ReadFile(fileName);
foreach (var customer in customers)
{
AddCustomer(customer.Name, customer.Surname, customer.Phone, customer.Address);
}

This will do your job.
string fileContent = System.IO.File.ReadAllText("YOUR_FILE_PATH");
//assumeing each customer record will be on separate line
string[] lines = fileContent.Split(new string [] {Environment.NewLine}, StringSplitOptions.RemoveEmptyEntries);
foreach (string line in lines)
{
//assuming a single line content will be like this "name,surname,phone,address"
string[] items = line.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries);
Customer cust = new Customer();
cust.Name = items[0];
cust.Surname = items[1];
cust.Phone = items[2];
cust.Address = items[3];
//now use this 'cust' object
}

Related

C# How to implement CSV file into this code

Hi I am fairly new to coding, I have a piece of code that searches for a string and replaces it with another string like so:
var replacements = new[]{
new{Find="123",Replace="Word one"},
new{Find="ABC",Replace="Word two"},
new{Find="999",Replace="Word two"},
};
var myLongString = "123 is a long 999 string yeah";
foreach(var set in replacements)
{
myLongString = myLongString.Replace(set.Find, set.Replace);
}
If I want to use a CSV file that contains a lot of words and their replacements, for example, LOL,Laugh Out Loud, and ROFL, Roll Around Floor Laughing. How would I implement that?
Create a text file that looks like (you could use commas, but I like pipes (|)):
123|Word One
ABC|Word Two
999|Word Three
LOL|Laugh Out Loud
ROFL|Roll Around Floor Laughing
Then create a tiny helper class:
public class WordReplace
{
public string Find { get; set; }
public string Replace { get; set; }
}
And finally, call this code:
private static string DoWordReplace()
{
//first read in the data
var fileData = File.ReadAllLines("WordReplace.txt");
var wordReplacePairs = new List<WordReplace>();
var lineNo = 1;
foreach (var item in fileData)
{
var pair = item.Split(new[] {'|'}, StringSplitOptions.RemoveEmptyEntries);
if (pair.Length != 2)
{
throw new ApplicationException($"Malformed file, line {lineNo}, data = [{item}] ");
}
wordReplacePairs.Add(new WordReplace{Find = pair[0], Replace = pair[1]});
++lineNo;
}
var longString = "LOL, 123 is a long 999 string yeah, ROFL";
//now do the replacements
var buffer = new StringBuilder(longString);
foreach (var pair in wordReplacePairs)
{
buffer.Replace(pair.Find, pair.Replace);
}
return buffer.ToString();
}
The result is:
Laugh Out Loud, Word One is a long Word Three string yeah, Roll Around Floor Laughing

Create a list of objects with initialized properties from a string with infos

I have a string that looks like that:
random text 12234
another random text
User infos:
User name : John
ID : 221223
Date : 23.02.2018
Job: job1
User name : Andrew
ID : 378292
Date : 12.08.2017
Job: job2
User name : Chris
ID : 930712
Date : 05.11.2016
Job : job3
some random text
And this class:
class User
{
public string UserName { get; set; }
public string ID { get; set; }
public string Date { get; set; }
public string Job { get; set; }
public User(string _UserName, string _ID, string _Date, string _Job)
{
UserName = _UserName
ID = _ID;
Date = _Date;
Job = _Job;
}
}
And I want to create a List of Users with informations from that string.
I have tried doing that:
List<User> Users = new List<User>();
string Data = (the data above)
string[] lines = Data.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
List<string> UserNames = new List<string>();
List<string> IDs = new List<string>();
List<string> Dates = new List<string>();
List<string> Jobs = new List<string>();
foreach (var line in lines)
{
if (line.StartsWith("User name : "))
{
UserNames.Add(Line.Remove(0, 12));
}
if (Line.StartsWith("ID : "))
{
IDs.Add(Line.Remove(0, 5));
}
if (Line.StartsWith("Date : "))
{
Dates.Add(Line.Remove(0, 7));
}
if (Line.StartsWith("Job : "))
{
Jobs.Add(Line.Remove(0, 6));
}
}
var AllData = UserNames.Zip(IDs, (u, i) => new { UserName = u, ID = i });
foreach (var data in AllData)
{
Users.Add(new User(data.UserName, data.ID, "date", "job"));
}
But I can only combine two lists using this code. Also, I have more than 4 values for each user (the string above was just a short example) .
Is there a better method? Thanks.
Since it seems to be always 4 lines of information you could go in steps of 4 with a loop through the splitted array lines. At each step you would split by colon : and collect the last item, which is the desired value:
EDIT: In this case I would suggets to look for the START of the data.
int startIndex = Data.IndexOf("User name");
EDIT 2:
also ends with another line of text
then you can use LastIndexOf to find the end of the important information:
int endIndex = Data.LastIndexOf("Job");
int lengthOfLastLine = Data.Substring(endIndex).IndexOf(Environment.NewLine);
endIndex += lengthOfLastLine;
and then simply take a SubString from the startindex on until the end
string [] lines = Data.Substring(startIndex, endIndex - startIndex)
.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
List<User> allUsers = new List<UserQuery.User>();
for (int i = 0; i < lines.Length; i += 4)
{
string name = lines[i].Split(':').Last().Trim();
string ID = lines[i + 1].Split(':').Last().Trim();
string Date = lines[i + 2].Split(':').Last().Trim();
string Job = lines[i + 3].Split(':').Last().Trim();
allUsers.Add(new User(name, ID, Date, Job));
}
Ahhh, and you should Trim the spaces away.
This solution should be readable. The hard coded step size of 4 is actually annoying in my solution
Disclaimer: This solution works only as long as the format does not change. If the order of the lines should change, it will return false results
Instead of checking each line to add each of them to a a list, you can create your list of User directly. There you go:
Split by double new line
Split by new line
Build each User
Code:
var users = data.Split(new[] {"\n\n" }, StringSplitOptions.None).Select(lines =>
{
var line = lines.Split(new[] { "\n" }, StringSplitOptions.None);
return new User(line[0].Substring(11), line[1].Substring(4), line[2].Substring(6), line[3].Substring(5));
});
Try it online!
As #Mong Zhu answer, remove everything before and after. A this point, this is another question I wont try to solve. Remove the noise before and after then parse your data.
For a robust, flexible and self-documenting solution that will allow you to easily add new fields, ignore all the extraneous text and also cater for variations in your file format (this seems to be the case with, for example, no space in "ID:" only in the 3rd record), I would use a Regex and some LINQ to return a collection of records as follows:
using System.Text.RegularExpressions;
public class Record
{
public string Name { get; set; }
public string ID { get; set; }
public string Date { get; set; }
public string Job { get; set; }
}
public List<Record> Test()
{
string s = #"User name : John
ID : 221223
Date : 23.02.2018
Job: job1
User name : Andrew
ID : 378292
Date : 12.08.2017
Job: job2
User name : Chris
ID: 930712
Date : 05.11.2016
Job: job3
";
Regex r = new Regex(#"User\sname\s:\s(?<name>\w+).*?ID\s:\s(?<id>\w+).*?Date\s:\s(?<date>[0-9.]+).*?Job:\s(?<job>\w\w+)",RegexOptions.Singleline);
r.Matches(s);
return (from Match m in r.Matches(s)
select new Record
{
Name = m.Groups["name"].Value,
ID = m.Groups["id"].Value,
Date = m.Groups["date"].Value,
Job = m.Groups["job"].Value
}).ToList();
}
The CSV format seems to be what you're looking for (since you want to add some header to this file the actual CSV stars on 6th line):
random text 12234
another random text
User infos:
UserName;ID;Date;Job
John;221223;23.02.2018;job1
Andrew;378292;12.08.2017;job2
Chris;930712;05.11.2016;job3
And then you could read this file and parse it:
var lines = File.ReadAllLines("pathToFile");
var dataStartIndex = lines.IndexOf("UserName;ID;Date;Job");
var Users = lines.Skip(dataStartIndex + 1).Select(s =>
{
var splittedStr = s.Split(';');
return new User(splittedStr[0], splittedStr[1], splittedStr[2], splittedStr[3]);
}).ToList();
If you're working with console entry just skip the header part and let user enter comma separated values for each user on a different string. Parse it in a same way:
var splittedStr = ReadLine().Split(';');
var userToAdd = new User(splittedStr[0], splittedStr[1], splittedStr[2] , splittedStr[3]);
Users.Add(userToAdd);

How to split string containing multiple delimeters of each and every line of text file?

This is the Input my file contains:
50|Hallogen|Mercury|M:4;C:40;A:1
90|Oxygen|Mars|M:10;C:20;A:00
5|Hydrogen|Saturn|M:33;C:00;A:3
Now i want to split each and every line of my text file and store in my class file like :
Expected output:
Planets[0]:
{
Number:50
name: Hallogen
object:Mercury
proportion[0]:
{
Number:4
},
proportion[1]:
{
Number:40
},
proportion[2]:
{
Number:1
}
}
etc........
My class file to store all this values:
public class Planets
{
public int Number { get; set; } //This field points to first cell of every row.output 50,90,5
public string name { get; set; } //This field points to Second cell of every row.output Hallogen,Oxygen,Hydrogen
public string object { get; set; } ////This field points to third cell of every row.output Mercury,Mars,Saturn
public List<proportion> proportion { get; set; } //This will store all proportions with respect to planet object.
//for Hallogen it will store 4,40,1.Just store number.ignore M,C,A initials.
//for oxygen it will store 10,20,00.Just store number.ignore M,C,A initials.
}
public class proportion
{
public int Number { get; set; }
}
This is what i have done:
List<Planets> Planets = new List<Planets>();
using (StreamReader sr = new StreamReader(args[0]))
{
String line;
while ((line = sr.ReadLine()) != null)
{
string[] parts = Regex.Split(line, #"(?<=[|;-])");
foreach (var item in parts)
{
var Obj = new Planets();//Not getting how to store it but not getting proper output in parts
}
Console.WriteLine(line);
}
}
Without you having to change any of your logic in "Planets"-class my fast solution to your problem would look like this:
List<Planets> Planets = new List<Planets>();
using (StreamReader sr = new StreamReader(args[0]))
{
String line;
while ((line = sr.ReadLine()) != null)
{
Planets planet = new Planets();
String[] parts = line.Split('|');
planet.Number = Convert.ToInt32(parts[0]);
planet.name = parts[1];
planet.obj = parts[2];
String[] smallerParts = parts[3].Split(';');
planet.proportion = new List<proportion>();
foreach (var item in smallerParts)
{
proportion prop = new proportion();
prop.Number =
Convert.ToInt32(item.Split(':')[1]);
planet.proportion.Add(prop);
}
Planets.Add(planet);
}
}
Oh before i forget it, you should not name your property of class Planets "object" because "object" is a keyword for the base class of everything, use something like "obj", "myObject" ,"planetObject" just not "object" your compiler will tell you the same ;)
To my understanding, multiple delimiters are maintained to have a nested structure.
You need to split the whole string first based on pipe, followed by semi colon and lastly by colon.
The order of splitting here is important. I don't think you can have all the tokens at once by splitting with all 3 delimiters.
Try following code for same kind of data
var values = new List<string>
{
"50|Hallogen|Mercury|M:4;C:40;A:1",
"90|Oxygen|Mars|M:10;C:20;A:00",
"5|Hydrogen|Saturn|M:33;C:00;A:3"
};
foreach (var value in values)
{
var pipeSplitted = value.Split('|');
var firstNumber = pipeSplitted[0];
var name = pipeSplitted[1];
var objectName = pipeSplitted[2];
var semiSpltted = value.Split(';');
var secondNumber = semiSpltted[0].Split(':')[1];
var thirdNumber = semiSpltted[1].Split(':')[1];
var colenSplitted = value.Split(':');
var lastNumber = colenSplitted[colenSplitted.Length - 1];
}
The most straigtforward solution is to use a regex where every (sub)field is matched inside a group
var subjectString = #"50|Hallogen|Mercury|M:4;C:40;A:1
90|Oxygen|Mars|M:10;C:20;A:00
5|Hydrogen|Saturn|M:33;C:00;A:3";
Regex regexObj = new Regex(#"^(.*?)\|(.*?)\|(.*?)\|M:(.*?);C:(.*?);A:(.*?)$", RegexOptions.Multiline);
Match match = regexObj.Match(subjectString);
while (match.Success) {
match.Groups[1].Value.Dump();
match.Groups[2].Value.Dump();
match.Groups[3].Value.Dump();
match.Groups[4].Value.Dump();
match.Groups[5].Value.Dump();
match.Groups[6].Value.Dump();
match = match.NextMatch();
}
If I understand correctly, your input is well formed. In this case you could use something like this:
string[] parts = Regex.Split(line, #"[|;-]");
var planet = new Planets(parts);
...
public Planets(string[] parts) {
int.TryParse(parts[0], this.Number);
this.name = parts[1];
this.object = parts[2];
this.proportion = new List<proportion>();
Regex PropRegex = new Regex("\d+");
for(int i = 3; i < parts.Length; i++){
Match PropMatch = PropRegex.Match(part[i]);
if(PropMatch.IsMatch){
this.proportion.Add(int.Parse(PropMatch.Value));
}
}
}

C# Parse CSV to JSON Wrong Format

Take a look and let me know what the hell i'm derping on ;)
[HttpPost]
public ActionResult Upload(HttpPostedFileBase File)
{
HttpPostedFileBase csvFile = Request.Files["adGroupCSV"];
byte[] buffer = new byte[csvFile.ContentLength];
csvFile.InputStream.Read(buffer, 0, csvFile.ContentLength);
string csvString = System.Text.Encoding.UTF8.GetString(buffer);
string[] lines = Regex.Split(csvString, "\r");
List<string[]> csv = new List<string[]>();
foreach (string line in lines)
{
csv.Add(line.Split(','));
}
string json = new System.Web.Script.Serialization.JavaScriptSerializer().Serialize(csv);
ViewData["CSV"] = json;
return View(ViewData);
}
This is how it is coming across:
json = "[[\"Col1\",\"Col2\",\"Col3\",\"Col4\",\"Col5\",\"Col6\"],[\"test\",\"test\",\"test\",\"test\",\"http://www.test.com/\",\"test/\"],[\"test\",\"test\",\"test\",\"test\",\"http://www.test.com...
This is how I want it:
{"Col1":"test","Col2":"test","Col3":"test","Col4":"test","Col5":"http://www.test.com/","Col6":"test/"}
Here is an example of the CSV
Col1,Col2,Col3,Col4,Col5,Col6
Test1,Test1,Test1,test1,test.test,test/
Test2,Test2,Test2,test2,test.test,test/
Test3,Test3,Test3,test3,test.test,test/
Test4,Test4,Test4,test4,test.test,test/
You need a dictionary. Just replace
List<string[]> csv = new List<string[]>();
foreach (string line in lines)
{
csv.Add(line.Split(','));
}
with
var csv = lines.Select(l => l.Split(',')
.Select((s,i)=>new {s,i})
.ToDictionary(x=>"Col" + (x.i+1), x=>x.s));
It should work...
EDIT
var lines = csvString.Split(new char[] { '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries);
var cols = lines[0].Split(',');
var csv = lines.Skip(1)
.Select(l => l.Split(',')
.Select((s, i) => new {s,i})
.ToDictionary(x=>cols[x.i],x=>x.s));
var json = new JavaScriptSerializer().Serialize(csv);
It looks like you have a an array of string arrays when you just want one object with all your columns as properties on it.
Instead of building up your
List<string[]> csv = new List<string[]>();
Can you make a new object from your JSON, like this:
public class UploadedFileObject
{
public string Col1 { get; set; }
public string Col2 { get; set; }
public string Col3 { get; set; }
public string Col4 { get; set; }
public string Col5 { get; set; }
public string Col6 { get; set; }
}
[HttpPost] public ActionResult Upload(HttpPostedFileBase File)
{
HttpPostedFileBase csvFile = Request.Files["adGroupCSV"];
byte[] buffer = new byte[csvFile.ContentLength];
csvFile.InputStream.Read(buffer, 0, csvFile.ContentLength);
string csvString = System.Text.Encoding.UTF8.GetString(buffer);
string[] lines = Regex.Split(csvString, "\r");
List<UploadedFileObject> returnObject = new List<UploadedFileObject>();
foreach (string line in lines)
{
String[] lineParts = line.Split(',');
UploadedFileObject lineObject = new UploadedFileObject();
lineObject.Col1 = lineParts[0];
lineObject.Col2 = lineParts[1];
lineObject.Col3 = lineParts[2];
lineObject.Col4 = lineParts[3];
lineObject.Col5 = lineParts[4];
lineObject.Col6 = lineParts[5];
returnObject.add(lineObject);
}
string json = new System.Web.Script.Serialization.JavaScriptSerializer().Serialize(returnObject);
ViewData["CSV"] = json;
return View(ViewData);
}
In line with the previous answer, perhaps you could use ServiceStack to deserialize the CSV into an array of objects, then re-serialize it using ServiceStack's JSON serializer?
http://www.servicestack.net/docs/text-serializers/json-csv-jsv-serializers
You need to ensure you are using the format that the JavaScriptSerializer expects you to.
Since you are giving it a List<string[]> it is formatting it as:
"[[list1Item1,list1Item2...],[list2Item1,list2Item2...]]"
Which would correlate in your file as row1 -> list1 etc.
However what you want is the first item from the first list, lining up with the first item in the second list and so on.
I don't know about the exact workings of JavaScriptSerializer, but you could try giving it a Dictionary instead of a List<string[]>, assuming you only had one line of data (two lines total).
This would involve caching the first two lines and doing the following:
for (int i = 0; i < first.Length; i++)
{
dict.Add(first[i],second[i]);
}

What is the way to org data read from a file in c#?

There are some cool classes and tricks and short cuts in C#. I know this but I have not worked with C# enough to have them memoried.
One cool trick is this. If you read from a file data that is arranged in a similar line-by-line structure where each line is arranged in columns spaced out by tabs, the data can be read into a kind of class in C# and then you can parse out one column of data by simply doing a "for each" command. Does anyone know off-hand how this is done?
Basically, what I am talking about is this. I understand how to read a file line by line:
int counter = 0;
string line;
System.IO.StreamReader file =
new System.IO.StreamReader(filename);
while ((line = file.ReadLine()) != null)
{
Console.WriteLine(line);
counter++;
}
file.Close();
Now, how would I go about replacing Console.WriteLine(line); with code that will organize the data automatically into members of a class provided that the line columns in the input file are seperated by /t (tabs)?
You can call line.Split('\t') This will give you string[] array. You can then parse each element to proper data type.
MyData LineToMyData(string line)
{
try
{
string[] arr = line.Split('\t');
return new MyData()
{
Time = DateTime.Parse(arr[0]),
Name = arr[1],
Age = Int32.Parse(arr[2])
};
}
catch (Exception ex)
{
throw new ArgumentException("line", ex);
}
}
Well, I think you need a class:
public class Stuff
{
public string field1 {get; set;}
public string field2 {get; set;}
public string fieldn {get; set;}
public Stuff()
{
field1 = "";
field2 = "";
fieldn = "";
}
}
Then create a list of your new class before the While-->read. Inside the while-->read, create your class, and fill it with the data using split as mentioned above.
List<Stuff> lotsaStuff = new List<Stuff>();
while ((line = file.ReadLine()) != null)
{
string[] fields = line.Split('\t');
Stuff newStuff = new Stuff();
newStuff.field1 = fields[0].ToString();
newStuff.field2 = fields[1].ToString();;
newStuff.fieldn = fields[2].ToString();;
lotsaStuff.Add(newStuff);
}
After the file close, you can use your list:
foreach (Stuff mystuff in lotsaStuff)
{
if (mystuff.field2 == "useME")
{
//do something here...
}
}
You will want to match the data types (I used all strings for simplicity) to your data, both in the class, and when you are filling the class from the line read.

Categories

Resources