C# ESC/POS 打印越南语
Posted
技术标签:
【中文标题】C# ESC/POS 打印越南语【英文标题】:C# ESC/POS Print Vietnamese 【发布时间】:2019-03-13 21:10:13 【问题描述】:我有一个使用 ESC/POS 将收据打印到收据打印机的应用程序。它需要支持多语言。目前,我已经用中文(繁体和简体)和泰文进行了测试。他们都工作正常。
但是,当我尝试打印越南语时,一些字符被替换为“?”。
这是我的代码:
public static readonly string ESC = "\u001B";
...
...
...
Encoding enc = Encoding.GetEncoding(1258); //vietnamese code page
string content = "Cơm chiên với các loại gia vị truyền thống làm cho lưỡi của bạn";
string toPrint = ESC + "t" + char.ConvertFromUtf32(94) + "\n" + Encoding.GetEncoding("Latin1").GetString(enc.GetBytes(str)); //code page 94 is for vietnamese (WPC1258). It is get from printer
在打印输出中,某些字符已被替换为“?” (见附图)。有什么想法吗?
更新
根据 Panagiotis Kanavos 的评论,我尝试了以下方法:
Encoding enc = Encoding.GetEncoding(1258); //vietnamese code page
string content = "Cơm chiên với các loại gia vị truyền thống làm cho lưỡi của bạn";
string newStr = Encoding.GetEncoding("Latin1").GetString(enc.GetBytes(content));
string origStr = enc.GetString(Encoding.GetEncoding("Latin1").GetBytes(newStr));
origStr 包含?
。我用中文和泰文确认, origStr 将等于内容。但对于越南语来说NOT。有什么想法吗?
更新 2
我决定使用 Panagiotis Kanavos 代码 bytesToPrint = enc.GetBytes("\x1Bt\x5E\n" + content);
,但它给了我完全相同的结果,其中包含 ?
而不是实际字符。
这就是我将内容(字符串或字节)发送到打印机的方式。
[DllImport("Winspool.drv", EntryPoint = "ClosePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
public static extern bool ClosePrinter(IntPtr hPrinter);
[DllImport("Winspool.drv", EntryPoint = "EndDocPrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
public static extern bool EndDocPrinter(IntPtr hPrinter);
[DllImport("Winspool.drv", EntryPoint = "EndPagePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
public static extern bool EndPagePrinter(IntPtr hPrinter);
[DllImport("Winspool.drv", EntryPoint = "OpenPrinterA", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
public static extern bool OpenPrinter([MarshalAs(UnmanagedType.LPStr)] string szPrinter, out IntPtr hPrinter, IntPtr pd);
[DllImport("Winspool.drv", EntryPoint = "StartDocPrinterA", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
public static extern bool StartDocPrinter(IntPtr hPrinter, Int32 level, [In, MarshalAs(UnmanagedType.LPStruct)] DOCINFOA di);
[DllImport("Winspool.drv", EntryPoint = "StartPagePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
public static extern bool StartPagePrinter(IntPtr hPrinter);
[DllImport("Winspool.drv", EntryPoint = "WritePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
public static extern bool WritePrinter(IntPtr hPrinter, IntPtr pBytes, Int32 dwCount, out Int32 dwWritten);
public static bool SendBytesToPrinter(string printerName, IntPtr pBytes, int dwCount, string docName = null, string dataType = "RAW")
DOCINFOA di = new DOCINFOA();
di.pDocName = string.IsNullOrWhiteSpace(docName) ? string.Empty : docName;
di.pDataType = string.IsNullOrWhiteSpace(dataType) ? "RAW" : dataType;
IntPtr hPrinter = new IntPtr(0); int dwError = 0, dwWritten = 0; bool bSuccess = false;
if (OpenPrinter(printerName.Normalize(), out hPrinter, IntPtr.Zero))
if (StartDocPrinter(hPrinter, 1, di))
if (StartPagePrinter(hPrinter))
bSuccess = WritePrinter(hPrinter, pBytes, dwCount, out dwWritten);
EndPagePrinter(hPrinter);
EndDocPrinter(hPrinter);
ClosePrinter(hPrinter);
if (bSuccess == false)
dwError = Marshal.GetLastWin32Error();
return bSuccess;
public static bool SendBytesToPrinter(string printerName, byte[] bytes, string docName)
int dwCount = bytes.Length;
IntPtr ptrBytes = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(byte)) * bytes.Length);
try
Marshal.Copy(bytes, 0, ptrBytes, bytes.Length);
SendBytesToPrinter(printerName, ptrBytes, dwCount, docName);
finally Marshal.FreeCoTaskMem(ptrBytes);
return true;
public static bool SendStringToPrinter(string printerName, string str, string docName)
int dwCount = str.Length;
IntPtr ptrBytes = Marshal.StringToCoTaskMemAnsi(str);
try SendBytesToPrinter(printerName, ptrBytes, dwCount, docName);
finally Marshal.FreeCoTaskMem(ptrBytes);
return true;
【问题讨论】:
您能否发布足够的代码以便有人可以重现该问题? ***.com/help/mcve 您好 Dipen,如果您将string toPrint
发送到 ESC 打印机,您将看到结果。
代码本身在使用`Encoding.GetEncoding("Latin1").GetString(enc.GetBytes(str));. Vietnamese is *not* Latin1 and any character that can't be converted to Latin1 is replaced by
?. The
content` string 已经是一个 Unicode 字符串。 .NET 已经使用 UTF16。 POS 是否支持 Unicode?是否配置为使用特定 代码页,例如Latin1、越南语或UTF8? 如何将字符串发送到 POS?
.NET 的编写器类(如 StreamWriter)默认使用 UTF8。如果您使用编写器写入 POS,它应该可以正常工作,无需代码页转换。如果您复制一个字节数组,您必须 找出配置的代码页。最好的选择是将设备配置为使用 UTF8,并使用 Encoding.UTF8.GetBytes()
only 来获取正确的字节。在任何其他情况下,您需要创建一个 Encoding 对象,例如使用Encoding.GetEncoding(1258)
并使用它的GetBytes()
方法only,以获取正确的字节。但是,您将丢失任何无法转换为该代码页的字符
@PanagiotisKanavos,不幸的是,对于 ESC/P 打印,这就是它的工作方式。在将其发送到 ESC/P 之前,您必须将其转换回拉丁语。然后它将与所选打印机的代码页(打印机初始化时选择的代码页)匹配。目前,该代码适用于中文/日文/泰文。
【参考方案1】:
这就是使用 C# 在打印输出上正确打印越南字符所需的全部内容
编辑你的代码
public static readonly string ESC = "\u001B";
...
...
...
//Encoding enc = Encoding.GetEncoding(1258); //vietnamese code page
string content = "Cơm chiên với các loại gia vị truyền thống làm cho lưỡi của bạn";
string toPrint = ESC + "t" + char.ConvertFromUtf32(94) + "\n";
// First you need to convert the vietnamese string to utf-8 bytes.
byte[] utf8Bytes = System.Text.Encoding.UTF8.GetBytes(content);
// Convert utf-8 bytes to a string.
toPrint += System.Text.Encoding.UTF8.GetString(utf8Bytes);
试试上面的代码,如果你仍然得到有趣的字符,请告诉我......
【讨论】:
嗨 Indago,它不起作用 :( 事实上,它更糟糕。现在,其他语言不再起作用。中文不再起作用,泰语也不起作用。你必须使用适当的编码. 越南语是1258。你最后上班了吗? C#(和 Windows)使用 UTF16,这就是为什么content
可以首先编译的原因。它是 Unicode。没有理由使用UTF8.GetBytes
。如果 POS 不支持 UTF16 或 UTF8,则必须对其进行配置
顺便说一句,没有如果或但关于这个。 SO 是一个 .NET 应用程序,这就是为什么它可以显示任何字符,包括这个问题中的越南语文本,而无需特殊处理
@PanagiotisKanavos .NET 可以正常显示字符...就在打印出来的时候...在中文、日文和泰文上都可以正常工作...只是在越南文上不行【参考方案2】:
我找到了答案!这不是我的代码,而是 CodePage 1258 的限制(参见Convert text to Latin encoding and decode back problem for Vietnamese)。
问题仍然存在,如何用越南语打印?
有一个叫 HICURIN 的人设法解决了这个问题(参见 Print Unicode Characters to POS printer)。希望他能与我们分享他的代码。
干杯, 山姆
【讨论】:
以上是关于C# ESC/POS 打印越南语的主要内容,如果未能解决你的问题,请参考以下文章
求助关于Qt5打印使用ESC/POS指令集,一直没弄明白,求示例
如何在 Linux 中向热敏打印机发送 ESC/POS 命令