C# 将文本转换为拉丁语编码并解码回越南语问题

C# 将文本转换为拉丁语编码并解码回越南语问题,c#,encoding,character-encoding,codepages,C#,Encoding,Character Encoding,Codepages,我想把越南语转换成拉丁语。要求将字节发送到ESC/P打印机(请参阅以了解原因) 但我的问题很简单,看看下面的代码: Encoding enc = Encoding.GetEncoding(1258); //vietnamese code page string content = "Cơm chiên với các loại gia vị truyền"; string newStr = Encoding.GetEncoding("Latin1").GetString(enc.GetBytes

我想把越南语转换成拉丁语。要求将字节发送到ESC/P打印机(请参阅以了解原因)

但我的问题很简单,看看下面的代码:

Encoding enc = Encoding.GetEncoding(1258); //vietnamese code page
string content = "Cơm chiên với các loại gia vị truyền";
string newStr = Encoding.GetEncoding("Latin1").GetString(enc.GetBytes(content));
string origStr = enc.GetString(Encoding.GetEncoding("Latin1").GetBytes(newStr)); //origStr is becomes "Cơm chiên v?i các lo?i gia v? truy?n"
为什么
origStr
变成
Cơm chin v?i CáC lo?i gia v?truy?n
而不是包含与
内容
相同的内容?但是,它在中文或泰语中工作得很好。您可以测试下面的代码

简体中文

Encoding enc = Encoding.GetEncoding(936); //chinese simplified code page
string content = "印尼炒饭";
string newStr = Encoding.GetEncoding("Latin1").GetString(enc.GetBytes(content));
string origStr = enc.GetString(Encoding.GetEncoding("Latin1").GetBytes(newStr)); //origStr is correct "印尼炒饭"
泰语

Encoding enc = Encoding.GetEncoding(874); //Thai code page
string content = "ข้าวผัดอินโดนีเซียกับเครื่องเทศแบบดั้ง";
string newStr = Encoding.GetEncoding("Latin1").GetString(enc.GetBytes(content));
string origStr = enc.GetString(Encoding.GetEncoding("Latin1").GetBytes(newStr)); //origStr is correct "ข้าวผัดอินโดนีเซียกับเครื่องเทศแบบดั้ง"
知道为什么吗?为什么越南语行不通?如何使其工作,以便我可以将其发送到打印机

谢谢你的帮助:)

附言。 这是我用来发送到打印机的代码

[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;
}

通常,当您向编码器提供代码页中不存在的数据时,会发生这种情况

因此,如果您尝试转换字节值大于255(在中不存在)的字符,您将得到回退,即本例中的
字符。我的猜测是,在第一种情况下,输入字符串中有无效数据(可能是看起来相同但不正确的字符)


我的下一步将是检查字符及其对应的字节值。

通常在向编码器提供代码页中不存在的数据时会发生这种情况。因此,如果您尝试转换字节值大于255(代码页1258中不存在)的字符,您将得到回退,即本例中的
字符。所以我猜测,在第一种情况下,输入字符串中有无效数据(可能是看起来相同但不正确的字符)。我的下一步是检查字符及其对应的字节值。然后看看,你不会找到
char。如果您对来回转换非常感兴趣,那么请取消阅读
Encoding enc=Encoding.GetEncoding(1258)
use
Encoding enc=Encoding.GetEncoding(1200)这是UTF16。@MarkusSafar和SergeyShevchenko,你们都是对的。请张贴您的答案,我将接受。@Sam非常荣幸,谢谢;-)