How do I see the true contents of this string? - ios

Please bear with me here since this question is not so easy to explain and word correctly.
I am using the following code in order to get data from a USB connected barcode reader, the scanner works fine and data is passed in as expected but my DB lookups fail and I believe they are failing because the data I am passing into the DBLookup method is incorrect but I am unable to see why, I think NSLog is helping me to show clear text data when in fact it isn't and I am stuck at debugging further.
Here is my code
- (void)didBarcodeDataReceive:(StarIoExtManager *)manager data:(NSData *)data {
NSLog(#"%s", __PRETTY_FUNCTION__);
NSMutableString *text = [NSMutableString stringWithString:#""];
const uint8_t *p = data.bytes;
for (int i = 0; i < data.length; i++) {
uint8_t ch = *(p + i);
[text appendFormat:#"%c", (char) ch];
}
NSLog(#"Scanned info as NSData was: %#", data); // raw NSData
//NSString *stringWithData = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSString *stringWithData = [[NSString alloc] initWithBytes:(char *)data.bytes length:data.length encoding:NSUTF8StringEncoding];
NSLog(#"Scanned info as StringFromData was: %#", stringWithData);
NSLog(#"Scanned ch conversion is: %#", text);
int createTransactionResult = -1;
createTransactionResult = [NWBarCodeHelper createTransactionRowFromBarCode:text];
if ([NWTillHelper isDebug] == 1) {
NSLog(#"mPOP delegate holds barcode: %#", stringWithData);
if(createTransactionResult != 0) {
NSLog(#"TransactionListView:mPOPDelegate:createTransactionFrombarCode failed with errorCode %i", createTransactionResult);
}
}
}
My Debug outputs shows the correct data as follows
2017-04-19 10:19:01.868198 NWMobileTill[3751:1638657] Scanned info as NSData was: <30393235 38333834 33393439 35310d0a>
2017-04-19 10:19:01.868439 NWMobileTill[3751:1638657] Scanned info as StringFromData was: 09258384394951
2017-04-19 10:19:01.868652 NWMobileTill[3751:1638657] Scanned ch conversion is: 09258384394951
2017-04-19 10:19:01.868979 NWMobileTill[3751:1638657] NWBarCodeHelper:createTransactionRowFromBarcode:barcode = 09258384394951
2017-04-19 10:19:01.875938 NWMobileTill[3751:1638657] NWBarcodeHelper:CreateTransactionRowFromBarcode: 0 or more than one row returned, basic data error, item count = 0
But as you can see the last rows shows the DB lookup failing, I KNOW the method is correct cause when I scan using the iPhone camera and passing that data to the same method it works just fine on the same barcode so it must be something with the string that is passed in from the USB scanner that is tricking me out but I am unable to understand why and I think NSLog is trying to help me but not showing me the encoded data or something?

Your string contains a \r\n at the end. Have a look at the following code:
unsigned char bytes[] = {0x30, 0x39, 0x32, 0x35, 0x38, 0x33, 0x38, 0x34, 0x33, 0x39 ,0x34, 0x39, 0x35, 0x31, 0x0d, 0x0a};
NSData *data = [NSData dataWithBytes:bytes length:16];
NSString *stringWithData = [[NSString alloc] initWithBytes:(char *)data.bytes length:data.length encoding:NSUTF8StringEncoding];
NSLog(#"%#", stringWithData); // 09258384394951
NSLog(#"%lu", (unsigned long)[stringWithData length]); // 16
// remove \r\n at the end which gets added by the barcode scanner
NSString *string = [stringWithData stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
NSLog(#"%#", string); // 09258384394951
NSLog(#"%lu", (unsigned long)[string length]); // 14
Or if you want to use your appendFormat approach you can just check if it is a valid digit before adding it to the string instead of removing it later.
To actually see the contents of your string you can either output the code point of each character in the string one by one or you can just set a breakpoint and Xcode will show it in the debugger:

Related

We are facing problem while creating compressed file of transferred socket data in hex string to converting to .tgz file in iOS App

We are facing problem while creating compressed file at iOS Device Document Directory, .tgz file is in Hex string transferring from pin-pad device to iPad iOS App at TCP socket layer. We used below HexToString function to convert that hex string and make file with .tgz. but at the end file is corrupted.
Can anyone please help us here, how to create compress file at iOS level with below hex string ? Please suggest us any code changes.
Note :- we had tried multiple NSStringEncoding technique, like ASCII, Unicode, Utf8, etc.
HEX String:-
1F8B08003058A8620203EDCA3B0A80301045D1594A5660265FB7E036065422A8453282CB57B4B2B112419CD3DCE2BD6966DD8F54925E4A975B62D22551EE741A2A5E199E80BBE8F1681DFDA5270BC6DB60D1398735A0092E0650082F580A53566A6F36F7BFFBFDA39A01841042FCD0062C8057FA00080000
we are using Xcode Version:13.1 and IOS Version 15.1 and above.
//Below function we used for creating .tgz file
//fileName here is abc.tgz which is compress file type
//content here is hex string mention aboved
+ (void)writeToLogFile:(NSString*)content fileName:(NSString*)fileNameString{
content = [NSString stringWithFormat:#"%#",content];
NSString *documentsDirectory = [NSHomeDirectory() stringByAppendingPathComponent:#"Documents"];
NSString *fileName = [documentsDirectory stringByAppendingPathComponent:fileNameString];
NSData *fileOriginalString = [self HextoString:content];
NSData *fileData = [fileOriginalString dataUsingEncoding:NSASCIIStringEncoding];
***//In alternative we also tried direct hex string to NSData type by calling below commentented method but it still failing
//NSData *fileData = [self dataFromHexString:content];***
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
NSError *error = nil;
[fileData writeToFile:fileName options:NSDataWritingAtomic error:&error];
NSLog(#"Write returned error: %#", [error localizedDescription]);
});
}
//Below function we used for Hex to String conversion
+(NSString*)HextoString:(NSString*)string{
#try{
NSMutableString * StrResult = [[NSMutableString alloc] init];
int i = 0;
while (i < [string length]){
NSString * hexChar = [string substringWithRange: NSMakeRange(i, 2)];
int value = 0;
sscanf([hexChar cStringUsingEncoding:NSASCIIStringEncoding], "%x", &value);
[StrResult appendFormat:#"%c", (char)value];
i+=2;
}
return StrResult;
}
#catch (NSException *exception){
[AELoggerManager info:[NSString stringWithFormat:#" %s EXCEPTION ::%#",__FUNCTION__,exception]];
}
}
+ (NSData *)dataFromHexString:(NSString *) string {
if([string length] % 2 == 1){
string = [#"0"stringByAppendingString:string];
}
const char *chars = [string UTF8String];
int i = 0, len = (int)[string length];
NSMutableData *data = [NSMutableData dataWithCapacity:len / 2];
char byteChars[3] = {'\0','\0','\0'};
unsigned long wholeByte;
while (i < len) {
byteChars[0] = chars[i++];
byteChars[1] = chars[i++];
wholeByte = strtoul(byteChars, NULL, 16);
[data appendBytes:&wholeByte length:2];
}
return data;
}

Send hexString Data through UDP

I'm developing an iOS app. I've come across a problem.
I am trying to send a hexString data through UDP to an wifi camera, which will response while getting correct data. My code is shown below. However I can't get any response from my wifi camera. (I'm using
https://github.com/robbiehanson/CocoaAsyncSocket)
NSString *sendMsg = #"6745000005000000000000000000000000000000000000001400000067450000140000000A";
NSData *bytes = [sendMsg dataUsingEncoding:NSUTF16BigEndianStringEncoding];
NSString *host = #"255.255.255.255";
[self.udpSocket sendData:bytes toHost:host port:ListenPort withTimeout:-1 tag:1];
Beside, I've try send my data through PacketSender (an app can send UDP data), which has a correct response.
enter image description here
Problem has been solved. The problem is while converting NSString to NSData. It's hex string which need to convert to NSData. Below is my code which works.
- (NSData *)dataFromHexString:(NSString *)hexString {
NSAssert((hexString.length > 0) && (hexString.length % 2 == 0), #"hexString.length mod 2 != 0");
NSMutableData *data = [[NSMutableData alloc] init];
for (NSUInteger i=0; i<hexString.length; i+=2) {
NSRange tempRange = NSMakeRange(i, 2);
NSString *tempStr = [hexString substringWithRange:tempRange];
NSScanner *scanner = [NSScanner scannerWithString:tempStr];
unsigned int tempIntValue;
[scanner scanHexInt:&tempIntValue];
[data appendBytes:&tempIntValue length:1];
}
return data;}

Message Sent To Deallocated Instantce

I'm using game center to send data between two players. For some reason I keep getting a deallocated instance message. Here's the code:
- (void)sendGameMove:(uint32_t)i andj:(NSString *)j {
MessageMove message;
message.message.messageType = kMessageTypeMove;
message.i = 1;
message.j = #"Testing 1 2 3s";
NSData *data = [NSData dataWithBytes:&message length:sizeof(MessageMove)];
MessageMove * messageMove = (MessageMove *) [data bytes];
NSLog(#"Message I: %i", messageMove->i);
NSLog(#"Message J: %#", messageMove->j);
[self sendData:data];
}
(I Filled in the i and j arguments for what i'm passing). In this method the NSLog statements both log what they're supposed to after creating the NSData object but when I sent that NSData object to the method [self sendData:data]:
- (void)sendData:(NSData *)data {
MessageMove * messageMove = (MessageMove *) [data bytes];
NSLog(#"Message I: %i", messageMove->i);
NSLog(#"Message J: %#", messageMove->j);
NSError *error;
BOOL success = [[GCHelper sharedInstance].match sendDataToAllPlayers:data withDataMode:GKMatchSendDataReliable error:&error];
if (!success) {
[self matchEnded];
}
}
In the NSLog statement the first one works fine so I get:
"Message I: 1"
in the console but for the second log statement I get :
"*** -[ respondsToSelector:]: message sent to deallocated instance"
the code to break down the data object is the exact same in the second method as in the first. Any ideas?
I'm guessing that MessageMove is a struct like:
typedef struct {
int i;
NSString *j;
} MessageMove;
The problem is that you're sending only the contents of the struct itself. In memory and on the network, it'd look something like this:
01000000 07FCA700
-----------------
i j
When the second device receives the message and tries to read the j pointer, it crashes because there's nothing there: that pointer was only valid on the origin device. The struct didn't even contain the contents of the string at all.
To fix this, you need to actually send the string in the message. Flexible array members are one way of storing a string directly in the struct:
typedef struct {
int32_t i; // explicit integer sizes are a good idea for network protocols
int32_t j_length;
char j[]; // the flexible array member
} MessageMove;
Send:
NSString *s = #"Testing 1 2 3s";
NSData *d = [s dataUsingEncoding:NSUTF8StringEncoding];
size_t messageSize = sizeof(MessageMove) + [d length];
MessageMove *mm = calloc(1, messageSize);
mm->i = 1;
mm->j_length = [d length];
memcpy(mm->j, [d bytes], [d length]);
[self sendData:[NSData dataWithBytes:mm length:messageSize]];
Receive:
MessageMove *mm = (MessageMove *)[data bytes];
assert(mm->j_length == [data length] - offsetof(MessageMove, j));
NSString *j = [[NSString alloc] initWithBytes:mm->j length:mm->j_length encoding:NSUTF8StringEncoding];
The assertion prevents reading past the end of the data buffer. offsetof is a macro from <stddef.h>.
For anything more complicated than this, I'd recommend serializing to and sending plist or JSON instead. They handle all the string copying details for you and let you send arrays and dictionary too.

uint8_t conversion to NSString

I need to convert the contents of a single element in my uint8_t buffer to an NSString so that I can display it to a label on my iPhone app. I read in the contents of buffer OK from a TCP connection. I am not getting the proper encoding so that an element's value can be displayed correctly. For example, if buffer[4] has the contents of 0xFD or 253, how do I best get that transferred to the label? (The label is data1) Or is there a much simpler way? Thanks.
uint8_t buffer[64];
uint8_t tinybuffer[1];
int len;
// Read in contents from TCP connection, log dump, and display to label.
len = [inputStream read:buffer maxLength:sizeof(buffer)];
if (len > 0) {
// Log dump
for(int i = 0; i < len; i++) {
NSLog(#"Returning byte %d : %x", i, buffer[i]);
}
NSLog(#"Finished Reading");
// Get data to the screen.
tinybuffer[0] = buffer[4];
NSString *str1 = [[NSString alloc] initWithBytes:tinybuffer length:1 encoding:NSUTF8StringEncoding];
_data1.text = str1;
NSString *str1 = [NSString stringWithFormat:#"%d", tinybuffer[0]];
should do what you want.

Converting an Sha256 hashed value into NSString

I have a requirement to integrate with a web service that serves as a login. The hash needs to be generated on the client. I am able to produce the correct hash as NSMutableData, but then I need to convert it to a string, without the spaces or brackets produced when the NSMutableData object is rendered as a string in the output console. I have read several posts, all seeming to say the same thing:
NSString *newstring = [[NSString alloc] initWithDSata:dataToConvert encoding:NSUTF8StringEncoding];
Unfortunately, this doesnt work for me. Using NSUTF8StringEncoding returns null. NSASCIIStringEncoding is even worse.
Here is my code:
NSString *password = [NSString stringWithFormat:#"%#%#", kPrefix, [self.txtPassword text]];
NSLog(#"PLAIN: %#", password);
NSData *data = [password dataUsingEncoding:NSASCIIStringEncoding];
NSMutableData *sha256Out = [NSMutableData dataWithLength:CC_SHA256_DIGEST_LENGTH];
CC_SHA256(data.bytes, data.length, sha256Out.mutableBytes);
NSString *preppedPassword = [[NSString alloc] initWithData:sha256Out encoding:NSASCIIStringEncoding];
NSLog(#"HASH: %#\n", preppedPassword);
How can I convert the NSMutableData to string?
My problem is that I need to from this
<7e8df5b3 17c99263 e4fe6220 bb75b798 4a41de45 44464ba8 06266397 f165742e>
to this
7e8df5b317c99263e4fe6220bb75b7984a41de4544464ba806266397f165742e
See How to convert an NSData into an NSString Hex string?
I use a slightly modified version myself:
#implementation NSData (Hex)
- (NSString *)hexRepresentationWithSpaces:(BOOL)spaces uppercase:(BOOL)uppercase {
const unsigned char *bytes = (const unsigned char *)[self bytes];
NSUInteger nbBytes = [self length];
// If spaces is true, insert a space every this many input bytes (twice this many output characters).
static const NSUInteger spaceEveryThisManyBytes = 4UL;
// If spaces is true, insert a line-break instead of a space every this many spaces.
static const NSUInteger lineBreakEveryThisManySpaces = 4UL;
const NSUInteger lineBreakEveryThisManyBytes = spaceEveryThisManyBytes * lineBreakEveryThisManySpaces;
NSUInteger strLen = 2 * nbBytes + (spaces ? nbBytes / spaceEveryThisManyBytes : 0);
NSMutableString *hex = [[NSMutableString alloc] initWithCapacity:strLen];
for (NSUInteger i = 0; i < nbBytes; ) {
if (uppercase) {
[hex appendFormat:#"%02X", bytes[i]];
} else {
[hex appendFormat:#"%02x", bytes[i]];
}
// We need to increment here so that the every-n-bytes computations are right.
++i;
if (spaces) {
if (i % lineBreakEveryThisManyBytes == 0) {
[hex appendString:#"\n"];
} else if (i % spaceEveryThisManyBytes == 0) {
[hex appendString:#" "];
}
}
}
return hex;
}
#end

Resources