通过"PrintNormal"打印大于124字节的二维码"GS ( k <Function 180>"?
Print QR code "GS ( k <Function 180>" with more than 124 bytes via "PrintNormal"?
我有一台 Epson TM-T88VI 打印机,使用 C# 中的 Microsoft.PointOfService.PosPrinter 进行打印。
我尝试通过 ESC POS 命令打印二维码。
一切正常,直到打印出 125+ 字节的二维码数据。
这是我的功能:
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\u007fP0AASDFASDFASDFADSFADSFASDFADSFADSFADSFADSFADSFADSFADSFADSFADSFKLJADSJKLFADSJKLFADSJKLFDJKLFDSJKLFADSJLFDSJLKFDJLSKFDJKLSFADXX"
rere[3]:
的值 127,rere[4]
的值 = 0
2)
然后我尝试生成一个字符串长度为125的二维码:
data
是 "AASDFASDFASDFADSFADSFASDFADSFADSFADSFADSFADSFADSFADSFADSFADSFKLJADSJKLFADSJKLFADSJKLFDJKLFDSJKLFADSJLFDSJLKFDJLSKFDJKLSFADXXT"
此二维码未打印(pL为128,pH为0),pL编码为“?”其字节值为 63:
"\u001d(k?P0AASDFASDFASDFADSFADSFASDFADSFADSFADSFADSFADSFADSFADSFADSFADSFKLJADSJKLFADSJKLFADSJKLFDJKLFDSJKLFADSJLFDSJLKFDJLSKFDJKLSFADXXT"
rere[3]:
的值 63,rere[4]
的值 = 0
我想依次获取两个二维码,但我只获取了一个和第二个二维码的部分内容为纯字符串文本。正如你在这里看到的:
图为1)的二维码和2)的文字部分
前 63 个字符被擦除,字符 64+ 打印为普通文本。
好的,那是因为字节值是63而不是128。但是为什么二维码不是打印63个字符?
这是因为字节值 128 被编码为字符串字符“?”。
但是,如果我不能保留字节值大于 127 的字符串,我如何使用 Microsoft.PointOfService.PosPrinter.PrintNormal 打印我的 QR 码?
PosPrinter class 中是否有接受纯字节数组的替代函数调用?我还没找到。
除了PosPrinter.PrintBarcode还有其他解决办法吗?
你有什么建议?
编辑:解决方案
我使用了字节数组,然后将每个字节(通过 char)转换为字符串。
该字符串使用纯字节值而不是编码。然后我使用转义序列"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)
这涉及到很多复杂的问题。
首先,我回答过上一个问题,如果你使用的是POSfor.NET(包括OPOS/JavaPOS),不要直接用PrintNormal
方法。
如果要打印二维码,PrintBarcode
方法可能支持,请查看EPSON的ADK文档,如果在ADK文档中找不到,请联系EPSON支持台。
可以根据 UnifiedPOS 规范为打印机发送 ESC/POS 控制命令。
名为 "Path through embedded data" (ESC|[*]#E) 的 UnifiedPOS POSPrinter 转义序列会将 # 中指定的数据字节直接发送到打印机。
但是,假定服务对象支持该功能。请查看您的 ADK 文档或支持联系人以了解支持可用性。
接下来,这取决于您是使用 POS for.NET 本机服务对象还是通过 COM Interop 使用 OPOS 服务对象。
使用 OPOS 服务对象时,从 Unicode 到 ANSI 代码页的转换由 OLE 运行时函数在方法调用期间自动完成,大于 127 的字符代码可以通过系统代码页更改。此外,如果数据中间有一个 0x00,它将在那里终止,其余数据将被忽略。
这是因为PrintNormal
方法的参数是字符串,不是字节数组。
服务对象的ILegacyControlObject.BinaryConversion property可以改为Nibble或Decimal,而不是默认值None。
但是,根据 POS for.NET 的 COM Interop 的实现,可能需要注意,因此最好联系支持台了解如何使用它。
如果您在 POS for.NET 中使用本机服务对象,则取决于它的实现方式。同样,请查看您的 ADK 文档或联系支持台以获取更多信息。
我遇到了同样的问题,但用不同的方式解决了它
问题在于使用字符串,我们使用 SerialPort.Write() 将数据发送到打印机。
它有这个有趣的条款
默认情况下,SerialPort 使用 ASCIIEncoding 对字符进行编码。 ASCIIEncoding 将所有大于 127 的字符编码为 (char)63 或 '?'。要支持该范围内的其他字符,请将编码设置为 UTF8Encoding、UTF32Encoding 或 UnicodeEncoding。
所以我们:
已将所有数据恢复为字节。
将 SerialPort 设置为 UTF-8 编码。
并直接发送字节。
我们现在可以打印高达 7000 位的二维码
我有一台 Epson TM-T88VI 打印机,使用 C# 中的 Microsoft.PointOfService.PosPrinter 进行打印。
我尝试通过 ESC POS 命令打印二维码。
一切正常,直到打印出 125+ 字节的二维码数据。
这是我的功能:
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\u007fP0AASDFASDFASDFADSFADSFASDFADSFADSFADSFADSFADSFADSFADSFADSFADSFKLJADSJKLFADSJKLFADSJKLFDJKLFDSJKLFADSJLFDSJLKFDJLSKFDJKLSFADXX"
rere[3]:
的值 127,rere[4]
的值 = 0
2)
然后我尝试生成一个字符串长度为125的二维码:
data
是 "AASDFASDFASDFADSFADSFASDFADSFADSFADSFADSFADSFADSFADSFADSFADSFKLJADSJKLFADSJKLFADSJKLFDJKLFDSJKLFADSJLFDSJLKFDJLSKFDJKLSFADXXT"
此二维码未打印(pL为128,pH为0),pL编码为“?”其字节值为 63:
"\u001d(k?P0AASDFASDFASDFADSFADSFASDFADSFADSFADSFADSFADSFADSFADSFADSFADSFKLJADSJKLFADSJKLFADSJKLFDJKLFDSJKLFADSJLFDSJLKFDJLSKFDJKLSFADXXT"
rere[3]:
的值 63,rere[4]
的值 = 0
我想依次获取两个二维码,但我只获取了一个和第二个二维码的部分内容为纯字符串文本。正如你在这里看到的:
前 63 个字符被擦除,字符 64+ 打印为普通文本。 好的,那是因为字节值是63而不是128。但是为什么二维码不是打印63个字符?
这是因为字节值 128 被编码为字符串字符“?”。 但是,如果我不能保留字节值大于 127 的字符串,我如何使用 Microsoft.PointOfService.PosPrinter.PrintNormal 打印我的 QR 码?
PosPrinter class 中是否有接受纯字节数组的替代函数调用?我还没找到。
除了PosPrinter.PrintBarcode还有其他解决办法吗?
你有什么建议?
编辑:解决方案 我使用了字节数组,然后将每个字节(通过 char)转换为字符串。 该字符串使用纯字节值而不是编码。然后我使用转义序列"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)
这涉及到很多复杂的问题。
首先,我回答过上一个问题,如果你使用的是POSfor.NET(包括OPOS/JavaPOS),不要直接用PrintNormal
方法。
如果要打印二维码,PrintBarcode
方法可能支持,请查看EPSON的ADK文档,如果在ADK文档中找不到,请联系EPSON支持台。
可以根据 UnifiedPOS 规范为打印机发送 ESC/POS 控制命令。
名为 "Path through embedded data" (ESC|[*]#E) 的 UnifiedPOS POSPrinter 转义序列会将 # 中指定的数据字节直接发送到打印机。
但是,假定服务对象支持该功能。请查看您的 ADK 文档或支持联系人以了解支持可用性。
接下来,这取决于您是使用 POS for.NET 本机服务对象还是通过 COM Interop 使用 OPOS 服务对象。
使用 OPOS 服务对象时,从 Unicode 到 ANSI 代码页的转换由 OLE 运行时函数在方法调用期间自动完成,大于 127 的字符代码可以通过系统代码页更改。此外,如果数据中间有一个 0x00,它将在那里终止,其余数据将被忽略。
这是因为PrintNormal
方法的参数是字符串,不是字节数组。
ILegacyControlObject.BinaryConversion property可以改为Nibble或Decimal,而不是默认值None。
但是,根据 POS for.NET 的 COM Interop 的实现,可能需要注意,因此最好联系支持台了解如何使用它。
如果您在 POS for.NET 中使用本机服务对象,则取决于它的实现方式。同样,请查看您的 ADK 文档或联系支持台以获取更多信息。
我遇到了同样的问题,但用不同的方式解决了它
问题在于使用字符串,我们使用 SerialPort.Write() 将数据发送到打印机。
它有这个有趣的条款
默认情况下,SerialPort 使用 ASCIIEncoding 对字符进行编码。 ASCIIEncoding 将所有大于 127 的字符编码为 (char)63 或 '?'。要支持该范围内的其他字符,请将编码设置为 UTF8Encoding、UTF32Encoding 或 UnicodeEncoding。
所以我们:
已将所有数据恢复为字节。
将 SerialPort 设置为 UTF-8 编码。
并直接发送字节。
我们现在可以打印高达 7000 位的二维码