2013年5月13日 星期一

cocoa 字元編碼

這幾天在處理一個登入介面

不過傳送密碼時碰到問題了

由於密碼中有特殊字元,諸如 @+等字元

而這些字元在 stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding 中並不會被編碼

所以 server 端收到後,會有處理上的問題

因此必須強制編碼

http://stackoverflow.com/questions/3423545/objective-c-iphone-percent-encode-a-string

上面的連結提供了一個不錯的方式處理

其他相關的知識

cocoa coding

http://secondflush2.blog.fc2.com/blog-entry-62.html

http://stackoverflow.com/questions/2467844/convert-utf-8-encoded-nsdata-to-nsstring

字串非 null-terminated

NSString* newStr = [[[NSString alloc] initWithData:theData

encoding:NSUTF8StringEncoding] autorelease];

null terminated 時,使用 stringWithUTF8String 避免結尾的 \0 產生多餘字元

If the data is null-terminated, you should instead use -stringWithUTF8String: to avoid the extra \0 at the end.

NSString* newStr = [NSString stringWithUTF8String:[theData bytes]];

NSString to ASCII 轉成 ASCII

NSString *string = @"2";

int asciiCode = [string characterAtIndex:0]; //50

base64-utf8编码的NSString转化为NSString

http://blog.csdn.net/chenghxc/article/details/8618580

1、NSData+Base64.h

[plain] view plaincopyprint?

  1. #import <Foundation/Foundation.h>  
  2.   
  3. void *NewBase64Decode(  
  4.     const char *inputBuffer,  
  5.     size_t length,  
  6.     size_t *outputLength);  
  7.   
  8. char *NewBase64Encode(  
  9.     const void *inputBuffer,  
  10.     size_t length,  
  11.     bool separateLines,  
  12.     size_t *outputLength);  
  13.   
  14. @interface NSData (Base64)  
  15.   
  16. + (NSData *)dataFromBase64String:(NSString *)aString;  
  17. - (NSString *)base64EncodedString;  
  18.   
  19. @end  

2、NSData+Base64.m

[plain] view plaincopyprint?

  1. #import "NSData+Base64.h"  
  2.   
  3. //  
  4. // Mapping from 6 bit pattern to ASCII character.  
  5. //  
  6. static unsigned char base64EncodeLookup[65] =  
  7.     "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";  
  8.   
  9. //  
  10. // Definition for "masked-out" areas of the base64DecodeLookup mapping  
  11. //  
  12. #define xx 65  
  13.   
  14. //  
  15. // Mapping from ASCII character to 6 bit pattern.  
  16. //  
  17. static unsigned char base64DecodeLookup[256] =  
  18. {  
  19.     xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx,   
  20.     xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx,   
  21.     xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, 62, xx, xx, xx, 63,   
  22.     52, 53, 54, 55, 56, 57, 58, 59, 60, 61, xx, xx, xx, xx, xx, xx,   
  23.     xx,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14,   
  24.     15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, xx, xx, xx, xx, xx,   
  25.     xx, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,   
  26.     41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, xx, xx, xx, xx, xx,   
  27.     xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx,   
  28.     xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx,   
  29.     xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx,   
  30.     xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx,   
  31.     xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx,   
  32.     xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx,   
  33.     xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx,   
  34.     xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx,   
  35. };  
  36.   
  37. //  
  38. // Fundamental sizes of the binary and base64 encode/decode units in bytes  
  39. //  
  40. #define BINARY_UNIT_SIZE 3  
  41. #define BASE64_UNIT_SIZE 4  
  42.   
  43. //  
  44. // NewBase64Decode  
  45. //  
  46. // Decodes the base64 ASCII string in the inputBuffer to a newly malloced  
  47. // output buffer.  
  48. //  
  49. //  inputBuffer - the source ASCII string for the decode  
  50. //  length - the length of the string or -1 (to specify strlen should be used)  
  51. //  outputLength - if not-NULL, on output will contain the decoded length  
  52. //  
  53. // returns the decoded buffer. Must be free'd by caller. Length is given by  
  54. //  outputLength.  
  55. //  
  56. void *NewBase64Decode(  
  57.     const char *inputBuffer,  
  58.     size_t length,  
  59.     size_t *outputLength)  
  60. {  
  61.     if (length == -1)  
  62.     {  
  63.         length = strlen(inputBuffer);  
  64.     }  
  65.       
  66.     size_t outputBufferSize =  
  67.         ((length+BASE64_UNIT_SIZE-1) / BASE64_UNIT_SIZE) * BINARY_UNIT_SIZE;  
  68.     unsigned char *outputBuffer = (unsigned char *)malloc(outputBufferSize);  
  69.       
  70.     size_t i = 0;  
  71.     size_t j = 0;  
  72.     while (i < length)  
  73.     {  
  74.         //  
  75.         // Accumulate 4 valid characters (ignore everything else)  
  76.         //  
  77.         unsigned char accumulated[BASE64_UNIT_SIZE];  
  78.         size_t accumulateIndex = 0;  
  79.         while (i < length)  
  80.         {  
  81.             unsigned char decode = base64DecodeLookup[inputBuffer[i++]];  
  82.             if (decode != xx)  
  83.             {  
  84.                 accumulated[accumulateIndex] = decode;  
  85.                 accumulateIndex++;  
  86.                   
  87.                 if (accumulateIndex == BASE64_UNIT_SIZE)  
  88.                 {  
  89.                     break;  
  90.                 }  
  91.             }  
  92.         }  
  93.           
  94.         //  
  95.         // Store the 6 bits from each of the 4 characters as 3 bytes  
  96.         //  
  97.         // (Uses improved bounds checking suggested by Alexandre Colucci)  
  98.         //  
  99.         if(accumulateIndex >= 2)    
  100.             outputBuffer[j] = (accumulated[0] << 2) | (accumulated[1] >> 4);    
  101.         if(accumulateIndex >= 3)    
  102.             outputBuffer[j + 1] = (accumulated[1] << 4) | (accumulated[2] >> 2);    
  103.         if(accumulateIndex >= 4)    
  104.             outputBuffer[j + 2] = (accumulated[2] << 6) | accumulated[3];  
  105.         j += accumulateIndex - 1;  
  106.     }  
  107.       
  108.     if (outputLength)  
  109.     {  
  110.         *outputLength = j;  
  111.     }  
  112.     return outputBuffer;  
  113. }  
  114.   
  115. //  
  116. // NewBase64Encode  
  117. //  
  118. // Encodes the arbitrary data in the inputBuffer as base64 into a newly malloced  
  119. // output buffer.  
  120. //  
  121. //  inputBuffer - the source data for the encode  
  122. //  length - the length of the input in bytes  
  123. //  separateLines - if zero, no CR/LF characters will be added. Otherwise  
  124. //      a CR/LF pair will be added every 64 encoded chars.  
  125. //  outputLength - if not-NULL, on output will contain the encoded length  
  126. //      (not including terminating 0 char)  
  127. //  
  128. // returns the encoded buffer. Must be free'd by caller. Length is given by  
  129. //  outputLength.  
  130. //  
  131. char *NewBase64Encode(  
  132.     const void *buffer,  
  133.     size_t length,  
  134.     bool separateLines,  
  135.     size_t *outputLength)  
  136. {  
  137.     const unsigned char *inputBuffer = (const unsigned char *)buffer;  
  138.       
  139.     #define MAX_NUM_PADDING_CHARS 2  
  140.     #define OUTPUT_LINE_LENGTH 64  
  141.     #define INPUT_LINE_LENGTH ((OUTPUT_LINE_LENGTH / BASE64_UNIT_SIZE) * BINARY_UNIT_SIZE)  
  142.     #define CR_LF_SIZE 2  
  143.       
  144.     //  
  145.     // Byte accurate calculation of final buffer size  
  146.     //  
  147.     size_t outputBufferSize =  
  148.             ((length / BINARY_UNIT_SIZE)  
  149.                 + ((length % BINARY_UNIT_SIZE) ? 1 : 0))  
  150.                     * BASE64_UNIT_SIZE;  
  151.     if (separateLines)  
  152.     {  
  153.         outputBufferSize +=  
  154.             (outputBufferSize / OUTPUT_LINE_LENGTH) * CR_LF_SIZE;  
  155.     }  
  156.       
  157.     //  
  158.     // Include space for a terminating zero  
  159.     //  
  160.     outputBufferSize += 1;  
  161.   
  162.     //  
  163.     // Allocate the output buffer  
  164.     //  
  165.     char *outputBuffer = (char *)malloc(outputBufferSize);  
  166.     if (!outputBuffer)  
  167.     {  
  168.         return NULL;  
  169.     }  
  170.   
  171.     size_t i = 0;  
  172.     size_t j = 0;  
  173.     const size_t lineLength = separateLines ? INPUT_LINE_LENGTH : length;  
  174.     size_t lineEnd = lineLength;  
  175.       
  176.     while (true)  
  177.     {  
  178.         if (lineEnd > length)  
  179.         {  
  180.             lineEnd = length;  
  181.         }  
  182.   
  183.         for (; i + BINARY_UNIT_SIZE - 1 < lineEnd; i += BINARY_UNIT_SIZE)  
  184.         {  
  185.             //  
  186.             // Inner loop: turn 48 bytes into 64 base64 characters  
  187.             //  
  188.             outputBuffer[j++] = base64EncodeLookup[(inputBuffer[i] & 0xFC) >> 2];  
  189.             outputBuffer[j++] = base64EncodeLookup[((inputBuffer[i] & 0x03) << 4)  
  190.                 | ((inputBuffer[i + 1] & 0xF0) >> 4)];  
  191.             outputBuffer[j++] = base64EncodeLookup[((inputBuffer[i + 1] & 0x0F) << 2)  
  192.                 | ((inputBuffer[i + 2] & 0xC0) >> 6)];  
  193.             outputBuffer[j++] = base64EncodeLookup[inputBuffer[i + 2] & 0x3F];  
  194.         }  
  195.           
  196.         if (lineEnd == length)  
  197.         {  
  198.             break;  
  199.         }  
  200.           
  201.         //  
  202.         // Add the newline  
  203.         //  
  204.         outputBuffer[j++] = '\r';  
  205.         outputBuffer[j++] = '\n';  
  206.         lineEnd += lineLength;  
  207.     }  
  208.       
  209.     if (i + 1 < length)  
  210.     {  
  211.         //  
  212.         // Handle the single '=' case  
  213.         //  
  214.         outputBuffer[j++] = base64EncodeLookup[(inputBuffer[i] & 0xFC) >> 2];  
  215.         outputBuffer[j++] = base64EncodeLookup[((inputBuffer[i] & 0x03) << 4)  
  216.             | ((inputBuffer[i + 1] & 0xF0) >> 4)];  
  217.         outputBuffer[j++] = base64EncodeLookup[(inputBuffer[i + 1] & 0x0F) << 2];  
  218.         outputBuffer[j++] = '=';  
  219.     }  
  220.     else if (i < length)  
  221.     {  
  222.         //  
  223.         // Handle the double '=' case  
  224.         //  
  225.         outputBuffer[j++] = base64EncodeLookup[(inputBuffer[i] & 0xFC) >> 2];  
  226.         outputBuffer[j++] = base64EncodeLookup[(inputBuffer[i] & 0x03) << 4];  
  227.         outputBuffer[j++] = '=';  
  228.         outputBuffer[j++] = '=';  
  229.     }  
  230.     outputBuffer[j] = 0;  
  231.       
  232.     //  
  233.     // Set the output length and return the buffer  
  234.     //  
  235.     if (outputLength)  
  236.     {  
  237.         *outputLength = j;  
  238.     }  
  239.     return outputBuffer;  
  240. }  
  241.   
  242. @implementation NSData (Base64)  
  243.   
  244. //  
  245. // dataFromBase64String:  
  246. //  
  247. // Creates an NSData object containing the base64 decoded representation of  
  248. // the base64 string 'aString'  
  249. //  
  250. // Parameters:  
  251. //    aString - the base64 string to decode  
  252. //  
  253. // returns the autoreleased NSData representation of the base64 string  
  254. //  
  255. + (NSData *)dataFromBase64String:(NSString *)aString  
  256. {  
  257.     NSData *data = [aString dataUsingEncoding:NSASCIIStringEncoding];  
  258.     size_t outputLength;  
  259.     void *outputBuffer = NewBase64Decode([data bytes], [data length], &outputLength);  
  260.     NSData *result = [NSData dataWithBytes:outputBuffer length:outputLength];  
  261.     free(outputBuffer);  
  262.     return result;  
  263. }  
  264.   
  265. //  
  266. // base64EncodedString  
  267. //  
  268. // Creates an NSString object that contains the base 64 encoding of the  
  269. // receiver's data. Lines are broken at 64 characters long.  
  270. //  
  271. // returns an autoreleased NSString being the base 64 representation of the  
  272. //  receiver.  
  273. //  
  274. - (NSString *)base64EncodedString  
  275. {  
  276.     size_t outputLength;  
  277.     char *outputBuffer =  
  278.         NewBase64Encode([self bytes], [self length], true, &outputLength);  
  279.       
  280.     NSString *result =  
  281.         [[[NSString alloc]  
  282.             initWithBytes:outputBuffer  
  283.             length:outputLength  
  284.             encoding:NSASCIIStringEncoding]  
  285.         autorelease];  
  286.     free(outputBuffer);  
  287.     return result;  
  288. }  
  289.   
  290. @end  

3、NSString+Base64.h

[plain] view plaincopyprint?

  1. #import <Foundation/Foundation.h>  
  2.   
  3. @interface NSString (Base64)  
  4. + (NSString *)base64Encode:(NSString *)plainText;  
  5. + (NSString *)base64Decode:(NSString *)base64String;  
  6. @end  

4、NSString+Base64.m

[plain] view plaincopyprint?

  1. #import "NSString+Base64.h"  
  2. #import "NSData+Base64.h"  
  3. @implementation NSString (Base64)  
  4.   
  5. + (NSString *)base64Encode:(NSString *)plainText  
  6. {  
  7.     NSData *plainTextData = [plainText dataUsingEncoding:NSUTF8StringEncoding];  
  8.     NSString *base64String = [plainTextData base64EncodedString];  
  9.     return base64String;  
  10. }  
  11.   
  12. + (NSString *)base64Decode:(NSString *)base64String  
  13. {  
  14.     NSData *plainTextData = [NSData dataFromBase64String:base64String];  
  15.     NSString *plainText = [[NSString alloc] initWithData:plainTextData encoding:NSUTF8StringEncoding];  
  16.     return plainText;  
  17. }  
  18. @end  

5、实例代码:

[plain] view plaincopyprint?

  1. #import "AppDelegate.h"  
  2. #import "NSString+Base64.h"  
  3.   
  4. @implementation AppDelegate  
  5.   
  6. @synthesize window = _window;  
  7.   
  8. - (void)dealloc  
  9. {  
  10.     [super dealloc];  
  11. }  
  12.       
  13. - (void)applicationDidFinishLaunching:(NSNotification *)aNotification  
  14. {  
  15.     NSString *str = @"未加密字符串";  
  16.     NSLog(@"nsstring: %@",str);  
  17.     NSString *base64utf8 = [NSString base64Encode:str];  
  18.     NSLog(@"base64utf8: %@",base64utf8);  
  19.     NSLog(@"nsstring: %@",[NSString base64Decode:base64utf8]);  
  20. }  
  21.   
  22. @end  

沒有留言: