C# - 将文本文件第一列插入数据库

3
我希望能够从文本文件中读取数据,并将其第一列作为行插入到数据库中。
以下是文本文件的样式:
1264311 | SMS_DR | DELIVERED
 373414 | SMS_DR | EXPIRED
    418 | SMS_DR | UNDELIVERABLE
1628984 | SMS_MT | 

我想只获取第一列整数值并将其插入数据库作为一个行,以得到如下结果:
DELIVERED   EXPIRED     UNDELIVERABLE       BLABLA
1264311     373414      418                 1628984 

当我运行我的代码时,它会插入所有4行,这是我的代码:

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();

结果:

enter image description here


你知道你的文件会有多少行吗? - jle
5个回答

2

您的代码对于每一行都进行插入操作,使用第一列作为所有参数。这可能不是您想要的结果。请尝试以下方法:

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();   

1
摆脱循环,像这样做:
cmdJBM.Parameters.AddWithValue("@DELIVERED", allLines1[0].Split(new char[] { '|' })[0]);

如果您知道文件的索引和确切行数,只需将索引放入代码中即可。

1
你需要这样的东西:

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);

非常感谢 :) 这正是我需要的! - Smail

1

您有逻辑错误...在您的列数组中,是当前行的拆分。

但是为什么您创建了sr1 = new StreamReader却没有使用它呢?

File.ReadAllLines是小文件的快速版本...但是对于大文件,您可能会遇到OutOfMemoryException。

尝试这个。

类程序 { 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));
        }
    }
}

0
首先,使用StreamReader打开文件,然后使用File.ReadAllLines()读取内容是无用的(而且您没有处理StreamReader,因此文件仍在使用中)。
假设文件格式正确(并且不会使用所有进程内存),则首先读取其内容:
var allLines = File.ReadAllLines(@"C:\Users\adamoui\Desktop\Statjbm_20161009.txt");

然后去掉不需要的字段(只要两个令牌,我们不需要创建我们不使用的2X字符串):

var allValues = allLines.Select(x => x.Split(new char[] { '|' }, 2)[0]);

现在你需要将每四行分为一组。我首先会介绍一个辅助函数,你可以在其他地方重复使用它(这里没有错误检查):

static IEnumerable<int> Range(int start, int count, int step) {
    for (int i=0; i < count; i += step)
        yield return start + i;
}

现在我们可以根据需要循环遍历我们的值:

var records = Range(0, allValues.Length, 4).Select(x => {
    return new {
        Delivered = allValues[x + 0],
        Expired = allValues[x + 1],
        // ...
    };
});

我们也可以引入一些常量来简化你的代码:

const string InsertRecordCommand = "INSERT INTO dbo.StatJBM_NEW (Noeud, Total_MT, Date, DELIVERED, EXPIRED, UNDELIVERABLE) VALUES (@Noeud, @Total_MT, @Date, @DELIVERED, @EXPIRED, @UNDELIVERABLE)";

将所有内容整合在一起(还要在必要时处理可释放的对象):
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();                
    }
}

现在也许是简化您的代码的时候了。您可能想使用像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
    };
}));

这就是全部(我没有提到不要硬编码路径和使用Environment.GetFolder(),因为我猜这只是一个例子)。请参考Dapper文档以获取有关其配置和约定的更多详细信息,请注意,如果没有贡献,它也可能是这样的:

foreach (var record in records)
    con.Execute(InsertRecordCommand, record);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接