stringByReplacingPercentEscapesUsingEncoding: が期待する結果を返さないことがある

パーセントエンコーディングされた ISO-2022-JP 文字列
@"%1B%24B%3CL%3F%3F%1B%28B.PNG"
NSString のメソッド stringByReplacingPercentEscapesUsingEncoding: でデコードしようとすると

NSString *string = @"%1B%24B%3CL%3F%3F%1B%28B.PNG";
NSString *decoded = [string stringByReplacingPercentEscapesUsingEncoding:NSISO2022JPStringEncoding];

@"$B<L??(B.PNG"
が返ってきます。期待している結果は @"写真.PNG" なのですが、どうもうまくデコードしてくれません。

試しに、パーセントエンコーディングされた文字列を
@"%1B%24%42%3C%4C%3F%3F%1B%28%42.PNG"
にしてデコードしてみると、期待通りの結果が返ってきます。

どうやら、%24B, %3CL, %28B がお気に召さないようです。
http://ja.wikipedia.org/wiki/URLエンコード
を読むと、お気に召さない文字列は仕様上間違いではないようですが、上記メソッドでは期待通りにはデコードしてくれません。

仕方がないので、気に入ってもらえるよう、
@"%1B%24B%3CL%3F%3F%1B%28B.PNG"

@"%1B%24%42%3C%4C%3F%3F%1B%28%42.PNG"
に変換して、デコードしてもらうようにします。

とりあえず、以下のコードで変換してみることにしました。

NSString *(^adjustedPercentEscapedString)(NSString *) = ^(NSString *percentEscapedString) {
    NSMutableString *adjustedString = [NSMutableString string];

    const char *cString = [percentEscapedString cStringUsingEncoding:NSASCIIStringEncoding];

    NSUInteger offsetFromPercent = NSNotFound;
    for (NSUInteger i=0; i 2) {
                    [adjustedString appendFormat:@"%%%02X", c];
                    offsetFromPercent = NSNotFound;
                }
                else {
                    [adjustedString appendFormat:@"%c", c];
                }
            }
            else {
                [adjustedString appendFormat:@"%%%02X", c];
            }
        }
    }

    return adjustedString;
};

NSString *adjustedString = adjustedPercentEscapedString(@"%1B%24B%3CL%3F%3F%1B%28B.PNG");

もう少し、appendFormat: の呼び出しを減らしたい気もしますが、
とりあえずうまくいっているので、ひとまずはこれで良しとします。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

CAPTCHA