Reputation: 41
I would like to read from text file and insert his first column as row in database.
This is the text file how it looks like:
1264311 | SMS_DR | DELIVERED
373414 | SMS_DR | EXPIRED
418 | SMS_DR | UNDELIVERABLE
1628984 | SMS_MT |
I want to get only the first column with integer values and insert them in my database as a row to have this:
DELIVERED EXPIRED UNDELIVERABLE BLABLA
1264311 373414 418 1628984
When i run my code it inserts all 4 lines, this my code:
sr1 = new StreamReader("C:\\Users\\adamoui\\Desktop\\Statjbm_20161009.txt");
string[] allLines1 = File.ReadAllLines("C:\\Users\\adamoui\\Desktop\\Statjbm_20161009.txt");
for (int i = 0; i < allLines1.Length; i++)
{
string[] column = allLines1[i].Split(new char[] { '|' });
SqlCommand cmdJBM = new SqlCommand("INSERT INTO dbo.StatJBM_NEW (Noeud, Total_MT, Date, DELIVERED, EXPIRED, UNDELIVERABLE) VALUES (@Noeud, @Total_MT, @Date, @DELIVERED, @EXPIRED, @UNDELIVERABLE)", con);
cmdJBM.Parameters.AddWithValue("@Noeud", "JBM");
cmdJBM.Parameters.AddWithValue("@DELIVERED", column[0]);
cmdJBM.Parameters.AddWithValue("@EXPIRED", column[0]);
cmdJBM.Parameters.AddWithValue("@UNDELIVERABLE", column[0]);
cmdJBM.Parameters.AddWithValue("@Total_MT", column[0]);
cmdJBM.Parameters.AddWithValue("@Date", DateTime.Now.AddDays(-1));
cmdJBM.ExecuteNonQuery();
}
con.Close();
Result:
Upvotes: 3
Views: 263
Reputation: 11
U have logical mistake... In your column array are the splits of the current line.
But why you create sr1 = new StreamReader and don't use it ?
File.ReadAllLines is a quick version for small files...but for big Files you can get a OutOfMemoryException.
Try this.
class Program { static void Main(string[] args) {
//current line from the file
string line;
//filereader
using (var file = new StreamReader("C:\\Users\\adamoui\\Desktop\\Statjbm_20161009.txt"))
{
//list for the first columns
var firstColumnInFile = new List<string>();
//read every line
while ((line = file.ReadLine()) != null)
{
//split line
var items = line.Split('|');
// add the first column in the list;
firstColumnInFile.Add(items.First());
}
if(firstColumnInFile.Count < 4)
return;
SqlCommand cmdJBM = new SqlCommand(@"INSERT INTO dbo.StatJBM_NEW
(Noeud, Total_MT, Date, DELIVERED, EXPIRED,
UNDELIVERABLE) VALUES (@Noeud, @Total_MT, @Date,
@DELIVERED, @EXPIRED, @UNDELIVERABLE)", con);
cmdJBM.Parameters.AddWithValue("@Noeud", "JBM");
cmdJBM.Parameters.AddWithValue("@DELIVERED", firstColumnInFile[0]); //first column
cmdJBM.Parameters.AddWithValue("@EXPIRED", firstColumnInFile[1]); //second column
cmdJBM.Parameters.AddWithValue("@UNDELIVERABLE", firstColumnInFile[2]); //third column
cmdJBM.Parameters.AddWithValue("@Total_MT", firstColumnInFile[3]); //...
cmdJBM.Parameters.AddWithValue("@Date", DateTime.Now.AddDays(-1));
}
}
}
Upvotes: 1
Reputation: 67128
First of all opening file with StreamReader
and then read content with File.ReadAllLines()
is useless (and you keep file in use because you do not dispose StreamReader
.)
Assuming that file is well-formed (and not huge to use all process memory) then first read its content:
var allLines = File.ReadAllLines(@"C:\Users\adamoui\Desktop\Statjbm_20161009.txt");
Then strip unwanted fields (just two tokens, we don't need to create 2X strings we do not use):
var allValues = allLines.Select(x => x.Split(new char[] { '|' }, 2)[0]);
Now you need to group lines 4-by-4. I'd first introduce an helper function you may reuse elsewhere (no error checking here):
static IEnumerable<int> Range(int start, int count, int step) {
for (int i=0; i < count; i += step)
yield return start + i;
}
Now we can loop through our values as required:
var records = Range(0, allValues.Length, 4).Select(x => {
return new {
Delivered = allValues[x + 0],
Expired = allValues[x + 1],
// ...
};
});
Let's also introduce some constants to clean your code:
const string InsertRecordCommand = "INSERT INTO dbo.StatJBM_NEW (Noeud, Total_MT, Date, DELIVERED, EXPIRED, UNDELIVERABLE) VALUES (@Noeud, @Total_MT, @Date, @DELIVERED, @EXPIRED, @UNDELIVERABLE)";
To put everything together (also disposing disposable objects where required):
var allValues = File.ReadAllLines(@"C:\Users\adamoui\Desktop\Statjbm_20161009.txt")
.Select(x => x.Split(new char[] { '|' }, 2)[0])
.ToArray();
var yesterday = DateTime.Now.AddDays(-1);
var records = Range(0, allValues.Length, 4).Select(x => {
return new {
Noeud = "JBM",
Delivered = allValues[x + 0],
Expired = allValues[x + 1],
Undeliverable = allValues[x + 2],
TotalMt = allValeus[x + 3],
Date = yesterday
};
});
foreach (var record in records)
{
using (var command = new SqlCommand(InsertRecordCommand , con))
{
command.Parameters.AddWithValue("@Noeud", record.Noeud);
command.Parameters.AddWithValue("@DELIVERED", record.Delivered);
command.Parameters.AddWithValue("@EXPIRED", record.Expired);
command.Parameters.AddWithValue("@UNDELIVERABLE", record.Undeliverable);
command.Parameters.AddWithValue("@Total_MT", record.TotalMt);
command.Parameters.AddWithValue("@Date", record.Date);
command.ExecuteNonQuery();
}
}
Now maybe it's time to simplify your code. You may want to use a lightweight mapper like Dapper:
var allValues = File.ReadAllLines(@"C:\Users\adamoui\Desktop\Statjbm_20161009.txt")
.Select(x => x.Split(new char[] { '|' }, 2)[0])
.ToArray();
var yesterday = DateTime.Now.AddDays(-1);
con.Insert(Range(0, allValues.Length, 4).Select(x => {
return new {
Noeud = "JBM",
Delivered = allValues[x + 0],
Expired = allValues[x + 1],
Undeliverable = allValues[x + 2],
Total_Mt = allValeus[x + 3],
Date = yesterday
};
}));
That's all (I do not mention to do not hardcode paths and to use Environment.GetFolder()
because I guess this is just an example.) Please consult Dapper documentation for further details about its configuration and conventions, note that without contribs it may also be like this:
foreach (var record in records)
con.Execute(InsertRecordCommand, record);
Upvotes: 0
Reputation: 316
You need something of this sort:
var delivered = allLines[0].Split(new char[] { '|' })[0];
var expired = allLines[1].Split(new char[] { '|' })[0];
var undeliverable = allLines[2].Split(new char[] { '|' })[0];
....
cmdJBM.Parameters.AddWithValue("@DELIVERED", delivered);
cmdJBM.Parameters.AddWithValue("@EXPIRED", expired);
cmdJBM.Parameters.AddWithValue("@UNDELIVERABLE", undeliverable);
Upvotes: 1
Reputation: 5402
Your code makes an insert for each line, using the first column as all params. Probably not what you had in mind. Try this:
var values = allLines1.Split('|')
.Select(arr => arr[0])
.ToArray();
SqlCommand cmdJBM = new SqlCommand(@"INSERT INTO dbo.StatJBM_NEW
(Noeud, Total_MT, Date, DELIVERED, EXPIRED,
UNDELIVERABLE) VALUES (@Noeud, @Total_MT, @Date,
@DELIVERED, @EXPIRED, @UNDELIVERABLE)", con);
cmdJBM.Parameters.AddWithValue("@Noeud", "JBM");
cmdJBM.Parameters.AddWithValue("@DELIVERED", values[0]);
cmdJBM.Parameters.AddWithValue("@EXPIRED", values[1]);
cmdJBM.Parameters.AddWithValue("@UNDELIVERABLE", values[2]);
cmdJBM.Parameters.AddWithValue("@Total_MT", values[3]);
cmdJBM.Parameters.AddWithValue("@Date", DateTime.Now.AddDays(-1));
cmdJBM.ExecuteNonQuery();
Upvotes: 2
Reputation: 9489
Get rid of the loop and do something like this:
cmdJBM.Parameters.AddWithValue("@DELIVERED", allLines1[0].Split(new char[] { '|' })[0]);
If you know the indexes and exact number of rows that your file will have, you can just put the indexes right into your code.
Upvotes: 1