2011-02-25 55 views
6

Theo Spolsky tôi không thể gọi mình là một nhà phát triển, vì vậy có rất nhiều xấu hổ đằng sau câu hỏi này ...Tôi cần trợ giúp chuyển đổi chuỗi C# từ mã hóa ký tự này sang mã hóa ký tự khác?

Kịch bản: Từ một ứng dụng C#, tôi muốn để có một giá trị chuỗi từ một SQL db và sử dụng nó như tên của một thư mục. Tôi có một máy chủ FTP an toàn (SSL) mà tôi muốn đặt thư mục hiện tại bằng cách sử dụng giá trị chuỗi từ DB.
Vấn đề: Mọi thứ đều hoạt động tốt cho đến khi tôi nhấn giá trị chuỗi với ký tự "đặc biệt" - dường như tôi không thể mã hóa tên thư mục chính xác để đáp ứng máy chủ FTP.

Đoạn mã ví dụ dưới đây

  • sử dụng nhân vật "đặc biệt" é là một ví dụ
  • sử dụng WinSCP như một ứng dụng bên ngoài cho FTPS comms
  • không hiển thị tất cả các mã cần thiết để thiết lập các quy trình "_winscp".
  • gửi lệnh tới exe WinSCP bằng cách viết cho quá trình standardinput
  • để đơn giản, không nhận thông tin từ DB, mà thay vào đó chỉ cần khai báo một chuỗi (nhưng tôi đã thực hiện một .Equals để xác nhận rằng giá trị từ DB giống như chuỗi đã khai báo)
  • thực hiện ba lần thử đặt thư mục hiện tại trên máy chủ FTP bằng cách sử dụng mã hóa chuỗi khác nhau - tất cả đều không thành công
  • cố gắng đặt thư mục bằng chuỗi đã được tạo từ mảng byte được tạo thủ công - hoạt động

Process _winscp = new Process(); 
byte[] buffer; 

string nameFromString = "Sinéad O'Connor"; 
_winscp.StandardInput.WriteLine("cd \"" + nameFromString + "\""); 

buffer = Encoding.UTF8.GetBytes(nameFromString); 
_winscp.StandardInput.WriteLine("cd \"" + Encoding.UTF8.GetString(buffer) + "\""); 

buffer = Encoding.ASCII.GetBytes(nameFromString); 
_winscp.StandardInput.WriteLine("cd \"" + Encoding.ASCII.GetString(buffer) + "\""); 

byte[] nameFromBytes = new byte[] { 83, 105, 110, 130, 97, 100, 32, 79, 39, 67, 111, 110, 110, 111, 114 }; 
_winscp.StandardInput.WriteLine("cd \"" + Encoding.Default.GetString(nameFromBytes) + "\""); 

Thay đổi mã UTF8 é thành 101 (thập phân) nhưng máy chủ FTP không thích nó.

Thay đổi mã ASCII é thành 63 (thập phân) nhưng máy chủ FTP không thích nó.

Khi tôi đại diện cho é là giá trị 130 (thập phân), máy chủ FTP rất vui, ngoại trừ tôi không thể tìm ra phương thức sẽ thực hiện điều này cho tôi (tôi phải tự tạo chuỗi từ byte rõ ràng).

Bất cứ ai cũng biết tôi nên làm gì để chuỗi mã hóa là 130 và làm cho máy chủ FTP vui vẻ và cuối cùng nâng tôi lên nhà phát triển cấp 1 bằng cách giải thích điều duy nhất mà nhà phát triển nên hiểu?

+2

Quá trình winscp đó là một phần của sự cố, đó là ứng dụng chế độ bảng điều khiển hoạt động trong trang mã 437, mã hóa IBM PC cũ. Trường hợp 130 thực sự là mã ký tự cho é. Dòng StandardInput thường tự động xử lý bản dịch nhưng mã của bạn rất lạ. Nó không thể làm việc như được đưa ra trong đoạn mã, quá trình này phải được bắt đầu trước tiên. Thua winscp, sử dụng System.Net với sự hỗ trợ của nó cho FTP. –

+0

Cảm ơn thông tin Hans. Tôi nhận ra các đoạn mã không hoạt động như (tôi cắt ra tất cả các mã quá trình khởi tạo). Tôi rất thích sử dụng một số hỗ trợ FTP .net gốc - nhưng nó có thể hỗ trợ FTP qua SSL (ví dụ: ftps) không? – Handleman

+0

Chỉ để hoàn thành cho các nhà phát triển trong tương lai - tôi lấy đề nghị của Hans và xem các thư viện FTP .net và chúng có thể xử lý ftps - vì vậy tôi đã nhanh chóng chuyển mã và bây giờ không còn dựa vào ứng dụng WinSCP bên ngoài nữa. không có vấn đề với mã hóa - nó chỉ hoạt động. Rất vui khi không có ứng dụng bên ngoài., Mã đơn giản hơn nhiều và hiệu suất tốt hơn. – Handleman

Trả lời

4

130 không phải là ASCII (ASCII chỉ là 7bits - xem tài liệu Encoding.ASCII - vì vậy nó đặt "é" vào bình thường "?"Bởi vì nó không có gì tốt hơn để làm) UTF-8 là thực sự mã hóa các ký tự vào hai byte (thập phân:. 195 & 169) nhưng bảo mã điểm

Sử dụng mã-page một cách rõ ràng, chẳng hạn như. Latin (CP 1252) - cần phải khớp với bất kỳ bên nào khác, như từ bên dưới, không có "130" ở đầu ra nên ... không phải mã hóa bạn cần :-) Nhưng điều tương tự cũng áp dụng: sử dụng mã hóa cho một trang mã cụ thể .

Sửa: Như Hans passant giải thích trong một chú thích, mã trang để sử dụng ở đây là MS-DOS (CP 437) đó sẽ dẫn đến kết quả mong muốn

.
// LINQPad -- Encoding is System.Text.Encoding 
var enc = Encoding.GetEncoding(1252); 
string.Join(" ", enc.GetBytes("Sinéad O'Connor")).Dump(); 
// -> 83 105 110 233 97 100 32 79 39 67 111 110 110 111 114 

Xem: http://msdn.microsoft.com/en-us/goglobal/bb688114 để biết thêm.

Mã hóa vui vẻ.

Btw. lựa chọn tốt trong nghệ sĩ - nếu nó là cố ý: p

+0

Cảm ơn pst và kudo đến Hans. Đối với những người quan tâm đến mã của tôi bây giờ trông giống như: string nameFromString = "Sinéad O'Connor"; byte [] buffer = Encoding.GetEncoding (437) .GetBytes (nameFromString); _winscp.StandardInput.WriteLine ("cd \" "+ Encoding.Default.GetString (buffer) +" \ ""); – Handleman

1

Tôi nghĩ rằng vấn đề ở đây là chuỗi TẤT CẢ. NET bằng Unicode. Không có "mã hóa tôi" trong các chuỗi .NET. Vì vậy, sử dụng Encoding.ASCII.GetString(buffer) bạn chuyển đổi "chuỗi" của bạn trong ASCII trở lại thành Unicode.

Tôi nghĩ rằng vấn đề của bạn nên được giải quyết bằng cách thay đổi mã hóa cho Process.StandardInput, vì vậy bạn có được mã hóa chính xác bên trong WinSCP.

HOẶC

Bạn nên kiểm tra Encoding.Default là gì, bởi vì tôi là khá chắc chắn nó không phải là UTF8 hoặc ASCII.

+0

Cảm ơn Euphoric. Tôi đã tìm thấy một cách để thiết lập mã hóa Process.StandardInput, và tôi chỉ thử UTF8, nhưng nó dường như không giúp đỡ (ở nhà bây giờ không có mã, sẽ đưa nó lên vào thứ hai). Tôi không quá lo lắng về việc mã hóa mặc định vì nó chỉ là một cách để có được phiên bản mảng byte của tôi thành một chuỗi để kiểm tra. – Handleman

+0

@pst: Tôi không có nghĩa là chuỗi đó không có bất kỳ mã hóa nào cả. Tôi có nghĩa là bạn không thể chọn chuỗi mã hóa nào. Nó luôn là UTF-16. @Handleman: Vâng, bây giờ bạn có thể thấy rằng Mã hóa "Mặc định" này không phải là UTF-8 hoặc ASCII, mà là mã hóa ngôn ngữ của bạn. – Euphoric

Các vấn đề liên quan