3

チャット コードを 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;
}
4

3 に答える 3

9

@portforwardpodcast は、可能であれば、utf8 の ASCII エンコードを避け、代わりに utf8 を直接処理/保存するようにスタックを設定する必要があるという点で絶対に正しいです。とはいえ、動作を変更できない場合は、次のコードが役立つ場合があります。

どのように機能するかについての公開された説明はありませんがNSNonLossyASCIIStringEncoding、その出力に基づいて次のようになります。

  • 拡張 ASCII 範囲 (10 進値 128 - 255) のバイトは、8 進エンコーディングを使用してエスケープされます (例えばñ、10 進値 241 -> \361)
  • 非 ASCII コード ポイントは、16 進エンコーディングを使用して 2 バイトのチャンクでエスケープされます (たとえば、10 進値 128549 で 32 ビットを占めます -> \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();
}

そしてデコードします (これは、2 つの別々のパスとしてではなく、ロック ステップで 2 種類のエンコーディングを解析することにより、より効率的にすることができます):

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();
}
于 2015-12-22T21:14:00.750 に答える
2

NSNonLossyASCIIStringEncoding を使用しないでください。utf-8 エンコーディングを使用してください。ios + android + Java spring backendでこの問題を自分で解決したところ、すべてを理解するのに丸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-新しい絵文字エンコーディング

DB 内の文字列の 16 進バイトを参照してください: MySQL 列に保存されている生のバイトを確認するにはどうすればよいですか?

MySQL のセットアップ方法の詳細: http://technovergence-en.blogspot.com/2012/03/mysql-from-utf8-to-utf8mb4.html

utf8 の詳細な FAQ - http://www.unicode.org/faq/utf_bom.html#utf8-4

表記との違いの詳細: \ud83d\udc7d およびメモリ内の 16 進値: 0xF09F91BD http://en.wikipedia.org/wiki/UTF-8#Description

これを使用して文字をコピーして貼り付け、実際の 16 進バイト値を表示します (絵文字で機能します): http://perishablepress.com/tools/utf8-hex/index.php

URL で utf8 をサポートするように Spring を取得します (GET パラメーターの場合) http://forum.springsource.org/showthread.php?93728-RequestParam-doesn-t-seem-to-be-decoded パラメーター エンコーディングを取得 http://forum. springsource.org/showthread.php?112181-Unable-to-Override-the-Spring-MVC-URL-decoding-which-uses-default-quot-ISO-8859-1-quot

于 2013-01-19T05:07:14.757 に答える