不管你是用.net framework还是用.net core或者更高版本.net环境,这篇文章也许都能帮到你!因为接下来我会提供一个简单粗暴的方式,来快速实现多款扫码器的通用扫码功能。目前本地测试过的包括基恩士系列、康耐视系列、以及其他支持以太网通信的多款小众厂家等。

下面开始重点操作:

首先,在你的项目里面引用Wesky.Net.OpenTools 包,1.0.7以及以上版本均可。

如果你是在.netframework环境下面开放,或者是没有使用依赖注入的项目中使用,使用方式可以直接new一个对象来使用,有关使用如下代码:

ICodeReader reader = new CodeReader();
ReaderClientInfo clientInfo = new ReaderClientInfo(); // 扫码器客户端实例
clientInfo.Ip = IPAddress.Parse("192.168.1.102"); // 扫码器IP
clientInfo.Port = 3000; // 扫码器端口号
clientInfo.Count = 3; // 没扫到码重试次数
clientInfo.SendTimeOut = 3000; // 请求超时 毫秒
clientInfo.ReceiveTimeOut = 3000; // 接收扫码内容超时 毫秒
clientInfo.Brand = "SR"; // 扫码器品牌
clientInfo.Command = "CMD"; // 扫码器触发指令,指令可通过各个扫码器厂家提供的配置软件,配置为通用的
clientInfo.ReaderNo = 1; // 扫码器编号,可自定义,例如有10个,就可以配置1-10号
clientInfo.CloseCommand = ""; // 停止触发指令,如果没有则默认空字符串即可

ReaderResultInfo res = reader.ReaderConnection(ref clientInfo); // 通信连接,连接扫码器服务端,参数返回客户端实例 以及 标准返回值类型ReaderResultInfo

if (!res.IsSucceed)
{
Console.WriteLine($"与扫码器建立通信连接失败:{res.Message}");
return;
}
res = reader.ReaderRead(ref clientInfo); // 传入扫码器客户端实例,进行扫码。并参数内返回最新的扫码器客户端实例
if (!res.IsSucceed)
{
Console.WriteLine($"扫码异常:{res.Message}");
return;
}
else
{
Console.WriteLine($"扫到码:{res.Value} 扫码耗时:{res.ElapsedMilliseconds}");
}
 

当然,强烈建议你们的项目使用.net core或以上环境。毕竟.net core是开源的,还可以跨平台,不管你是在Windows运行还是在Linux,都可以运行。

下面是在.net core或以上环境下的使用。例如我新建一个.net 8的webapi项目,

对ICodeReader接口和CodeReader类进行依赖注入的注册,建议使用瞬时生命周期,可以提高多个扫码器同时存在时的并发扫码效率。

例如:builder.Services.AddTransient<ICodeReader, CodeReader>();

建议新建一个全局实体类属性,用于存储扫码器的所有客户端实例,用于保持实例长连接。

例如:

public class ReaderClients{    public static ReaderClientInfo[] Clients { get; set; }=new ReaderClientInfo[0];}

扫码器服务注入和使用.此处为了方便,我直接创建一个api控制器来演示,并对ICodeReader进行了构造函数注入。大佬们请自行根据实际情况进行操作。

假设有一个方法,或者接口等,传入一批扫码设备的配置信息,例如配置文件读取、数据库读取、或者其他任意方式配置的扫码器集合信息,传给连接接口或者方法等。然后根据传入的配置信息,进行对每个设备通信连接:

访问扫码函数,进行触发扫码操作。以下案例仅供参考,请根据个人实际情况进行优化或者修改。例如修改扫码次数、扫码成功或失败的其他处理等等。

控制器内所有代码如下:

 1  public class ScannerController : ControllerBase
2 {
3 private readonly ICodeReader _reader;
4 public ScannerController(ICodeReader reader)
5 {
6 _reader = reader;
7 }
8 ​
9 [HttpPost]
10 public IActionResult Connection([FromBody] List<ReaderClientInfo> clientInfos)
11 {
12 // 创建一个StringBuilder对象用于存储返回的结果信息
13 var result = new StringBuilder();
14 try
15 {
16 if (clientInfos == null || clientInfos.Count == 0)
17 {
18 return Ok("没有可用客户连接信息"); // No available client connection info.
19 }
20 ​
21 // 为全局静态数组分配空间
22 ReaderClients.Clients = new ReaderClientInfo[clientInfos.Count];
23 ​
24 // 用于追踪失败的连接,以便存储到全局数组中
25 for (int i = 0; i < clientInfos.Count; i++)
26 {
27 var clientInfo = clientInfos[i];
28 // 尝试与读卡器设备建立连接
29 var res = _reader.ReaderConnection(ref clientInfo);
30 if (res.IsSucceed)
31 {
32 // 连接成功,记录成功信息
33 result.AppendLine($"{DateTime.Now:yyyy/MM/dd HH:mm:ss}>>>与扫码器设备通信连接成功:{res.Message}");
34 }
35 else
36 {
37 // 连接失败,记录失败信息并将客户端信息存储到全局静态数组中
38 ReaderClients.Clients[i] = clientInfo;
39 result.AppendLine($"{DateTime.Now:yyyy/MM/dd HH:mm:ss}>>>通信连接失败");
40 }
41 }
42 ​
43 // 返回所有连接结果
44 return Ok(result.ToString());
45 }
46 catch (Exception ex)
47 {
48 // 异常处理,返回异常信息
49 return Ok($"{DateTime.Now:yyyy/MM/dd HH:mm:ss}>>>通信连接失败: {ex.Message}");
50 }
51 }
52 ​
53 [HttpPost]
54 public IActionResult BeginScanner(int count)
55 {
56 const string timeFormat = "yyyy/MM/dd HH:mm:ss";
57 StringBuilder result = new StringBuilder();
58 if (ReaderClients.Clients == null || !ReaderClients.Clients.Any())
59 {
60 return Ok($"{DateTime.Now.ToString(timeFormat)} >>> 没有可连接的扫码器客户端,无法启动扫描功能。");
61 }
62 try
63 {
64 for (int now = 1; now <= count; now++)
65 {
66 var res = _reader.ReaderRead(ref ReaderClients.Clients[0]); // 假设第一个客户端已连接。下标0代表第一个扫码器,请根据实际情况修改。
67 if (res.IsSucceed)
68 {
69 result.AppendLine($"{DateTime.Now.ToString(timeFormat)} >>> 第{now}次扫码,扫码结果:{res.Message}");
70 }
71 else
72 {
73 result.AppendLine($"{DateTime.Now.ToString(timeFormat)} >>> 第{now}次扫码,扫码失败:{res.Value} 扫码耗时:{res.ElapsedMilliseconds}毫秒");
74 }
75 }
76 }
77 catch (Exception ex)
78 {
79 result.AppendLine($"{DateTime.Now.ToString(timeFormat)} >>> 扫码异常:{ex.Message}");
80 }
81 return Ok(result.ToString());
82 }
83 }

其他介绍:扫码器配置参数和通用返回值参数对应实体类说明。

扫码器客户端配置实体类:

 1 /// <summary>
2 /// Represents the client configuration for a scanner.
3 /// 表示扫描器的客户端配置。
4 /// </summary>
5 public class ReaderClientInfo
6 {
7 /// <summary>
8 /// The IP address of the scanner.
9 /// 扫描器的IP地址。
10 /// </summary>
11 public IPAddress Ip { get; set; }
12 ​
13 /// <summary>
14 /// The port number for the scanner connection.
15 /// 扫描器连接的端口号。
16 /// </summary>
17 public int Port { get; set; }
18 ​
19 /// <summary>
20 /// Number of retry attempts if no code is scanned.
21 /// 如果没有扫描到码的重试次数。
22 /// </summary>
23 public short Count { get; set; }
24 ​
25 /// <summary>
26 /// The socket connection to the scanner.
27 /// 扫描器的Socket连接。
28 /// </summary>
29 public Socket Client { get; set; }
30 ​
31 /// <summary>
32 /// The identifier number of the scanner.
33 /// 扫描器的编号。
34 /// </summary>
35 public ushort ReaderNo { get; set; }
36 ​
37 /// <summary>
38 /// Timeout in milliseconds for sending requests.
39 /// 发送请求的超时时间(毫秒)。
40 /// </summary>
41 public int SendTimeOut { get; set; } = 3000;
42 ​
43 /// <summary>
44 /// Timeout in milliseconds for receiving responses.
45 /// 接收响应的超时时间(毫秒)。
46 /// </summary>
47 public int ReceiveTimeOut { get; set; } = 3000;
48 ​
49 /// <summary>
50 /// The brand of the scanner, such as Keyence, Cognex, OPT, etc.
51 /// 扫描器的品牌,例如基恩士、康耐视、OPT等等。
52 /// </summary>
53 public string Brand { get; set; }
54 ​
55 /// <summary>
56 /// Command to trigger the scan.
57 /// 触发扫描的命令。
58 /// </summary>
59 public string Command { get; set; }
60 ​
61 /// <summary>
62 /// Command to stop triggering the scanner (used by Keyence).
63 /// 停止触发扫描器的命令(基恩士使用)。
64 /// </summary>
65 public string CloseCommand { get; set; }
66 ​
67 /// <summary>
68 /// Start character for commands, if applicable (empty string if none).
69 /// 命令的起始字符(如果有),没有则为空字符串。
70 /// </summary>
71 public string Start { get; set; } = string.Empty;
72 ​
73 /// <summary>
74 /// End character for commands, such as '\r\n' for Keyence; empty if not used.
75 /// 命令的结束字符,如基恩士使用的'\r\n';如果不使用则为空字符串。
76 /// </summary>
77 public string End { get; set; } = string.Empty;
78 }

返回值实体类:

 1   /// <summary>
2 /// Represents the result information from a scanner.
3 /// 表示扫描器的结果信息。
4 /// </summary>
5 public class ReaderResultInfo
6 {
7 /// <summary>
8 /// Indicates whether the scan was successful.
9 /// 指示扫描是否成功。
10 /// </summary>
11 public bool IsSucceed { get; set; } = false;
12 ​
13 /// <summary>
14 /// The error message if the scan failed.
15 /// 如果扫描失败,错误信息。
16 /// </summary>
17 public string Message { get; set; } = string.Empty;
18 ​
19 /// <summary>
20 /// The result of the scan.
21 /// 扫描结果。
22 /// </summary>
23 public string Value { get; set; } = string.Empty;
24 ​
25 /// <summary>
26 /// The time taken for the scan in milliseconds.
27 /// 扫描所耗费的时间(毫秒)。
28 /// </summary>
29 public long ElapsedMilliseconds { get; set; } = 0;
30 ​
31 /// <summary>
32 /// The number identifying the scanner.
33 /// 扫描器编号。
34 /// </summary>
35 public ushort ReaderNo { get; set; } = 0;
36 ​
37 /// <summary>
38 /// The brand of the scanner.
39 /// 扫描器品牌。
40 /// </summary>
41 public string Brand { get; set; } = string.Empty;
42 }

如果觉得有帮助,欢迎点赞、分享​。

​不介意也可关注个人公众号:Dotnet Dancer

不管你是用.net framework还是用.net core或者更高版本.net环境,这篇文章也许都能帮到你!因为接下来我会提供一个简单粗暴的方式,来快速实现多款扫码器的通用扫码功能。目前本地测试过的包括基恩士系列、康耐视系列、以及其他支持以太网通信的多款小众厂家等。

下面开始重点操作:

首先,在你的项目里面引用Wesky.Net.OpenTools 包,1.0.7以及以上版本均可。

如果你是在.netframework环境下面开放,或者是没有使用依赖注入的项目中使用,使用方式可以直接new一个对象来使用,有关使用如下代码:

ICodeReader reader = new CodeReader();ReaderClientInfo clientInfo = new ReaderClientInfo(); // 扫码器客户端实例clientInfo.Ip = IPAddress.Parse("192.168.1.102"); // 扫码器IPclientInfo.Port = 3000; // 扫码器端口号clientInfo.Count = 3;  // 没扫到码重试次数clientInfo.SendTimeOut = 3000; // 请求超时 毫秒clientInfo.ReceiveTimeOut = 3000; // 接收扫码内容超时 毫秒clientInfo.Brand = "SR"; // 扫码器品牌clientInfo.Command = "CMD"; // 扫码器触发指令,指令可通过各个扫码器厂家提供的配置软件,配置为通用的clientInfo.ReaderNo = 1;  // 扫码器编号,可自定义,例如有10个,就可以配置1-10号clientInfo.CloseCommand = ""; // 停止触发指令,如果没有则默认空字符串即可ReaderResultInfo res = reader.ReaderConnection(ref clientInfo); // 通信连接,连接扫码器服务端,参数返回客户端实例 以及 标准返回值类型ReaderResultInfoif (!res.IsSucceed){    Console.WriteLine($"与扫码器建立通信连接失败:{res.Message}");    return;}res = reader.ReaderRead(ref clientInfo); // 传入扫码器客户端实例,进行扫码。并参数内返回最新的扫码器客户端实例if (!res.IsSucceed){   Console.WriteLine($"扫码异常:{res.Message}");    return;}else{    Console.WriteLine($"扫到码:{res.Value}  扫码耗时:{res.ElapsedMilliseconds}");}

当然,强烈建议你们的项目使用.net core或以上环境。毕竟.net core是开源的,还可以跨平台,不管你是在Windows运行还是在Linux,都可以运行。

下面是在.net core或以上环境下的使用。例如我新建一个.net 8的webapi项目,

对ICodeReader接口和CodeReader类进行依赖注入的注册,建议使用瞬时生命周期,可以提高多个扫码器同时存在时的并发扫码效率。

例如:builder.Services.AddTransient<ICodeReader, CodeReader>();

建议新建一个全局实体类属性,用于存储扫码器的所有客户端实例,用于保持实例长连接。

例如:

public class ReaderClients{    public static ReaderClientInfo[] Clients { get; set; }=new ReaderClientInfo[0];}

扫码器服务注入和使用.此处为了方便,我直接创建一个api控制器来演示,并对ICodeReader进行了构造函数注入。大佬们请自行根据实际情况进行操作。

假设有一个方法,或者接口等,传入一批扫码设备的配置信息,例如配置文件读取、数据库读取、或者其他任意方式配置的扫码器集合信息,传给连接接口或者方法等。然后根据传入的配置信息,进行对每个设备通信连接:

访问扫码函数,进行触发扫码操作。以下案例仅供参考,请根据个人实际情况进行优化或者修改。例如修改扫码次数、扫码成功或失败的其他处理等等。

控制器内所有代码如下:

 public class ScannerController : ControllerBase {     private readonly ICodeReader _reader;     public ScannerController(ICodeReader reader)     {         _reader = reader;     }     [HttpPost]     public IActionResult Connection([FromBody] List<ReaderClientInfo> clientInfos)     {         // 创建一个StringBuilder对象用于存储返回的结果信息         var result = new StringBuilder();         try         {             if (clientInfos == null || clientInfos.Count == 0)             {                 return Ok("没有可用客户连接信息"); // No available client connection info.             }             // 为全局静态数组分配空间             ReaderClients.Clients = new ReaderClientInfo[clientInfos.Count];             // 用于追踪失败的连接,以便存储到全局数组中             for (int i = 0; i < clientInfos.Count; i++)             {                 var clientInfo = clientInfos[i];                 // 尝试与读卡器设备建立连接                 var res = _reader.ReaderConnection(ref clientInfo);                 if (res.IsSucceed)                 {                     // 连接成功,记录成功信息                     result.AppendLine($"{DateTime.Now:yyyy/MM/dd HH:mm:ss}>>>与扫码器设备通信连接成功:{res.Message}");                 }                 else                 {                     // 连接失败,记录失败信息并将客户端信息存储到全局静态数组中                     ReaderClients.Clients[i] = clientInfo;                     result.AppendLine($"{DateTime.Now:yyyy/MM/dd HH:mm:ss}>>>通信连接失败");                 }             }             // 返回所有连接结果             return Ok(result.ToString());         }         catch (Exception ex)         {             // 异常处理,返回异常信息             return Ok($"{DateTime.Now:yyyy/MM/dd HH:mm:ss}>>>通信连接失败: {ex.Message}");         }     }     [HttpPost]     public IActionResult BeginScanner(int count)     {         const string timeFormat = "yyyy/MM/dd HH:mm:ss";         StringBuilder result = new StringBuilder();         if (ReaderClients.Clients == null || !ReaderClients.Clients.Any())         {             return Ok($"{DateTime.Now.ToString(timeFormat)} >>> 没有可连接的扫码器客户端,无法启动扫描功能。");         }         try         {             for (int now = 1; now <= count; now++)             {                 var res = _reader.ReaderRead(ref ReaderClients.Clients[0]); // 假设第一个客户端已连接。下标0代表第一个扫码器,请根据实际情况修改。                 if (res.IsSucceed)                 {                     result.AppendLine($"{DateTime.Now.ToString(timeFormat)} >>> 第{now}次扫码,扫码结果:{res.Message}");                 }                 else                 {                     result.AppendLine($"{DateTime.Now.ToString(timeFormat)} >>> 第{now}次扫码,扫码失败:{res.Value} 扫码耗时:{res.ElapsedMilliseconds}毫秒");                 }             }         }         catch (Exception ex)         {             result.AppendLine($"{DateTime.Now.ToString(timeFormat)} >>> 扫码异常:{ex.Message}");         }         return Ok(result.ToString());     } }

其他介绍:扫码器配置参数和通用返回值参数对应实体类说明。

扫码器客户端配置实体类:

/// <summary>/// Represents the client configuration for a scanner./// 表示扫描器的客户端配置。/// </summary>public class ReaderClientInfo{    /// <summary>    /// The IP address of the scanner.    /// 扫描器的IP地址。    /// </summary>    public IPAddress Ip { get; set; }    /// <summary>    /// The port number for the scanner connection.    /// 扫描器连接的端口号。    /// </summary>    public int Port { get; set; }    /// <summary>    /// Number of retry attempts if no code is scanned.    /// 如果没有扫描到码的重试次数。    /// </summary>    public short Count { get; set; }    /// <summary>    /// The socket connection to the scanner.    /// 扫描器的Socket连接。    /// </summary>    public Socket Client { get; set; }    /// <summary>    /// The identifier number of the scanner.    /// 扫描器的编号。    /// </summary>    public ushort ReaderNo { get; set; }    /// <summary>    /// Timeout in milliseconds for sending requests.    /// 发送请求的超时时间(毫秒)。    /// </summary>    public int SendTimeOut { get; set; } = 3000;    /// <summary>    /// Timeout in milliseconds for receiving responses.    /// 接收响应的超时时间(毫秒)。    /// </summary>    public int ReceiveTimeOut { get; set; } = 3000;    /// <summary>    /// The brand of the scanner, such as Keyence, Cognex, OPT, etc.    /// 扫描器的品牌,例如基恩士、康耐视、OPT等等。    /// </summary>    public string Brand { get; set; }    /// <summary>    /// Command to trigger the scan.    /// 触发扫描的命令。    /// </summary>    public string Command { get; set; }    /// <summary>    /// Command to stop triggering the scanner (used by Keyence).    /// 停止触发扫描器的命令(基恩士使用)。    /// </summary>    public string CloseCommand { get; set; }    /// <summary>    /// Start character for commands, if applicable (empty string if none).    /// 命令的起始字符(如果有),没有则为空字符串。    /// </summary>    public string Start { get; set; } = string.Empty;    /// <summary>    /// End character for commands, such as '\r\n' for Keyence; empty if not used.    /// 命令的结束字符,如基恩士使用的'\r\n';如果不使用则为空字符串。    /// </summary>    public string End { get; set; } = string.Empty;}

返回值实体类:

  /// <summary>  /// Represents the result information from a scanner.  /// 表示扫描器的结果信息。  /// </summary>  public class ReaderResultInfo  {      /// <summary>      /// Indicates whether the scan was successful.      /// 指示扫描是否成功。      /// </summary>      public bool IsSucceed { get; set; } = false;      /// <summary>      /// The error message if the scan failed.      /// 如果扫描失败,错误信息。      /// </summary>      public string Message { get; set; } = string.Empty;      /// <summary>      /// The result of the scan.      /// 扫描结果。      /// </summary>      public string Value { get; set; } = string.Empty;      /// <summary>      /// The time taken for the scan in milliseconds.      /// 扫描所耗费的时间(毫秒)。      /// </summary>      public long ElapsedMilliseconds { get; set; } = 0;      /// <summary>      /// The number identifying the scanner.      /// 扫描器编号。      /// </summary>      public ushort ReaderNo { get; set; } = 0;      /// <summary>      /// The brand of the scanner.      /// 扫描器品牌。      /// </summary>      public string Brand { get; set; } = string.Empty;    }  

如果觉得有帮助,欢迎点赞、分享​。

​不介意也可关注个人公众号:Dotnet Dancer

工业福利!用.NET快速开发物联网扫码器设备的通用扫码功能的更多相关文章

  1. java 快速开发平台 有代码生成器 springmvc SSM后台框架源码

    .   权限管理:点开二级菜单进入三级菜单显示 角色(基础权限)和按钮权限      角色(基础权限): 分角色组和角色,独立分配菜单权限和增删改查权限.      按钮权限: 给角色分配按钮权限.2 ...

  2. C#.NET 大型通用信息化系统集成快速开发平台 4.1 版本 - 严格的用户账户审核功能

    整个集团有几万个用户,一个个用户添加是不现实的,只有每个公司的系统管理员添加.或者用户申请帐户,然后有相应的管理员审核,才会更准确一些. 每个公司.分公司.部门的账户情况只有所在公司的管理员是最清楚的 ...

  3. 使用GizwitsOpenAPI,快速开发轻应用

    导读:使用机智云提供的Open API(Http / WebSocket),可以快速开发网页或微信应用等基于html的轻应用,用于管理和控制智能设备.机智云 Open API 主要帮助开发者通过 HT ...

  4. winform快速开发平台 -> 基础组件之分页控件

    一个项目控件主要由及部分的常用组件,当然本次介绍的是通用分页控件. 处理思想:我们在处理分页过程中主要是针对数据库操作. 一般情况主要是传递一些开始位置,当前页数,和数据总页数以及相关关联的业务逻辑. ...

  5. SNF开发平台WinForm之十四-站内发送系统信息-SNF快速开发平台3.3-Spring.Net.Framework

    1运行效果: 2开发实现: .组装站内信息发送实体对象. SNFService SNFService = new SNFService(); if (this.ucUser.SelectedIds ! ...

  6. SNF开发平台WinForm之十三-单独从服务器上获取PDF文件进行显示-SNF快速开发平台3.3-Spring.Net.Framework

    1运行效果: 2开发实现: 如果需要单独显示PDF文件时用下面代码去实现,指定url地址. 地址: . 获取附件管理的实体对象: List<KeyValuePair<string, obj ...

  7. SNF开发平台WinForm之十二-发送手机短信功能调用-金笛-SNF快速开发平台3.3-Spring.Net.Framework

    1.调用前组装参数 2.调用发送信息服务脚本   .调用前组装参数: BaseSendTaskEntity entity = new BaseSendTaskEntity(); entity.Mess ...

  8. SNF开发平台WinForm之十一-程序打包-SNF快速开发平台3.3-Spring.Net.Framework

    原来我们用的是微软自带的打包工具去打包,但感觉好像也是第三方做的打包并且很是麻烦,还有时不成功报错.那综合考虑就找一个简单实用的打包工具吧,就找到了NSIS这个.具体打包步骤如下: 1.安装NSIS ...

  9. SNF开发平台WinForm之十-Excel导入-SNF快速开发平台3.3-Spring.Net.Framework

    7.1运行效果: 2.Excel导入开发实现 2.1. 创建窗体,修改命名空间 新增的窗体命名“FrmImport表名”,这个导入窗口比较其它窗口会特殊一些,需要继承BaseFormImport父级窗 ...

  10. SNF开发平台WinForm之九-代码生成器使用说明-SNF快速开发平台3.3-Spring.Net.Framework

    下面就具体的使用说明: 1.获取代码生成器的授权码(根据本机)-----还原数据库-------改config-----代码生成器 改代码生成器Config 2.登录代码生成器 3.查看是否连接成功 ...

随机推荐

  1. HarmonyOS SDK,赋能开发者实现更具象、个性化开发诉求

    随着移动互联网的逐步成熟,用户的需求越来越细化.鸿蒙生态为开发者提供的HarmonyOS SDK开放能力,高效赋能美团外卖等合作伙伴实现更具象.个性化的开发诉求,给用户提供更丰富便捷的体验. 点击链接 ...

  2. 可视化库 pygal 无法保存成本地文件

    问题:在使用可视化库 pygal 保存图像到本地时,出现报错 第一次报错是,提示没有  cairosvg  这个模块,所以直接通过 pip 安装 pip install cairosvg 安装完了以后 ...

  3. BZOJ 4403序列统计

    假设存在一个满足条件的长度为i的不下降序列(显然是一定存在的)那么只需要从中选出i个数即可 (不必在意选出具体数的大小,可以把满足条件的序列写下来,选几个数感受一下). 但是$n \choose m ...

  4. mysql 必知必会整理—全球化与本地化[十六]

    前言 简单介绍一下字符集. 数据库表被用来存储和检索数据.不同的语言和字符集需要以不同的方式存储和检索. 因此,MySQL需要适应不同的字符集(不同的字母和字符),适应不同的排序和检索数据的方法. 字 ...

  5. The request client is not a secure context and the resource is in more-private address space `privat

    Chrome跨域问题:has been blocked by CORS policy: The request client is not a secure context and the resou ...

  6. 第壹課-Install:Mirth Connect在Win10下的安装步骤

    1.安装JDK,推荐安装JDK8 64位,版本jdk-8u201-windows-x64.exe. 安装JDK后,同时必须配置win10的系统环境变量[示例如下]: JAVA_HOME : F:\Ja ...

  7. EasyNLP集成K-BERT算法,借助知识图谱实现更优Finetune

    导读 知识图谱(Knowledge Graph)的概念⾸次出现2012年,由Google提出,它作为⼀种⼤规模语义⽹络, 准确地描述了实体以及实体之间的关系.知识图谱最早应⽤于搜索引擎,⽤于准备返回⽤ ...

  8. 盒马新零售基于DataWorks搭建数据中台的实践

    大家好,我叫许日花名欢伯,在2016年盒马早期的时候,我就转到了盒马的事业部作为在线数据平台的研发负责人,现在阿里云的计算平台负责DataWorks的建模引擎团队.今天的分享内容也来源于另一位嘉宾李启 ...

  9. 微信不再提供小程序打开App?借助H5为App引流的方式你必须知道!

    简介: 2021年5月14日App开发者领域发布了一条重要消息:微信开放平台为了提升用户体验,将于2021年5月20日(后来延期到2021年5月27日)起不再提供"小程序打开App技术服务& ...

  10. Quick BI的可视分析之路

    简介: Quick BI是专为云上用户量身打造的智能数据分析和可视化BI产品,帮助企业快速完成从传统的数据分析到数据云化+分析云化的转变,将企业的业务数据产出后以最快的速度被推送到各组织侧消费使用.本 ...