You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Aucma.Scada/Aucma.Scada.HikRobot/MvCodeHelper.cs

665 lines
29 KiB
C#

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

using MvCodeReaderSDKNet;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
using static System.Runtime.CompilerServices.RuntimeHelpers;
using HighWayIot.Log4net;
using HighWayIot.Config;
using System.Security.Policy;
using HighWayIot.Repository.service;
using System.Linq;
using HighWayIot.Repository.service.Impl;
namespace Aucma.Core.Scanner
{
public class MvCodeHelper
{
private static AppConfig appConfig = AppConfig.Instance;
public static bool m_bGrabbing = true;
private static string SheellLastCode;
private static string LinerLastCode;
// 内胆扫码器ip
private static string LinerScannerIp = appConfig.linerHikRobotIp;
// 箱壳扫码器ip
private static string ShellScannerIp = appConfig.shellHikRobotIp;
private static IRealTaskInfoService _realTaskInfoService = new RealTaskInfoServiceImpl();
#region 全局变量定义
public static DateTime ShellLiveTime = DateTime.Now;
public static DateTime LinerLiveTime = DateTime.Now;
#endregion
#region 委托事件
/// <summary>
/// 刷新扫码器状态
/// </summary>
/// <param name="materialCodeStr"></param>
/// <param name="ip"></param>
public delegate void RefreshState(string ip, bool flag);
public static event RefreshState RefreshStateEvent;
public delegate void RefreshMaterialCodeStr(string materialCodeStr, string ip);
public static event RefreshMaterialCodeStr RefreshMaterialCodeStrEvent;
//NoRead事件通知
public delegate void MessageNoRead(string storeCode);
public static event MessageNoRead MessageNoReadEvent;
/// <summary>
/// 日志信息刷新
/// </summary>
/// <param name="message"></param>
public delegate void RefreshLogMessage(string message);
public static event RefreshLogMessage RefreshLogMessageEvent;
#endregion
public static void ShellImageCallbackFunc(IntPtr pData, IntPtr pstFrameInfoEx2, IntPtr pUser)
{
var stFrameInfo = (MvCodeReader.MV_CODEREADER_IMAGE_OUT_INFO_EX2)Marshal.PtrToStructure(pstFrameInfoEx2, typeof(MvCodeReader.MV_CODEREADER_IMAGE_OUT_INFO_EX2));
MvCodeReader.MV_CODEREADER_RESULT_BCR_EX2 stBcrResult = (MvCodeReader.MV_CODEREADER_RESULT_BCR_EX2)Marshal.PtrToStructure(stFrameInfo.UnparsedBcrList.pstCodeListEx2, typeof(MvCodeReader.MV_CODEREADER_RESULT_BCR_EX2));
if(stBcrResult.nCodeNum==0)
{
//更新扫码器存活时间
ShellLiveTime = DateTime.Now;
Console.WriteLine("箱壳No Read 处理");
//MessageNoReadEvent(appConfig.shellStoreCode);
}
else
{
for (Int32 i = 0; i < stBcrResult.nCodeNum; i++)
{
string strCode = Encoding.GetEncoding("GB2312").GetString(stBcrResult.stBcrInfoEx2[i].chCode);
//Console.WriteLine(DateTime.Now + ":箱壳扫码器==>Get CodeNum: " + "CodeNum[" + i.ToString() + "], CodeString[" + strCode.Trim().TrimEnd('\0') + "]");
string materialCode = strCode.Trim().TrimEnd('\0');
Console.WriteLine($"{DateTime.Now}====>>>箱壳扫码成功:{materialCode}");
if (string.IsNullOrEmpty(SheellLastCode) || SheellLastCode != strCode.Trim().TrimEnd('\0'))
{
//更新扫码器存活时间
ShellLiveTime = DateTime.Now;
RefreshMaterialCodeStrEvent?.Invoke(strCode.Trim().TrimEnd('\0'), ShellScannerIp);
SheellLastCode = strCode.Trim().TrimEnd('\0');
}
else
{
if (_realTaskInfoService == null)
{
Console.WriteLine("箱壳和上次扫描结果一样,并且任务队列无法获取");
}
else
{
//获取当前条码是否存在入库任务
var taskInfo = _realTaskInfoService.GetTaskInfosForInstore(appConfig.shellStoreCode, 0, 1);
if (taskInfo != null)
{
var infos = taskInfo.Where(x => x.materialCode == materialCode).ToList();
if (infos.Count > 0)
{
Console.WriteLine("箱壳和上次扫描结果一样,并已存在入库任务");
}
else
{
//更新扫码器存活时间
ShellLiveTime = DateTime.Now;
RefreshMaterialCodeStrEvent?.Invoke(strCode.Trim().TrimEnd('\0'), ShellScannerIp);
SheellLastCode = strCode.Trim().TrimEnd('\0');
}
}
}
}
}
}
}
public static void LinerImageCallbackFunc(IntPtr pData, IntPtr pstFrameInfoEx2, IntPtr pUser)
{
var stFrameInfo = (MvCodeReader.MV_CODEREADER_IMAGE_OUT_INFO_EX2)Marshal.PtrToStructure(pstFrameInfoEx2, typeof(MvCodeReader.MV_CODEREADER_IMAGE_OUT_INFO_EX2));
MvCodeReader.MV_CODEREADER_RESULT_BCR_EX2 stBcrResult = (MvCodeReader.MV_CODEREADER_RESULT_BCR_EX2)Marshal.PtrToStructure(stFrameInfo.UnparsedBcrList.pstCodeListEx2, typeof(MvCodeReader.MV_CODEREADER_RESULT_BCR_EX2));
if (stBcrResult.nCodeNum == 0)
{
// 更新存活时间
LinerLiveTime = DateTime.Now;
Console.WriteLine("内胆No Read 处理");
//MessageNoReadEvent(appConfig.linerStoreCode);
}
else
{
for (Int32 i = 0; i < stBcrResult.nCodeNum; i++)
{
string strCode = Encoding.GetEncoding("GB2312").GetString(stBcrResult.stBcrInfoEx2[i].chCode);
string materialCode = strCode.Trim().TrimEnd('\0');
Console.WriteLine($"{DateTime.Now}====>>>内胆扫码成功:{materialCode}");
if (string.IsNullOrEmpty(LinerLastCode) || LinerLastCode != strCode.Trim().TrimEnd('\0'))
{
// 更新存活时间
LinerLiveTime = DateTime.Now;
RefreshMaterialCodeStrEvent?.Invoke(strCode.Trim().TrimEnd('\0'), LinerScannerIp);
LinerLastCode = strCode.Trim().TrimEnd('\0');
}
else
{
if (_realTaskInfoService == null)
{
Console.WriteLine("内胆和上次扫描结果一样,并且任务队列无法获取");
}
else
{
//获取当前条码是否存在入库任务
var taskInfo = _realTaskInfoService.GetTaskInfosForInstore(appConfig.linerStoreCode, 0, 1);
if (taskInfo != null)
{
var infos = taskInfo.Where(x => x.materialCode == materialCode).ToList();
if (infos.Count > 0)
{
Console.WriteLine("内胆和上次扫描结果一样,并已存在入库任务");
}
else
{
//更新扫码器存活时间
LinerLiveTime = DateTime.Now;
RefreshMaterialCodeStrEvent?.Invoke(strCode.Trim().TrimEnd('\0'), LinerScannerIp);
LinerLastCode = strCode.Trim().TrimEnd('\0');
}
}
}
}
}
}
}
public static void Shell()
{
ShellLiveTime = DateTime.Now;
MvCodeReader.cbOutputEx2delegate ImageCallback;
MvCodeReader.MV_CODEREADER_IMAGE_OUT_INFO_EX2 stFrameInfo = new MvCodeReader.MV_CODEREADER_IMAGE_OUT_INFO_EX2();
MvCodeReader device = new MvCodeReader();
int nRet = MvCodeReader.MV_CODEREADER_OK;
do
{
try
{
// ch:枚举设备 | en:Enum device
MvCodeReader.MV_CODEREADER_DEVICE_INFO_LIST stDevList = new MvCodeReader.MV_CODEREADER_DEVICE_INFO_LIST();
nRet = MvCodeReader.MV_CODEREADER_EnumDevices_NET(ref stDevList, MvCodeReader.MV_CODEREADER_GIGE_DEVICE);
if (MvCodeReader.MV_CODEREADER_OK != nRet)
{
// 刷新扫码器状态
RefreshStateEvent?.Invoke("箱壳", false);
Thread.Sleep(1000 * 10);
break;
}
if (0 == stDevList.nDeviceNum)
{
// 刷新扫码器状态
RefreshStateEvent?.Invoke("箱壳", false);
Thread.Sleep(1000 * 10);
break;
}
MvCodeReader.MV_CODEREADER_DEVICE_INFO stDevInfo; // 通用设备信息
int nDevIndex = -1;
// ch:打印设备信息 | en:Print device info
for (Int32 i = 0; i < stDevList.nDeviceNum; i++)
{
stDevInfo = (MvCodeReader.MV_CODEREADER_DEVICE_INFO)Marshal.PtrToStructure(stDevList.pDeviceInfo[i], typeof(MvCodeReader.MV_CODEREADER_DEVICE_INFO));
if (MvCodeReader.MV_CODEREADER_GIGE_DEVICE == stDevInfo.nTLayerType)
{
MvCodeReader.MV_CODEREADER_GIGE_DEVICE_INFO stGigEDeviceInfo = (MvCodeReader.MV_CODEREADER_GIGE_DEVICE_INFO)MvCodeReader.ByteToStruct(stDevInfo.SpecialInfo.stGigEInfo, typeof(MvCodeReader.MV_CODEREADER_GIGE_DEVICE_INFO));
uint nIp1 = ((stGigEDeviceInfo.nCurrentIp & 0xff000000) >> 24);
uint nIp2 = ((stGigEDeviceInfo.nCurrentIp & 0x00ff0000) >> 16);
uint nIp3 = ((stGigEDeviceInfo.nCurrentIp & 0x0000ff00) >> 8);
uint nIp4 = (stGigEDeviceInfo.nCurrentIp & 0x000000ff);
string ipStr = nIp1 + "." + nIp2 + "." + nIp3 + "." + nIp4;
if (ipStr == ShellScannerIp)
{
nDevIndex = i;
Console.WriteLine("device IP :" + ipStr);
}
}
}
if (nDevIndex < 0)
{
Console.WriteLine("未找到箱壳扫码器");
// 刷新扫码器状态
RefreshStateEvent?.Invoke("箱壳", false);
Thread.Sleep(1000 * 30);
break;
}
stDevInfo = (MvCodeReader.MV_CODEREADER_DEVICE_INFO)Marshal.PtrToStructure(stDevList.pDeviceInfo[nDevIndex], typeof(MvCodeReader.MV_CODEREADER_DEVICE_INFO));
// ch:创建设备 | en:Create device
nRet = device.MV_CODEREADER_CreateHandle_NET(ref stDevInfo);
if (MvCodeReader.MV_CODEREADER_OK != nRet)
{
// 刷新扫码器状态
RefreshStateEvent?.Invoke("箱壳", false);
break;
}
// ch:打开设备 | en:Open device
nRet = device.MV_CODEREADER_OpenDevice_NET();
if (MvCodeReader.MV_CODEREADER_OK != nRet)
{
// 刷新扫码器状态
RefreshStateEvent?.Invoke("箱壳", false);
break;
}
// 刷新扫码器状态
RefreshStateEvent?.Invoke("箱壳", true);
// ch:注册回调函数 | en:Register image callback
ImageCallback = new MvCodeReader.cbOutputEx2delegate(ShellImageCallbackFunc);
nRet = device.MV_CODEREADER_RegisterImageCallBackEx2_NET(ImageCallback, IntPtr.Zero);
if (MvCodeReader.MV_CODEREADER_OK != nRet)
{
// 刷新扫码器状态
RefreshStateEvent?.Invoke("箱壳", false);
break;
}
// ch:开启抓图 || en: start grab image
nRet = device.MV_CODEREADER_StartGrabbing_NET();
if (MvCodeReader.MV_CODEREADER_OK != nRet)
{
// 刷新扫码器状态
RefreshStateEvent?.Invoke("箱壳", false);
break;
}
while (true)
{
Thread.Sleep(1000 * 60);
DateTime dateTime = DateTime.Now;
TimeSpan timeSpan = dateTime.Subtract(ShellLiveTime);
if (timeSpan.TotalMinutes >= 10)
{
Console.WriteLine("箱壳扫码器超时");
//CloseShell();
//Shell();
break;
}
}
// Console.ReadLine();
// 刷新扫码器状态
RefreshStateEvent?.Invoke("箱壳", false);
// ch:停止抓图 | en:Stop grabbing
nRet = device.MV_CODEREADER_StopGrabbing_NET();
if (MvCodeReader.MV_CODEREADER_OK != nRet)
{
break;
}
// ch:关闭设备 | en:Close device
nRet = device.MV_CODEREADER_CloseDevice_NET();
if (MvCodeReader.MV_CODEREADER_OK != nRet)
{
break;
}
// ch:销毁设备 | en:Destroy device
nRet = device.MV_CODEREADER_DestroyHandle_NET();
if (MvCodeReader.MV_CODEREADER_OK != nRet)
{
break;
}
}catch(Exception ex)
{
Console.WriteLine($"Shell扫码器异常:{ex.Message}");
}
} while (false);
Thread.Sleep (1000);
Shell();
}
public static void Liner()
{
LinerLiveTime = DateTime.Now;
MvCodeReader.cbOutputEx2delegate ImageCallback;
MvCodeReader.MV_CODEREADER_IMAGE_OUT_INFO_EX2 stFrameInfo = new MvCodeReader.MV_CODEREADER_IMAGE_OUT_INFO_EX2();
MvCodeReader device = new MvCodeReader();
int nRet = MvCodeReader.MV_CODEREADER_OK;
do
{
try
{
// ch:枚举设备 | en:Enum device
MvCodeReader.MV_CODEREADER_DEVICE_INFO_LIST stDevList = new MvCodeReader.MV_CODEREADER_DEVICE_INFO_LIST();
nRet = MvCodeReader.MV_CODEREADER_EnumDevices_NET(ref stDevList, MvCodeReader.MV_CODEREADER_GIGE_DEVICE);
if (MvCodeReader.MV_CODEREADER_OK != nRet)
{
// 刷新扫码器状态
RefreshStateEvent?.Invoke("内胆", false);
Thread.Sleep(1000 * 10);
break;
}
if (0 == stDevList.nDeviceNum)
{
// 刷新扫码器状态
RefreshStateEvent?.Invoke("内胆", false);
Thread.Sleep(1000 * 10);
break;
}
MvCodeReader.MV_CODEREADER_DEVICE_INFO stDevInfo; // 通用设备信息
Int32 nDevIndex = -1;
// ch:打印设备信息 | en:Print device info
for (Int32 i = 0; i < stDevList.nDeviceNum; i++)
{
stDevInfo = (MvCodeReader.MV_CODEREADER_DEVICE_INFO)Marshal.PtrToStructure(stDevList.pDeviceInfo[i], typeof(MvCodeReader.MV_CODEREADER_DEVICE_INFO));
if (MvCodeReader.MV_CODEREADER_GIGE_DEVICE == stDevInfo.nTLayerType)
{
MvCodeReader.MV_CODEREADER_GIGE_DEVICE_INFO stGigEDeviceInfo = (MvCodeReader.MV_CODEREADER_GIGE_DEVICE_INFO)MvCodeReader.ByteToStruct(stDevInfo.SpecialInfo.stGigEInfo, typeof(MvCodeReader.MV_CODEREADER_GIGE_DEVICE_INFO));
uint nIp1 = ((stGigEDeviceInfo.nCurrentIp & 0xff000000) >> 24);
uint nIp2 = ((stGigEDeviceInfo.nCurrentIp & 0x00ff0000) >> 16);
uint nIp3 = ((stGigEDeviceInfo.nCurrentIp & 0x0000ff00) >> 8);
uint nIp4 = (stGigEDeviceInfo.nCurrentIp & 0x000000ff);
string ip = ((stGigEDeviceInfo.nCurrentIp & 0xff000000) >> 24) + "." + ((stGigEDeviceInfo.nCurrentIp & 0x00ff0000) >> 16) + "." + ((stGigEDeviceInfo.nCurrentIp & 0x0000ff00) >> 8) + "." + (stGigEDeviceInfo.nCurrentIp & 0x000000ff);
string ipStr = nIp1 + "." + nIp2 + "." + nIp3 + "." + nIp4;
if (ipStr == LinerScannerIp)
{
Console.WriteLine("device IP :" + ipStr);
nDevIndex = i;
}
}
}
if (nDevIndex < 0)
{
Console.WriteLine("未找到内胆扫码器");
// 刷新扫码器状态
RefreshStateEvent?.Invoke("内胆", false);
Thread.Sleep(1000 * 30);
break;
}
stDevInfo = (MvCodeReader.MV_CODEREADER_DEVICE_INFO)Marshal.PtrToStructure(stDevList.pDeviceInfo[nDevIndex], typeof(MvCodeReader.MV_CODEREADER_DEVICE_INFO));
// ch:创建设备 | en:Create device
nRet = device.MV_CODEREADER_CreateHandle_NET(ref stDevInfo);
if (MvCodeReader.MV_CODEREADER_OK != nRet)
{
break;
}
// ch:打开设备 | en:Open device
nRet = device.MV_CODEREADER_OpenDevice_NET();
if (MvCodeReader.MV_CODEREADER_OK != nRet)
{
// 刷新扫码器状态
RefreshStateEvent?.Invoke("箱壳", false);
break;
}
// 刷新扫码器状态
RefreshStateEvent?.Invoke("内胆", true);
// ch:注册回调函数 | en:Register image callback
ImageCallback = new MvCodeReader.cbOutputEx2delegate(LinerImageCallbackFunc);
nRet = device.MV_CODEREADER_RegisterImageCallBackEx2_NET(ImageCallback, IntPtr.Zero);
if (MvCodeReader.MV_CODEREADER_OK != nRet)
{
break;
}
// ch:开启抓图 || en: start grab image
nRet = device.MV_CODEREADER_StartGrabbing_NET();
if (MvCodeReader.MV_CODEREADER_OK != nRet)
{
break;
}
while (true)
{
Thread.Sleep(1000 * 60);
DateTime dateTime = DateTime.Now;
TimeSpan timeSpan = dateTime.Subtract(LinerLiveTime);
if (timeSpan.TotalMinutes >= 10)
{
Console.WriteLine("内胆扫码器超时");
//CloseShell();
//Shell();
break;
}
}
//Console.ReadLine();
// ch:停止抓图 | en:Stop grabbing
nRet = device.MV_CODEREADER_StopGrabbing_NET();
if (MvCodeReader.MV_CODEREADER_OK != nRet)
{
break;
}
// ch:关闭设备 | en:Close device
nRet = device.MV_CODEREADER_CloseDevice_NET();
if (MvCodeReader.MV_CODEREADER_OK != nRet)
{
break;
}
// ch:销毁设备 | en:Destroy device
nRet = device.MV_CODEREADER_DestroyHandle_NET();
if (MvCodeReader.MV_CODEREADER_OK != nRet)
{
break;
}
}catch(Exception ex)
{
Console.WriteLine($"Liner扫码器异常:{ex.Message}");
}
} while (false);
Thread.Sleep(1000);
Liner();
}
public static async Task LinerRobot()
{
try
{
while (true)
{
// 枚举设备
MvCodeReader.MV_CODEREADER_DEVICE_INFO_LIST stDevList = new MvCodeReader.MV_CODEREADER_DEVICE_INFO_LIST();
var deviceList = await Task.Run(() => MvCodeReader.MV_CODEREADER_EnumDevices_NET(ref stDevList, MvCodeReader.MV_CODEREADER_GIGE_DEVICE));
if (stDevList.nDeviceNum == 0)
{
await Task.Delay(10000); // 10秒后重试
continue;
}
// 过滤设备
var linerDevice = stDevList.pDeviceInfo
.Select(ptr => (MvCodeReader.MV_CODEREADER_DEVICE_INFO)Marshal.PtrToStructure(ptr, typeof(MvCodeReader.MV_CODEREADER_DEVICE_INFO)))
.FirstOrDefault(info =>
{
if (info.nTLayerType != MvCodeReader.MV_CODEREADER_GIGE_DEVICE) return false;
var gigeDeviceInfo = (MvCodeReader.MV_CODEREADER_GIGE_DEVICE_INFO)MvCodeReader.ByteToStruct(info.SpecialInfo.stGigEInfo, typeof(MvCodeReader.MV_CODEREADER_GIGE_DEVICE_INFO));
return $"{(gigeDeviceInfo.nCurrentIp & 0xff000000) >> 24}.{(gigeDeviceInfo.nCurrentIp & 0x00ff0000) >> 16}.{(gigeDeviceInfo.nCurrentIp & 0x0000ff00) >> 8}.{gigeDeviceInfo.nCurrentIp & 0x000000ff}" == LinerScannerIp;
});
if (stDevList.nDeviceNum == 0)
{
Console.WriteLine("未找到内胆扫码器");
await Task.Delay(30000); // 30秒后重试
continue;
}
var device = new MvCodeReader();
// 创建设备
var handleResult = await Task.Run(() => device.MV_CODEREADER_CreateHandle_NET(ref linerDevice));
if (handleResult != MvCodeReader.MV_CODEREADER_OK)
continue;
// 打开设备
var openResult = await Task.Run(() => device.MV_CODEREADER_OpenDevice_NET());
if (openResult != MvCodeReader.MV_CODEREADER_OK)
{
RefreshStateEvent?.Invoke("箱壳", false);
continue;
}
// 注册回调函数
var imageCallback = new MvCodeReader.cbOutputEx2delegate(LinerImageCallbackFunc);
var registerResult = await Task.Run(() => device.MV_CODEREADER_RegisterImageCallBackEx2_NET(imageCallback, IntPtr.Zero));
if (registerResult != MvCodeReader.MV_CODEREADER_OK)
continue;
// 开启抓图
var startGrabbingResult = await Task.Run(() => device.MV_CODEREADER_StartGrabbing_NET());
if (startGrabbingResult != MvCodeReader.MV_CODEREADER_OK)
continue;
// 等待
while (true)
{
Thread.Sleep(1000 * 60);
DateTime dateTime = DateTime.Now;
TimeSpan timeSpan = dateTime.Subtract(LinerLiveTime);
if (timeSpan.TotalMinutes >= 10)
{
Console.WriteLine("内胆扫码器超时");
break;
}
}
// 停止抓图
var stopGrabbingResult = await Task.Run(() => device.MV_CODEREADER_StopGrabbing_NET());
if (stopGrabbingResult != MvCodeReader.MV_CODEREADER_OK)
continue;
// 关闭设备
var closeResult = await Task.Run(() => device.MV_CODEREADER_CloseDevice_NET());
if (closeResult != MvCodeReader.MV_CODEREADER_OK)
continue;
// 销毁设备
var destroyResult = await Task.Run(() => device.MV_CODEREADER_DestroyHandle_NET());
if (destroyResult != MvCodeReader.MV_CODEREADER_OK)
continue;
}
}
catch (Exception ex)
{
Console.WriteLine($"Liner扫码器异常:{ex.Message}");
}
}
#region 判断字符编码
/// <summary>
/// 判断字符编码
/// </summary>
/// <param name="inputStream"></param>
/// <returns></returns>
public static bool IsTextUTF8(byte[] inputStream)
{
int encodingBytesCount = 0;
bool allTextsAreASCIIChars = true;
for (int i = 0; i < inputStream.Length; i++)
{
byte current = inputStream[i];
if ((current & 0x80) == 0x80)
{
allTextsAreASCIIChars = false;
}
// First byte
if (encodingBytesCount == 0)
{
if ((current & 0x80) == 0)
{
// ASCII chars, from 0x00-0x7F
continue;
}
if ((current & 0xC0) == 0xC0)
{
encodingBytesCount = 1;
current <<= 2;
// More than two bytes used to encoding a unicode char.
// Calculate the real length.
while ((current & 0x80) == 0x80)
{
current <<= 1;
encodingBytesCount++;
}
}
else
{
// Invalid bits structure for UTF8 encoding rule.
return false;
}
}
else
{
// Following bytes, must start with 10.
if ((current & 0xC0) == 0x80)
{
encodingBytesCount--;
}
else
{
// Invalid bits structure for UTF8 encoding rule.
return false;
}
}
}
if (encodingBytesCount != 0)
{
// Invalid bits structure for UTF8 encoding rule.
// Wrong following bytes count.
return false;
}
// Although UTF8 supports encoding for ASCII chars, we regard as a input stream, whose contents are all ASCII as default encoding.
return !allTextsAreASCIIChars;
}
#endregion
}
}