• 引言
    工作需要将数十万条文本数据解析存入Mysql数据库中,代码使用C#实现,存储效率还可以,以下是一些主要代码的说明。

txtdataToMysql

项目描述:解析文本文件,该文件使用爬虫爬下的数十万条数据,主要是图片以及图片关键字,图片信息使用','分隔,关键字使用 ' '(一个空格),关键字不允许重复。

  • 分析需要创建的数据库
    该数据库为多对多,所以需要三张表,一张表为image_info,一张为image_keyword,一张为关系表img_and_key_relation。在这里并没有添加外键,加入外键后插入数据难度比较大,Mysql还没有具体学习过,关于主键与外键的关系,以及外键的作用等以后补充。以下为创建数据库的代码
    1
    2
    3
    4
    5
    create database emotion;
    use emotion;
    create table image_Keyword(keyword_id int(4) not null primary key,keyword varchar(40) not null);
    create table image_info(image_id int(4) not null primary key,id_other varchar(20) not null,id_self varchar(9) not null,image_url varchar(100) not null);
    create table img_and_key_relation(relation_id int(4) not null primary key auto_increment,keyword_id int(4) not null,image_id int(4) not null);

这里并没有将image_infoimage_keyword的主键设为自动增加,为了插入img_and_key_relation表时能够获得其余两张表的键值,具体获得方法将在代码中讲解。
解析文本
代码使用c#写的所以可以使用按行读取文本,使用Split()方法将文本进行解析,对于文本解析专门设置了一个class TxtFilter,在该类中实现文本解析方法,在插入关键字时,使用Dictionary<string, int> keywordDic,将关键字存入字典中,字典的关键字为解析的关键字,使用字典因为要求键值唯一,这样在匹配关键字是可以方便,开始的时候并没有注意到Mysql数据库大小写不敏感,而c#的字典键值为大小写敏感的,所有在插入关键字是有些重复了,设置字典大小写不敏感需要如此创建字典
Dictionary<string, int> keywordDic = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);这样可以保证插入的关键字唯一。对判断关键字的唯一性使用hashset也是可以,但是不知道它能否无视大小写,所以还需要补充,hashset的时间复杂度为O(1),而Dictionary的时间复杂度为O(n),当数据量比较大时查找速度比较快。Dictionaryhashset的区别再去字典使用key查找value,查找value的速度比较快,而hashset为一个集合,关于这两个的区别以后还会补充,目前只知道这些。

  • c#连接Mysql数据库
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    private static string constr = @"Server=localhost;UserId=root;password=yourpassword;Database=databaseName";
    public MySqlConnection sqlConnection() {
    MySqlConnection conn = new MySqlConnection(constr);
    conn.Open();
    string msg = conn.State.ToString();
    return conn;
    }
    public void sqlConnectionClose(MySqlConnection conn) {
    conn.Close();
    }

这里创建了一个数据库类,在该类中实现以上两种方法,目的保护数据库账户密码,在这里并不需要,只是个人的一点想法,不知道对错

  • 如何大批量插入数据到Mysql中
    这里参考了链接采用了事物处理的方法,具体的还需要进一步学习。主要是将插入语句放入到一个List<string>中,所以需要解析文本,生成插入语句,将所有的插入语句添加到一个列表中,为了检查插入语句的正确性,将所有的插入语句写入到一个txt文本中,方便检查。
  • txtFilter类分析
    解析的文本文件由一些特点,有些图片没有关键字,所以对于这些信息需要判断删除,并且解析关键字的时候有的关键字是空格,这些问题在开始的时候都没有考虑到。所以在原来的代码上添加了一些判定条件。为了检查方便将三张表的插入语句各自打印了出来,有些代码存在重复,可以优化一些,比如针对不同的操作设定操作码,使用switch case语句,选择不同的筛选方式。先写出关键的文本解析语句,将所有插入语句存入List<string>中,并且定义了将插入语句写入文本的函数,这样有利于查看插入语句是否存在问题。以下是主要函数代码:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    大专栏  c#数据库解析ine">52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    public List<string> filterToSqlCommond2(string fileName)
    {
    List<string> SQLStringList = new List<string>();
    Data fileData = new Data();
    Dictionary<string, int> keywordDic = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);
    string sqlCommond="";
    int numOfKeyword = 0;
    int numOfImage = 0;
    //如果使用HashSet判断关键字是否存在会更快一些,这里并没有用这种方法
    //HashSet<string> keywordSet = new HashSet<string>();
    StreamReader sr = new StreamReader(fileName);
    string strContent;
    while ((strContent = sr.ReadLine()) != null)
    {
    string[] strArr = strContent.Split(',');
    fileData.id_other = strArr[0];
    fileData.id_self = strArr[1];
    fileData.image_url = strArr[3];
    string insertImageCommond = "";
    string insertKeyAndR = "";
    string[] keyword = strArr[4].Split(' ');
    //numKeyword表示读取每一行获得的关键字个数
    int numKeyword = keyword.Length;
    switch(numKeyword){
    case 1:
    if (!string.IsNullOrEmpty(keyword[0]))
    {
    numOfImage += 1;
    insertImageCommond = string.Format(@"insert into image(image_id,id_other,id_self,image_url) values('{0}','{1}','{2}','{3}');", numOfImage, fileData.id_other, fileData.id_self, fileData.image_url);
    if (!keywordDic.Keys.Contains(keyword[0]))
    {
    numOfKeyword += 1;
    keywordDic.Add(keyword[0], numOfKeyword);
    string.Format(@" insert into imagekeyword(keyword_id,keyword) value('{0}','{1}');insert into img_and_key_relation(keyword_id,image_id) values('{2}','{3}');", keywordDic[keyword[0]], keyword[0], keywordDic[keyword[0]], numOfImage);
    }
    else
    {
    int keyword_id = keywordDic[keyword[0]];
    insertKeyAndR = insertKeyAndR + string.Format(@"insert into img_and_key_relation(keyword_id,image_id) values('{0}','{1}');", keyword_id, numOfImage);
    }
    }
    sqlCommond = insertImageCommond + insertKeyAndR;
    SQLStringList.Add(sqlCommond);
    break;
    default:
    numOfImage += 1;
    insertImageCommond = string.Format(@"insert into image(image_id,id_other,id_self,image_url) values('{0}','{1}','{2}','{3}');", numOfImage, fileData.id_other, fileData.id_self, fileData.image_url);
    for (int i = 0; i < numKeyword; i++)
    {
    if (!string.IsNullOrEmpty(keyword[i]))
    {
    if (!keywordDic.Keys.Contains(keyword[i]))
    {
    numOfKeyword += 1;
    keywordDic.Add(keyword[i], numOfKeyword);
    insertKeyAndR = insertKeyAndR + string.Format(@" insert into imagekeyword(keyword_id,keyword) value('{0}','{1}');insert into img_and_key_relation(keyword_id,image_id) values('{2}','{3}');", keywordDic[keyword[i]], keyword[i], keywordDic[keyword[i]], numOfImage);
    }
    else
    {
    int keyword_id = keywordDic[keyword[i]];
    insertKeyAndR = insertKeyAndR + string.Format(@"insert into img_and_key_relation(keyword_id,image_id) values('{0}','{1}');", keyword_id, numOfImage);
    }
    }
    }
    sqlCommond = insertImageCommond + insertKeyAndR;
    SQLStringList.Add(sqlCommond);
    break;
    }
    }
    return SQLStringList;
    }

为了将关键字是空格的图像解析出去,所以使用了两种方式,一般有空格的图像信息的键值长度为1,但是键值为1的又不一定是空格(有点啰嗦意思理解就好)所以将解析方式设为两种,键值长度为1>1两种。然后判断键值是否为空格,不是空格的话将图像长度+1,数据库中图像表的键值与图片长度(相当于图片的index)相关联。
因为一个图像不一定有一个关键字,所以图像的插入语句与关键字与关系表的插入语句分开统计。获得每个图片关键字的长度,将每一个图片的关键字使用Sqlit(' ')解析到一个字符串数组中,遍历字符串判断关键字是否存在在字典中,不存在的话将该关键字插入到关键字表中,存在的话直接在关键字字典中查找该关键字的键值,将图像的键值与该关键字的键值插入到关系表中。最后将该图片的所有插入语句赋值给sqlCommond,加入到指令列表SQLStringList中,解析完后返回列表。

c#数据库解析的更多相关文章

  1. 使用递归算法结合数据库解析成java树形结构

    使用递归算法结合数据库解析成java树形结构 1.准备表结构及对应的表数据a.表结构: create table TB_TREE ( CID NUMBER not null, CNAME VARCHA ...

  2. 【ABAP系列】SAP 的逻辑数据库解析

    公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[ABAP系列]SAP 的逻辑数据库解析   前 ...

  3. oracle数据库解析json格式

    随着非关系型数据大规模使用,以json格式产生的数据也出现在我所管理的Oracle数据库的CLOB字段里面,使用过程中就需要解析出指定键的值. 使用了最新版本 如果Oracle版本为12.1.0.2的 ...

  4. iOS sqlite3数据库解析

    看来从版本3.3.1基本上已经支持线程句柄的传递功能.具体限制我标记了一下.(6) Is SQLite threadsafe?SQLite is threadsafe. We make this co ...

  5. 数据库解析IP,时间戳

    #解析IP SELECT INET_NTOA('168494269'); #解析时间戳 SELECT FROM_UNIXTIME('1505458308');

  6. 递归算法结合数据库 解析 java树形结构

    1.准备表结构及对应的表数据a.表结构: create table TB_TREE ( CID NUMBER not null, CNAME VARCHAR2(50), PID NUMBER //父节 ...

  7. Sakila——MySQL样例数据库解析(已经迁移)

    一.Introduction Sakila可以作为数据库设计的参考,也可作为实验数据.我是用作数据仓库和ODI学习的实验数据. The Sakila sample database was devel ...

  8. 阶段5 3.微服务项目【学成在线】_day17 用户认证 Zuul_07-用户认证-认证服务查询数据库-解析申请令牌错误信息

    1.2.5.4 解析申请令牌错误信息 当账号输入错误应该返回用户不存在的信息,当密码错误要返回用户名或密码错误信息,业务流程图如下: 修改申请令牌的程序解析返回的错误: 由于restTemplate收 ...

  9. 纯真IP数据库解析Delphi D10.1下正常使用

    直接一个单元,代码分享出来. unit   Net.IPLocation; interface uses System.Classes, System.SysUtils, Winapi.WinSock ...

随机推荐

  1. java8的lambda过滤list遍历集合,排序

    1.根据属性过滤list List<AllManagerBean> testLists = broadCastRoomMapper.allManagerlist(); List<Al ...

  2. 图论模型--dijstra算法和floyd算法

    matlab代码实现:https://blog.csdn.net/weixin_40108753/article/details/81237585 python代码实现:

  3. bzoj2127happiness(最小割)

    一眼最小割. 一种比较好想的建图方式如下: 连源点表示学文,连汇点表示学理,然后adde(S,id(i,j),a[i][j]),adde(id(i,j),T,b[i][j]):对于相邻座位选择同一科的 ...

  4. 计量经济与时间序列_关于Box-Jenkins的ARMA模型的经济学意义(重要思路)

    1 很多人已经了解到AR(1)这种最简单的时间序列模型,ARMA模型包括AR模型和MA模型两个部分,这里要详细介绍Box-Jenkins模型的观念(有些资料中把ARMA模型叫做Box-Jenkins模 ...

  5. Java之代码块

    package com.atguigu.java3;/* * 代码块(或初始化块) * * 1. 代码块的作用:用来初始化类.对象 * 2. 代码块如果有修饰的话,只能使用static. * 3. 分 ...

  6. Django静态文件配置-request方法-ORM简介-字段的增删改查

    app的创建注意事项: 在Django新创建的app要在seetings.py中添加注册,才会生效 创建app:django-adminapp an startapp app名称 或者 python3 ...

  7. Pipe Fitter and the Fierce Dogs

    Pipe Fitter and the Fierce Dogs [JAG Asia 2016] 理解题意之后,就是一个非常傻的DP 然后难在理解题意,理解非法状态 #include <bits/ ...

  8. Linux服务器性能查看命令

    一.uptime命令 [root@#test~]# uptime15:26:42 up 101 days, 18:44,  3 users,  load average: 0.18, 0.22, 0. ...

  9. Scapy-ARPspoof学习

    layout title tag date post Scapy模块学习之ARP欺骗 Python 2018-05-08 from scapy.all import Ether,ARP,sendp,g ...

  10. 使用 Wintersmith + Serverless Framework 快速创建个人站点

    首先我们来介绍下,Wintersmith 是一个简单而灵活的静态站点生成器.采用 markdown 构建,这个是我们的基础条件. Serverless Framework:在 GitHub 上有三万颗 ...