After hours of research I gave up.
I receive text data from a WebService. For some case, the text is inJapanese, and the WS returns its Unicoded version. For example: \U00e3\U0082\U008f
I know that this is a Japanese char.
I am trying to display this Unicode char or string inside a UILabel.
Since the simple setText method does'nt display the correct chars, I used this (copied) routine:
unichar unicodeValue = (unichar) strtol([[[p innerData] valueForKey:#"title"] UTF8String], NULL, 16);
char buffer[2];
int len = 1;
if (unicodeValue > 127) {
buffer[0] = (unicodeValue >> 8) & (1 << 8) - 1;
buffer[1] = unicodeValue & (1 << 8) - 1;
len = 2;
} else {
buffer[0] = unicodeValue;
}
[[cell title] setText:[[NSString alloc] initWithBytes:buffer length:len encoding:NSUTF8StringEncoding] ];
But no success: the UILabel is empty.
I know that one way could be convert the chars to hex and then from hex to String...is there a simpler way?
SOLVED
First you must be sure that your server is sending UTF8 and not UNICODE CODE POINTS. The only way I found is to json_encode strings which contain UNICODE chars.
Then, in iOS user unescaping following this link Using Objective C/Cocoa to unescape unicode characters, ie \u1234
Related
I need to send a UDP packet with HEX values like this example;
char buffer[4]={0x22,0x00,0x0d,0xf4};
However, I need to be able to change the hex values in code.
hex1 = "0x83";
hex2 = "0x11";
hex3 = "0x00";
hex4 = "0x01";
char buffer[4]={hex1, hex2, hex3, hex4}
I have tried the example above but it does not work. Can you show me the correct way to build the buffer for sending.
Declare and fill the buffer separately. And remove the quotes around your hex values.
char buffer[4];
buffer[0] = 0x83;
buffer[1] = 0x11;
buffer[2] = 0x00;
buffer[3] = 0x01;
I am implementing AES decoder, for creating IV and key, the algorithm is such that
IV Key's 16 bytes:the first 16 bytes of ProductID.getBytes("UTF-8")
(If there are no enough bytes,
make up to 16 bytes at right by 0x32)
and my code for padding
- (char*)paddedStringFromString:(NSString *)string withLength:(NSUInteger)length{
const char *stringC = [string UTF8String];
char * output;
output = malloc(length+1);
for (NSInteger i = 0; i < length; i++) {
if (i < string.length) output[i] = stringC[i];
else output[i] = 0x32;
}
return output;
}
But I am not getting the right result. Is my approach for padding is right. Please help
I think the args length and string.length are not the same, right?
I am successfully passing a 64 bit number from a objC client to a java client, but am unable to send to an objC client.
Java Code
/*
* Retrieve a double (64-bit) number from the stream.
*/
private double getDouble() throws IOException
{
byte[] buffer = getBytes(8);
long bits =
((long)buffer[0] & 0x0ff) |
(((long)buffer[1] & 0x0ff) << 8) |
(((long)buffer[2] & 0x0ff) << 16) |
(((long)buffer[3] & 0x0ff) << 24) |
(((long)buffer[4] & 0x0ff) << 32) |
(((long)buffer[5] & 0x0ff) << 40) |
(((long)buffer[6] & 0x0ff) << 48) |
(((long)buffer[7] & 0x0ff) << 56);
return Double.longBitsToDouble(bits);
}
objC code
/*
* Retrieve a double (64-bit) number from the stream.
*/
- (double)getDouble
{
NSRange dblRange = NSMakeRange(0, 8);
char buffer[8];
[stream getBytes:buffer length:8];
[stream replaceBytesInRange:dblRange withBytes:NULL length:0];
long long bits =
((long long)buffer[0] & 0x0ff) |
(((long long)buffer[1] & 0x0ff) << 8) |
(((long long)buffer[2] & 0x0ff) << 16) |
(((long long)buffer[3] & 0x0ff) << 24) |
(((long long)buffer[4] & 0x0ff) << 32) |
(((long long)buffer[5] & 0x0ff) << 40) |
(((long long)buffer[6] & 0x0ff) << 48) |
(((long long)buffer[7] & 0x0ff) << 56);
NSNumber *tempNum = [NSNumber numberWithLongLong:bits];
NSLog(#"\n***********\nsizeof long long %d \n tempNum: %#\nbits %lld",sizeof(long long), tempNum, bits);
return [tempNum doubleValue];
}
the result of NSLog is
sizeof long long 8
tempNum: -4616134021117358511
bits -4616134021117358511
the number should be : -1.012345
The problem is that I am trying to convert Java to objC in the getDouble func. My middleware takes into account the endian issues. The simple solution is if the target is little endian
- (double)getDouble
NSRange dblRange = NSMakeRange(0, 8);
double swapped;
[stream getBytes:&swapped length:8];
[stream replaceBytesInRange:dblRange withBytes:NULL length:0];
return swapped;
Thanks all for input - got a lot of experience and a little understanding from this exercise.
A double and a long long are not the same thing. A long represents an integer, which has no fractional portion, and a double represents a floating-point number, which has a fractional portion. These two types have completely different ways of representing their values in memory. That is to say, if you were to look at the bits for a long long representing the number 4000 and compare those to the bits for a double representing the number 4000, they would be different.
So as Wevah notes, the first step is for you to use the proper double type, and the correct %f formatter in your call to NSLog().
I would add, though, that you also need to be careful to get your bytes in the native order for the machine your C code is running on. For a detailed description of what I'm referring to, see http://en.wikipedia.org/wiki/Endianness The short version is that different processors may represent numbers in different ways in memory, and you need to ensure in your code that once you get a pile of bytes from the network, you are putting the bytes in the right order for your processor before you attempt to interpret it as a number.
Luckily, this is a solved issue, and is easily accounted for by using the CFConvertFloat64SwappedToHost() function from CoreFoundation:
[stream getBytes:buffer length:8];
[stream replaceBytesInRange:dblRange withBytes:NULL length:0];
double myDouble = CFConvertFloat64SwappedToHost(*((double*)buffer));
NSNumber *tempNum = [NSNumber numberWithDouble:myDouble];
NSLog(#"\n***********\nsizeof double %d \n tempNum: %#\nbits %f",sizeof(double), tempNum, myDouble);
return [tempNum doubleValue];
You probably want to convert it to a double (possibly/probably via a union; see Jonathan's comment) and use the %f specifier.
Is there a better or shorter way of striping out all the non-digit characters with Objective-C on the iPhone?
NSString * formattedNumber = #"(123) 555-1234";
NSCharacterSet * nonDigits = [[NSCharacterSet decimalDigitCharacterSet] invertedSet];
NSString * digits;
NSArray * parts = [formattedNumber componentsSeparatedByCharactersInSet:nonDigits];
if ( [parts count] > 1 ) {
digits = [parts componentsJoinedByString:#""];
} else {
digits = [parts objectAtIndex:0];
}
return digits;
You could use a RegEx-replacement that replaces [\D] with nothing.
Dupe of Remove all but numbers from NSString
The accepted answer there involves using NSScanner, which seems heavy-handed for such a simple task. I'd stick with what you have there (though someone in the other thread suggested a more compact version if it, thus:
NSString *digits = [[formattedNumber componentsSeparatedByCharactersInSet:
[[NSCharacterSet decimalDigitCharacterSet] invertedSet]]
componentsJoinedByString:#""];
Phone numbers can contain asterisks and number signs (* and #), and may start with a +. The ITU-T E-123 Recommandation recommends that the + symbol be used to indicate that the number is an international number and also to serve as a reminder that the country-specific international dialling sequence must be used in place of it.
Spaces, hyphens and parentheses cannot be dialled so they do not have any significance in a phone number. In order to strip out all useless symbols, you should remove all characters not in the decimal character set, except * and #, and also any + not found at the start of the phone number.
To my knowledge, there is no standardised or recommended way to represent manual extensions (some use x, some use ext, some use E). Although, I have not encountered a manual extension in a long time.
NSUInteger inLength, outLength, i;
NSString *formatted = #"(123) 555-5555";
inLength = [formatted length];
unichar result[inLength];
for (i = 0, outLength = 0; i < inLength; i++)
{
unichar thisChar = [formatted characterAtIndex:i];
if (iswdigit(thisChar) || thisChar == '*' || thisChar == '#')
result[outLength++] = thisChar; // diallable number or symbol
else if (i == 0 && thisChar == '+')
result[outLength++] = thisChar; // international prefix
}
NSString *stripped = [NSString stringWithCharacters:result length:outLength];
You could do something like this:
NSString *digits = [[formattedNumber componentsSeparatedByCharactersInSet:[NSCharacterSet decimalDigitCharacterSet]] componentsJoinedByString:#""];
Noting 0xA3's comment above, you could optionally use a different NSCharacterSet that includes + and other non-digits that are valid in phone numbers.
I am trying to escape double-byte (usually Japanese or Chinese) characters from a string so that they can be included in an RTF file. Thanks to poster falconcreek, I can successfully escape special characters (e.g. umlaut, accent, tilde) that are single-byte.
- (NSString *)stringFormattedRTF:(NSString *)inputString
{
NSMutableString *result = [NSMutableString string];
for ( int index = 0; index < [inputString length]; index++ ) {
NSString *temp = [inputString substringWithRange:NSMakeRange( index, 1 )];
unichar tempchar = [inputString characterAtIndex:index];
if ( tempchar > 127) {
[result appendFormat:#"\\\'%02x", tempchar];
} else {
[result appendString:temp];
}
}
return result;
}
It appears this is looking for any unicode characters with a decimal value higher than 127 (which basically means anything not ASCII). If I find one, I escape it and translate that to a hex value.
EXAMPLE: Small "e" with acute accent gets escaped and converted to its hex value, resulting in "\'e9"
While Asian characters are above 127 decimal value, the output from the above appears to be reading the first byte of the unicode double byte character and encoding that then passing the second byte as is. For the end user it ends up ????.
Suggestions are greatly appreciated. Thanks.
UPDATED Code sample based on suggestion. Not detecting. :(
NSString *myDoubleByteTestString = #"blah は凄くいいアップです blah åèüñ blah";
NSMutableString *resultDouble = [NSMutableString string];
for ( int index = 0; index < [myDoubleByteTestString length]; index++ )
{
NSString *tempDouble = [myDoubleByteTestString substringWithRange:NSMakeRange( index, 1 )];
NSRange doubleRange = [tempDouble rangeOfComposedCharacterSequenceAtIndex:index];
if(doubleRange.length > 2)
{
NSLog(#"%# is a double-byte character. Escape it.", tempDouble);
// How to escape double-byte?
[resultDouble appendFormat:tempDouble];
}
else
{
[resultDouble appendString:tempDouble];
}
}
Take a look at the code at rangeOfComposedCharacterSequenceAtIndex: to see how to get all the characters in a composed character. You'll then need to encode each of the characters in the resulting range.