c# - 打印二维码“GS(k“通过“PrintNormal”超过 124 个字节?
问题描述
我有一台 Epson TM-T88VI 打印机并使用 C# 中的 Microsoft.PointOfService.PosPrinter 进行打印。
我尝试通过 ESC POS 命令打印二维码。
一切正常,直到打印 125+ 字节的 QR 码数据。
这是我的功能:
private string fct180(string data)
{
byte[] barr = System.Text.ASCIIEncoding.ASCII.GetBytes(data);
int len = barr.Length + 3;
byte pH = (byte)(len / 256);
byte pL = (byte)(len - (256 * pH));
byte[] cmd = new byte[8 + barr.Length];
cmd[0] = 29;
cmd[1] = 40;
cmd[2] = 107;
cmd[3] = pL;
cmd[4] = pH;
cmd[5] = 49;
cmd[6] = 80;
cmd[7] = 48;
Array.Copy(barr, 0, cmd, 8, barr.Length);
string testing = System.Text.ASCIIEncoding.ASCII.GetString(cmd);
byte[] rere = System.Text.ASCIIEncoding.ASCII.GetBytes(testing);
string ret = System.Text.ASCIIEncoding.ASCII.GetString(cmd);
return ret;
}
我的情况:
1)起初我尝试生成内容字符串长度为124的二维码:
data
是"AASDFASDFASDFADSFADSFASDFADSFADSFADSFADSFADSFADSFADSFADSFADSFKLJADSJKLFADSJKLFADSJKLFDJKLFDSJKLFADSJLFDSJLKFDJLSKFDJKLSFADXX"
此二维码打印正确(pL 为 127,pH 为 0),pL 编码为“\u007f”:
"\u001d(k\u007f\01P0AASDFASDFASDFADSFADSFASDFADSFADSFADSFADSFADSFADSFADSFADSFADSFKLJADSJKLFADSJKLFADSJKLFDJKLFDSJKLFADSJLFDSJLKFDJLSKFDJKLSFADXX"
值为rere[3]:
127,值为rere[4]
= 0
2)然后我尝试生成一个字符串长度为125的二维码:
data
是"AASDFASDFASDFADSFADSFASDFADSFADSFADSFADSFADSFADSFADSFADSFADSFKLJADSJKLFADSJKLFADSJKLFDJKLFDSJKLFADSJLFDSJLKFDJLSKFDJKLSFADXXT"
此二维码不打印(pL 为 128,pH 为 0),pL 编码为“?” 其字节值为 63:
"\u001d(k?\01P0AASDFASDFASDFADSFADSFASDFADSFADSFADSFADSFADSFADSFADSFADSFADSFKLJADSJKLFADSJKLFADSJKLFDJKLFDSJKLFADSJLFDSJLKFDJLSKFDJKLSFADXXT"
值rere[3]:
63,值rere[4]
= 0
我想一个接一个地获取两个条形码,但我只将第二个二维码内容的一个和一部分作为纯字符串文本。如您在此处看到 的:图为1)的QR码和2)的文字部分
前 63 个字符被擦除,字符 64+ 被打印为普通文本。好的,那是因为字节值是63而不是128。但是为什么QR码没有打印63 char?
那是因为字节值 128 被编码为字符串字符“?”。但是,如果我不能保留字节值 > 127 的字符串,如何使用 Microsoft.PointOfService.PosPrinter.PrintNormal 打印我的 QR 码?
PosPrinter 类中是否有其他函数调用可以接受纯字节数组?我还没有找到一个。
除了 PosPrinter.PrintBarcode 还有其他解决方案吗?
你有什么建议?
编辑:解决方案 我使用了字节数组,然后将每个单字节(通过字符)转换为字符串。该字符串使用纯字节值而不是编码。然后我使用转义序列“ESC|[*]#E”。然后在 PrintNormal 中使用它。这会将字符串直接定向到打印机,而不会在两者之间进行处理。现在也可以处理大于 127 的字节值。
string ESC = System.Text.ASCIIEncoding.ASCII.GetString(new byte[] { 27 });
byte[] bqr = ...;
string data = "";
for (int i = 0; i < bqr.Length; ++i)
{
data += (char)bqr[i];
}
string cmd = ESC + "|*" + data.Length + "E" + data;
printer.PrintNormal(PrinterStation.Receipt, cmd)
解决方案
这涉及到很多并发症。
首先,我回答了上一个问题,如果您使用的是 POS for.NET(包括 OPOS/JavaPOS),请不要直接使用该PrintNormal
方法发送打印机的 ESC/POS 控制命令。
如果您想打印二维码,可能有PrintBarcode
方法支持,请查看EPSON的ADK文档,如果在ADK文档中找不到,请联系EPSON客服。
可以根据 UnifiedPOS 规范为打印机发送 ESC/POS 控制命令。
称为“通过嵌入数据的路径”(ESC|[*]#E) 的 UnifiedPOS POSPrinter 转义序列会将 # 中指定的数据字节直接发送到打印机。
但是,假定服务对象支持该功能。请查阅您的 ADK 文档或支持联系人以获取支持可用性。
接下来,这取决于您是使用 POS for.NET 本机服务对象还是通过 COM Interop 使用 OPOS 服务对象。
使用 OPOS 服务对象时,从 Unicode 到 ANSI 代码页的转换由 OLE 运行时函数在方法调用期间自动完成,大于 127 的字符代码可以由系统代码页更改。另外,如果数据中间有一个 0x00,它将在那里终止,其余数据将被忽略。
这是因为该PrintNormal
方法的参数是字符串,而不是字节数组。
服务对象的ILegacyControlObject.BinaryConversion 属性可以更改为 Nibble 或 Decimal,而不是默认值 None。
但是,根据 POS for .NET 的 COM Interop 的实现情况,可能需要注意,因此最好联系支持人员了解如何使用它。
如果您在 POS for.NET 中使用本机服务对象,则取决于它的实现方式。同样,请查看您的 ADK 文档或联系支持台以获取更多信息。
推荐阅读
- sql - impala shell 输出带有附件的 csv 文件生成
- django - 在 django + vue 应用程序中使用 axios 时出错
- java - Gradle Kotlin DSL:找不到或加载主类
- android - Android Room - 每个应用程序一个或多个实例?
- sql - 组匹配值并查找哪些缺少相关值?
- java - 是否可以选择底部导航项的圆形背景?
- flask-admin - Flask-Admin 在提交表单时发送电子邮件
- jmeter - Blazemeter 因 jmx 文件而崩溃
- azure-devops - Azure DevOps 查询依赖项
- java - 检查属性是否等于字符串值列表