Convert an NSArray of byte values into an NSData - nsarray

I have an array returned from a web service containing byte values (non binary format, i.e. 0-255). These represent a thumbnail image. I want need to create an NSData object from these values. How can I do this?

+ (id)dataWithBytes:(const void *)bytes length:(NSUInteger)length is your friend:
void bytesToNSDataExample() {
unsigned char bytes[] = {'h', 'e', 'l', 'l', 'o'};
NSData *data = [NSData dataWithBytes:bytes length:5];
NSString *string = [[NSString alloc] initWithData:data encoding:NSISOLatin1StringEncoding];
NSLog(#"%#", string);
// if data was a image like in your case, you would probably do something like this:
NSImageRep *imgRep = [NSBitmapImageRep imageRepWithData:data];
}

Related

Conversion from WCHAR to const unsigned char

I am a wix application packager. I am quite new to C++ and I am stuck with the below issue.
In my code, I am trying to convert wchar to const unsigned char. I have tried quite a few solutions that I got on the Internet, but I am unable to do it.
WCHAR szabc[888] = L"Example";
const unsigned char* pText = (const unsigned char*)szabc;
For your reference, the value of szabc is hard-coded, but ideally it is fetched as user input during installation of my code. szabc needs to be converted to const unsigned char as operator= doesn't seem to be working for conversion.
I am not getting any compilation error, but when I run this code, only the first character of szabc is being assigned to pText, I want the whole value of szabc to be assigned to pText.
As the value of pText is a user account password in a real time scenario, and it will be passed to a method which encrypts the value of the password.
Since you neglected to mention your OS, I am assuming it is Windows. You need WideCharToMultiByte or the standard wcstombs functions.
Note that both will determine the target encoding using system settings, so results will vary across computers. If possible, convert to UTF-8 or tell your users to stay away from special characters.
operator= cannot assign a value to a variable of an unrelated type. Which is why you cannot assign a WCHAR[] directly to an unsigned char*.
However, the real problem is with how the pointed data is being interpreted. You have a 16-bit Unicode string, and you are trying to pass it to a method that clearly wants a null-terminated 8-bit string instead.
On Windows, WCHAR is 2 bytes, and so the 2nd byte in your Unicode string is 0x00, eg:
WCHAR szabc[] = {L'E', L'x', L'a', L'm', L'p', L'l', L'e', L'\0'};
Has the same memory layout as this:
BYTE szabc[] = {'E', 0x00, 'x', 0x00, 'a', 0x00, 'm', 0x00, 'p', 0x00, 'l', 0x00, 'e', 0x00, '\0', 0x00};
This is why the method appears to see only 1 "character". It stops reading when it encounters the 1st 0x00 byte.
Thus, a simple pointer type-cast will not suffice. You will need to either:
use an 8-bit string to begin with, eg:
CHAR szabc[888] = "Example";
unsigned char* pText = (unsigned char*)szabc;
// use pText as needed...
convert the Unicode data at runtime, using WideCharToMultiByte() or equivalent, eg:
WCHAR szabc[888] = L"Example";
int len = WideCharToMultiByte(CP_ACP, 0, szabc, -1, NULL, 0, NULL, NULL);
CHAR szConverted = new char[len];
WideCharToMultiByte(CP_ACP, 0, szabc, -1, szConverted, len, NULL, NULL);
unsigned char* pText = (unsigned char*)szConverted;
// use pText as needed...
delete[] szConverted;

C++ strcpy_s throws error when copying to new char array

My goal is to generate a new array with the correct amount of spots and copy an old character array into it.
When using strcpy_s, an exception is thrown. I can not figure out why the exception is being thrown which states that the Buffer is too small. I can not use vectors or strings. How can I fix this using strcpy_s and char arrays?
char str[4] = { 't', 'e', 's', 't' };
int allocated = 4;
char * reservedString = new char[allocated]();
strcpy_s(reservedString, allocated, str);
EDIT:
Changing my code to add one to the array gives me the same "buffer too small" exception.
char str[4] = { 't', 'e', 's', 't' };
int allocated = 4;
char * reservedString = new char[allocated+1]();
strcpy_s(reservedString, allocated, str);
EDIT 2:
As someone commented str needed to be set to 5 in size and have a null terminator included. Thank you this fixed my problem.
Updated code:
char str[5] = { 't', 'e', 's', 't', '\0'};
int allocated = 5;
char * reservedString = new char[allocated]();
strcpy_s(reservedString, allocated, str);
You need five characters to store the zero-terminated string "test". Your str array is just four characters, with no zero terminator. If you want a zero-terminator, declare it like this:
char str[] = "test";
Then you need of course
int allocated = 5;
And after that:
char * reservedString = new char[allocated];
strcpy_s(reservedString, allocated, str);
char str[4] = { 't', 'e', 's', 't' }; is a 4-byte array in the memory. It is not a string, and it is completely random where a "trailing" zero will occur after these 4 bytes, and an arbitrary amount of other data in between.
However, strcpy_s() expects copying a zero-terminated string, just one of the extras it does is checking if the source string will fit into the destination. It will not, that is why you get the error.
[...] the following errors are detected at runtime and call the currently installed constraint handler function:
* src or dest is a null pointer
* destsz is zero or greater than RSIZE_MAX
* destsz is less or equal strnlen_s(src, destsz); in other words, truncation would occur
* overlap would occur between the source and the destination strings
You get the third one, a truncation of the "garbage" bytes would occur.
str is not a string. A string is a sequence of non-NUL characters, terminated by NUL.
You should pass the size of the buffer to strcpy_s(), not the maximum string-size (which is one less).
That is, if you should use strcpy_s() at all. You shouldn't.
Use strcpy(), or as you already have the exact size, memcpy() or std::copy_n().
As a side-note, zeroing memory just to turn around and overwrite it is a pointless waste.
You are not allocating the proper memory:
char str[4] = { 't', 'e', 's', 't' };
It allocates 5 bytes, 4 for each character plus the null terminator.---
Do:
char str[4] = { 't', 'e', 's', 't' };
char * reservedString = new char[5]();
strcpy_s(reservedString, allocated, str);
Or:
char str[4] = { 't', 'e', 's', 't' };
char * reservedString = new char[5]();
strcpy(reservedString, str);

An array output

If I set an array variable a[]="abc" , and then set another array variable b[]={'d','e','f'} ,my last output code is printf("%s",b) ,it's output value is "defabc",why? My output is array b but the output value will output array b first and then output array a second.
The whole code is on bellow.
#include<stdio.h>
void main(){
char a[]="abc";
char b[]={'d','e','f'};
printf("%s",b);
}
The output is "defabc".
And the string length of array b is 7 why?
In C all strings should be null (i.e. \0) terminated, so your second variable should look like the following:
char b[] = {'d', 'e', 'f', '\0'};
You might be curious why "defabc" is printed with your code. The answer is, all local variables are stored in a stack-based memory layout. So your memory layout looks like this:
|'d' | <-- b
|'e' |
|'f' |
|'a' | <-- a
|'b' |
|'c' |
|'\0'|
Also note that printf("%s", ...) reads until it reach a \0, so printf("%s", a) works as expected but printf("%s", b) prints "defabc".
You need a null terminator at the end of both strings. your second string does not have it as its defined as an array of characters.
Correct ways to declare a string
char b[] = { 'd', 'e', 'f', '\0' }; // null terminator required
or
char b[] = "def"; // null terminator added automatically
So, this code will print def as output
#include <stdio.h>
int main() {
char a[] = "abc";
char b[] = { 'd', 'e', 'f', '\0' };
printf("%s", b);
return 0;
}

copy all the nsdata bytes into a char* error

I have the following situation:
NSData *audioData = [NSData dataWithContentOfFile:[fileURL path] options:0 error:nil];
I need to send this audioData to the server using a method that accepts as input parameter pj_str_t value;
So I did:
unsigned char *getBytes = (unsigned char*)[audioData bytes]; //here insteand of 10600 bytes I only have 4 bytes.
value=pj_str((char*)getBytes);
The value is a string from 4 bytes. What am I doing wrong?
Beware that audio data can contain 0's and the pj_str(char *) function you're using will mistake them for the end of the string. Try this:
pj_str_t string;
pj_strset(&string, getBytes, [audioData length]);

get data from hexadecimal character

I have the code as below:
NSString* str = #"π";
const char* chr = [str UTF8String];
The value for chr is "\xcf\x80" which is a sequence of hexadecimal charter.
To write as RTF file I need to extract the value excluding "\x" from this hexadecimal character.
How should I do to get the data?
Regards
In C the char type is an integral type so you can produce a hexadecimal representation of a character just as you would any other integer value - using the %x format specifier. To convert a complete C string to a string of hexadecimal just iterate over the string and build up the result. Rough code, typed directly into answer so expected errors:
NSString *str = ...
const char *cStr = [str UTF8String];
NSMutableString *hexStr = [NSMutableString new]; // for result
while( *cStr ) // loop while cStr is not pointing at a null char
{
[hexStr appendFormat:#"%02x", *cStr++]; // %02x - zero fill, width 2, hex
}