NSNonLossyASCIIStringEncoding等效于Android

时间:2012-12-10 11:35:24

标签: android ios nsstring

我需要将一些聊天代码从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;
}

3 个答案:

答案 0 :(得分:7)

@portforwardpodcast是绝对正确的,如果可能的话,你应该避免对你的utf8进行ASCII编码,而是设置你的堆栈来直接处理/存储utf8。也就是说,如果您无法更改行为,则以下代码可能会有所帮助。

虽然没有关于NSNonLossyASCIIStringEncoding如何工作的公开说明,但基于其输出,它看起来像:

  • 扩展ASCII范围(十进制值128 - 255)中的字节使用八进制编码进行转义(例如ñ,小数值为241 - &gt; \361
  • 非ASCII代码点使用十六进制编码以两个字节的块进行转义(例如,它占用32位,十进制值128549 - &gt; \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")