title: Convert text to Latin encoding and decode back problem for Vietnamese
body: <p>I'm trying to convert Vietnamese to Latin. It is a requirement to send the byte to ESC/P printer (see <a href="https://stackoverflow.com/questions/52715099/c-sharp-esc-pos-print-vietnamese">C# ESC/POS Print Vietnamese</a> for reason why).</p>
  
  <p>But my question is very simple, look at this code:</p>
  
  <pre><code>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"
  </code></pre>
  
  <p>Why is the <code>origStr</code> becomes <code>Cơm chiên v?i các lo?i gia v? truy?n</code> instead of contain the same content with <code>content</code>? But, it <strong>works</strong> fine in Chinese or Thai. You can test the code below...</p>
  
  <p>For Chinese Simplified</p>
  
  <pre><code>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 "印尼炒饭"
  </code></pre>
  
  <p>For Thai</p>
  
  <pre><code>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 "ข้าวผัดอินโดนีเซียกับเครื่องเทศแบบดั้ง"
  </code></pre>
  
  <p>Any idea why? Why Vietnamese won't work? How to make it work so I can send it to Printer?</p>
  
  <p>Thanks for any help :)</p>
  
  <p>PS.
  Here is the code I used to send to printer</p>
  
  <pre><code>[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;
  }
  </code></pre>