我在JS中编写了一个客户端代码,它应该与我无法修改的第三方c#服务兼容。
该服务提供base64 unicode 编码字符串(JSON), 为了(简化)示例,这是c#代码:
var myString = Encoding.Unicode.GetBytes("{\"counter\":0}");
var encodedString = Convert.ToBase64String(myString);
导致:" ewAiAGMAbwB1AG4AdABlAHIAIgA6ADAAfQA ="
现在我需要在客户端更新这个编码的JSON,并返回一个有效的base64字符串,该字符串将由这个C#代码解码:
byte[] bytes = Convert.FromBase64String(encodedString);
string decodedString = Encoding.Unicode.GetString(bytes);
我在网上找到的所有解决方案/示例都导致解码功能输出无效结果。
例如,当使用基本window.btoa("{\"counter\":1}")
导致eyJjb3VudGVyIjoxfQ==
时
反过来,当在c#app上解码时,最多会导致格式异常,或导致完全乱码。
任何想法?
答案 0 :(得分:1)
正如@roeland所说,“技巧”是首先将字符串编码为UTF16-LE,然后将UTF16-LE字符串编码为base64。
我解决它的方法是先使用以下方法将字符串转换为字节数组:
function str2ByteArr(str) {
var bytes = [];
for (var i = 0; i < str.length; ++i) {
bytes.push(str.charCodeAt(i));
bytes.push(0);
}
return bytes;
}
"{\"counter\":0}"
的结果将是:
[123, 0, 34, 0, 99, 0, 111, 0, 117, 0, 110, 0, 116, 0, 101, 0, 114, 0, 34, 0, 58, 0, 48, 0, 125, 0]
然后将数组转换为base64:
function arrayBufferToBase64(buffer) {
var binary = '';
var bytes = new Uint8Array(buffer);
var len = bytes.byteLength;
for (var i = 0; i < len; i++) {
binary += String.fromCharCode(bytes[i]);
}
return window.btoa(binary);
}
并总结一下:
var byteArr = str2ByteArr(str);
return arrayBufferToBase64(byteArr);
结果是:
"ewAiAGMAbwB1AG4AdABlAHIAIgA6ADAAfQA="
我发现将字符串转换为字节数组'utf-8','utf-16be'和'utf-16le'编码的另一种方法是使用Text.Encoder,您可以在其中明确选择编码这样:
var textEncoder = new TextEncoder('utf-16le')
textEncoder.encode("{\"counter\":0}")
但资源管理器不支持此功能。
答案 1 :(得分:0)
可接受的答案假设高字节始终为0。情况并非总是如此,实际上对私はGoogle翻訳を使用訳を进行编码是行不通的。诀窍是使用此处找到的技术:将字符串转换为UTF16 Little Endian数组时使用How to convert a String to Bytearray:
bytes.push(charCode & 0xFF); // low byte
bytes.push((charCode & 0xFF00) >>> 8); // high byte
完整解决方案:
function base64Encode(str)
{
var bytes = [];
for (var i = 0; i < str.length; ++i)
{
var charCode = str.charCodeAt(i);
bytes.push(charCode & 0xFF);
bytes.push((charCode & 0xFF00) >>> 8);
}
var len = bytes.length;
var buffer = "";
for (var i = 0; i < len; i++)
{
buffer += String.fromCharCode(bytes[i]);
}
return window.btoa(buffer);
}
答案 2 :(得分:-1)
下面是用于解码的Java脚本代码:
// here you will have to reference again in the inspector the
// SoundController component from above
[SerializeField] private SoundController _soundController;
// ....
// than whereever you have your code for
// "... plays for a specific image target and it stops when the target is lost ..."
// you add the line like e.g. for letter A
SoundController.CurrentLetter = SoundController.Letter.A;
此encodeString传递给您的控制器。
var Base64 = { _keyStr: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=", encode: function (e) { var t = ""; var n, r, i, s, o, u, a; var f = 0; e = Base64._utf8_encode(e); while (f < e.length) { n = e.charCodeAt(f++); r = e.charCodeAt(f++); i = e.charCodeAt(f++); s = n >> 2; o = (n & 3) << 4 | r >> 4; u = (r & 15) << 2 | i >> 6; a = i & 63; if (isNaN(r)) { u = a = 64 } else if (isNaN(i)) { a = 64 } t = t + this._keyStr.charAt(s) + this._keyStr.charAt(o) + this._keyStr.charAt(u) + this._keyStr.charAt(a) } return t }, decode: function (e) { var t = ""; var n, r, i; var s, o, u, a; var f = 0; e = e.replace(/++[++^A-Za-z0-9+/=]/g, ""); while (f < e.length) { s = this._keyStr.indexOf(e.charAt(f++)); o = this._keyStr.indexOf(e.charAt(f++)); u = this._keyStr.indexOf(e.charAt(f++)); a = this._keyStr.indexOf(e.charAt(f++)); n = s << 2 | o >> 4; r = (o & 15) << 4 | u >> 2; i = (u & 3) << 6 | a; t = t + String.fromCharCode(n); if (u != 64) { t = t + String.fromCharCode(r) } if (a != 64) { t = t + String.fromCharCode(i) } } t = Base64._utf8_decode(t); return t }, _utf8_encode: function (e) { e = e.replace(/\r\n/g, "n"); var t = ""; for (var n = 0; n < e.length; n++) { var r = e.charCodeAt(n); if (r < 128) { t += String.fromCharCode(r) } else if (r > 127 && r < 2048) { t += String.fromCharCode(r >> 6 | 192); t += String.fromCharCode(r & 63 | 128) } else { t += String.fromCharCode(r >> 12 | 224); t += String.fromCharCode(r >> 6 & 63 | 128); t += String.fromCharCode(r & 63 | 128) } } return t }, _utf8_decode: function (e) { var t = ""; var n = 0; var r = c1 = c2 = 0; while (n < e.length) { r = e.charCodeAt(n); if (r < 128) { t += String.fromCharCode(r); n++ } else if (r > 191 && r < 224) { c2 = e.charCodeAt(n + 1); t += String.fromCharCode((r & 31) << 6 | c2 & 63); n += 2 } else { c2 = e.charCodeAt(n + 1); c3 = e.charCodeAt(n + 2); t += String.fromCharCode((r & 15) << 12 | (c2 & 63) << 6 | c3 & 63); n += 3 } } return t } }
var id = 7;
var encodeString = Base64.encode(id.toString());
console.log(encodeString);
C#代码:
http://localhost:60362/ProjectManagement/Project/ProjectSettings/MTA=
最终代码:
解密值:
public static string base64Encode(string sData)
{
try
{
byte[] encData_byte = new byte[sData.Length];
encData_byte = System.Text.Encoding.UTF8.GetBytes(sData);
string encodedData = Convert.ToBase64String(encData_byte);
return encodedData;
}
catch (Exception)
{
return string.Empty;
}
}
/// <summary>
/// Method To Decrypt Password
/// </summary>
/// <param name="sData"></param>
/// <returns></returns>
public static string base64Decode(string sData)
{
try
{
System.Text.UTF8Encoding encoder = new System.Text.UTF8Encoding();
System.Text.Decoder utf8Decode = encoder.GetDecoder();
byte[] todecode_byte = Convert.FromBase64String(sData);
int charCount = utf8Decode.GetCharCount(todecode_byte, 0, todecode_byte.Length);
char[] decoded_char = new char[charCount];
utf8Decode.GetChars(todecode_byte, 0, todecode_byte.Length, decoded_char, 0);
string result = new String(decoded_char);
return result;
}
catch (Exception)
{
return string.Empty;
}
}