我需要将一些聊天代码从iOS移植到Android。在将聊天消息发送到套接字之前,iOS代码使用NSNonLossyASCIIStringEncoding
类作为NSString :: dataUsingEncoding的参数。
你会怎么在Android中做到这一点?关于相反解码的同样问题。
例如,如果不这样做,换行符就会消失在另一部手机上收到的消息中。
iOS上的代码:
NSData *data1 = [myStringTosend dataUsingEncoding:NSNonLossyASCIIStringEncoding];
NSString *goodValue = [[[NSString alloc] initWithData:data1 encoding:NSUTF8StringEncoding] autorelease];
解码:
NSData *data = [[NSData alloc] initWithData:[response dataUsingEncoding:NSASCIIStringEncoding]];
到目前为止(并且不正确),Android端编码:
OutputStream os = socket.getOutputStream();
os.write(request.getBytes("UTF-8"));
os.flush();
解码:
while ((bytesRead = is.read(buffer, 0, BUFFER_SIZE)) >= 0) {
if (bytesRead > 0) response.append(new String(buffer, 0, bytesRead, "UTF-8"));
if (bytesRead < BUFFER_SIZE) break;
}
答案 0 :(得分:7)
@portforwardpodcast是绝对正确的,如果可能的话,你应该避免对你的utf8进行ASCII编码,而是设置你的堆栈来直接处理/存储utf8。也就是说,如果您无法更改行为,则以下代码可能会有所帮助。
虽然没有关于NSNonLossyASCIIStringEncoding
如何工作的公开说明,但基于其输出,它看起来像:
ñ
,小数值为241 - &gt; \361
)\ud83d\ude25
)所以编码:
public static String encodeToNonLossyAscii(String original) {
Charset asciiCharset = Charset.forName("US-ASCII");
if (asciiCharset.newEncoder().canEncode(original)) {
return original;
}
StringBuffer stringBuffer = new StringBuffer();
for (int i = 0; i < original.length(); i++) {
char c = original.charAt(i);
if (c < 128) {
stringBuffer.append(c);
} else if (c < 256) {
String octal = Integer.toOctalString(c);
stringBuffer.append("\\");
stringBuffer.append(octal);
} else {
String hex = Integer.toHexString(c);
stringBuffer.append("\\u");
stringBuffer.append(hex);
}
}
return stringBuffer.toString();
}
要解码(通过在锁定步骤中解析两种类型的编码,而不是两次单独的传递,可以提高效率):
private static final Pattern UNICODE_HEX_PATTERN = Pattern.compile("\\\\u([0-9A-Fa-f]{4})");
private static final Pattern UNICODE_OCT_PATTERN = Pattern.compile("\\\\([0-7]{3})");
public static String decodeFromNonLossyAscii(String original) {
Matcher matcher = UNICODE_HEX_PATTERN.matcher(original);
StringBuffer charBuffer = new StringBuffer(original.length());
while (matcher.find()) {
String match = matcher.group(1);
char unicodeChar = (char) Integer.parseInt(match, 16);
matcher.appendReplacement(charBuffer, Character.toString(unicodeChar));
}
matcher.appendTail(charBuffer);
String parsedUnicode = charBuffer.toString();
matcher = UNICODE_OCT_PATTERN.matcher(parsedUnicode);
charBuffer = new StringBuffer(parsedUnicode.length());
while (matcher.find()) {
String match = matcher.group(1);
char unicodeChar = (char) Integer.parseInt(match, 8);
matcher.appendReplacement(charBuffer, Character.toString(unicodeChar));
}
matcher.appendTail(charBuffer);
return charBuffer.toString();
}
答案 1 :(得分:2)
不要使用NSNonLossyASCIIStringEncoding,请使用utf-8编码。我刚刚在ios + android + java spring后端解决了这个问题,我花了整整4天的时间来解决所有问题。 Android无法显示表情符号,但这为我提供了几乎所有(或所有不确定)语言的完全角色支持。以下是帮助我的文章:
必读:http://blog.manbolo.com/2012/10/29/supporting-new-emojis-on-ios-6 http://blog.manbolo.com/2011/12/12/supporting-ios-5-new-emoji-encoding
查看数据库内的字符串的十六进制字节:How can I see raw bytes stored in a MySQL column?
有关如何设置MySQL的详细信息:http://technovergence-en.blogspot.com/2012/03/mysql-from-utf8-to-utf8mb4.html
深入了解utf8- http://www.unicode.org/faq/utf_bom.html#utf8-4
的常见问题有关与表示法的区别的详细信息:\ ud83d \ udc7d和内存中的十六进制值:0xF09F91BD http://en.wikipedia.org/wiki/UTF-8#Description
使用此方法复制和粘贴字符以查看实际的十六进制字节值(适用于表情符号):http://perishablepress.com/tools/utf8-hex/index.php
获取Spring以支持网址中的utf8(用于GET参数)http://forum.springsource.org/showthread.php?93728-RequestParam-doesn-t-seem-to-be-decoded Get Parameter Encoding http://forum.springsource.org/showthread.php?112181-Unable-to-Override-the-Spring-MVC-URL-decoding-which-uses-default-quot-ISO-8859-1-quot
答案 2 :(得分:0)
我的答案代码相当于Android的IOS NSNonLossyASCIIStringEncoding。
在你的gradle中放置下方。
compile 'org.apache.commons:commons-lang3:3.4'
然后把方法放到你的Utils类这样
public static String encode(String s)
{
return StringEscapeUtils.escapeJava(s);
}
public static String decode(String s)
{
return StringEscapeUtils.unescapeJava(s);
}
然后简单地调用这个方法来编码字符串或像这样解码字符串
//for encode
String stencode = Utils.encode("mystring");
//for decode
String stdecode = Utils.decode("mystring")