I have a string which is decoded by windows-1256 like this
A0C8E5CFC7CF2DC7DDDEE5ED
I want to encode that to UTF-8 in android.
I tried to encode like this
String input = "A0C8E5CFC7CF2DC7DDDEE5ED";
try {
String message = new String(input.getBytes(), "windows-1256");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
but I didn't see what expected expression.
I wrote some codes in C# for this purpose ,like this
int index = 0;
while (response[index] != 0x00)
result = result + Encoding.GetEncoding("windows-1256").GetString(response, index++, 1);
it works fine.
does anyone have any idea how to solve it?
Thanks in advance
First you convert your hex string into byte array. See this post.
Then, convert the byte array byte[] into UTF-8 using
String str = new String(byte[], "windows-1256");
UTF-8 is the native android encoding. Hope it helps.
Related
I am using AES (Rijndael) encryption method to encrypt a string. The transformation used is ECB_PKCS5PADDING. It will return a base64 encoded string. I had decoded the string using base64 and converted to hex using a function. The code snippets are attached below.
private void encrptString()
{
sample = "<xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
String encrypt = Encoder.BuilderAES()
.message(sample)
.method(AES.Method.AES_ECB_PKCS5PADDING)
.key("xxxxxxxxxxxxxx")
.keySize(AES.Key.SIZE_128)
.encrypt();
System.out.println("encrypt"+encrypt);
String stringFromBase = new String(Base64.decode(encrypt,Base64.DEFAULT));
System.out.println("base64"+stringFromBase.trim());
String hex= null;
try {
hex = toHex(stringFromBase);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
Toast.makeText(this, hex, Toast.LENGTH_SHORT).show();
System.out.println("hex"+hex.trim());
}
public String toHex(String arg) throws UnsupportedEncodingException {
return String.format("%040x", new BigInteger(1, arg.getBytes("UTF-8")));
}
base64 Input String:
O3Kmyftikp0lY/8SVWMiLFCn9sdQX7HauqdLZXcE+jkVcZH7kfPD/
jSLIC2wlP1iQTaiynoaW8A7L1INEYunkmCWT2eVwumwouHVT7d5Kq
/sqEcB9/9pyyAuSjrQxtCgJlHm7dlvt0lVEHD2pHnEAhZTRtuuy6b
8MNI7W4jLn+/ZNEqZxdJll26a52D7ceFv
Expected output:
3b72a6c9fb62929d2563ff125563222c50a7f6c7505fb1dabaa74b657704fa391571
91fb91f3c3fe348b202db094fd624136a2ca7a1a5bc03b2f520d118ba79260964f67
95c2e9b0a2e1d54fb7792aafeca84701f7ff69cb202e4a3ad0c6d0a02651e6edd96fb
749551070f6a479c402165346dbaecba6fc30d23b5b88cb9fe
fd9344a99c5d265976e9ae760fb71e16f
I am getting this output:
3b72efbfbdefbfbdefbfbd62efbfbdefbfbd2563efbfbd125563222c50efbfbdefbfbd
efbfbd505fefbfbddabaefbfbd4b657704efbfbd391571efbfbdefbfbdefbfbdefbfbd
efbfbd34efbfbd202defbfbdefbfbdefbfbd624136efbfbdefbfbd7a1a5befbfbd3b2f
520d11efbfbdefbfbdefbfbd60efbfbd4f67efbfbdefbfbde9b0a2efbfbdefbfbd4fef
bfbd792aefbfbdefbfbd4701efbfbdefbfbd69efbfbd202e4a3aefbfbdefbfbdd0a026
51efbfbdefbfbdefbfbd6fefbfbd49551070efbfbd79efbfbd02165346dbaecba6efbf
bd30efbfbd3b5befbfbdcb9fefbfbdefbfbd344aefbfbdefbfbdefbfbd65efbfbd6eef
bfbdefbfbd60efbfbd
I'd leave the decoded Base64 as a byte[] and encode that:
String b64 = "O3Kmyftikp0lY/8SVWMiLFCn9sdQX7HauqdLZXcE+jkVcZH7kfPD/ jSLIC2wlP1iQTaiynoaW8A7L1INEYunkmCWT2eVwumwouHVT7d5Kq /sqEcB9/9pyyAuSjrQxtCgJlHm7dlvt0lVEHD2pHnEAhZTRtuuy6b 8MNI7W4jLn+/ZNEqZxdJll26a52D7ceFv";
StringBuilder hexStringBuilder = new StringBuilder();
for (byte b : Base64.decode(b64, Base64.DEFAULT)) {
hexStringBuilder.append(String.format("%02x", b));
}
String hex = hexStringBuilder.toString()
You should base64-decode to a byte array (byte[]) and then hex encode the byte array to a string.
I am using the write() method in order to write in a file of the external storage. This method only accepts byte[] as an input. I have tried passing a String and I get an error message ("The method write(int) in the type FileOutputStream is not applicable for the arguments String"). If I pass an int, I don't get error but in the file nothing is written. The value I get from calling getNumSentPackets() is an int and I need to convert it to byte[]. I have been looking at other questions already answered here and I have tried the ByteBuffer option but the result I get in the file is not what I want, this means, I don't get the number of sent packets. Can anybody help me, please?
This is my code:
public void createFile(String name) {
try {
String filename = name;
File myFile = new File(Environment.getExternalStorageDirectory(), filename);
if (!myFile.exists())
myFile.createNewFile();
String title = "FLOODING RESULTS FILE\n\n";
String sent = "Number of sent packets\n";
FileOutputStream fos;
byte[] data = title.getBytes();
byte[] intSent = sent.getBytes();
int numSent = mSender.getNumSentPackets();
byte[] numSentBytes = ByteBuffer.allocate(10).putInt(numSent).array();
try{
fos = new FileOutputStream(myFile);
fos.write(data);
fos.write(intSent);
fos.write(numSentBytes);
fos.flush();
fos.close();
} catch (Exception e) {
e.printStackTrace();
}
} catch (IOException e) {
e.printStackTrace();
}
}
public static int getNumSentPackets() {
return nSentPackets;
}
The expected output file would be as follows:
FLOODING RESULTS FILE
Number of sent packets 200
200 is only an example, meaning with this that I would like to see there a number which would correspond to the total number of sent packets.
Thank you in advance.
As I am a lazy developer, I like to use the existing facilities in my languages of choice, for example, for java, a PrintWriter.
public void createFile(String filename) {
try {
File myFile = new File(Environment.getExternalStorageDirectory(), filename);
PrintWriter out = new PrintWriter(myFile); // this will create the file if necessary
out.println("FLOODING RESULTS FILE");
out.println();
out.print("Number of sent packets ");
out.println(mSender.getNumSentPackets());
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
This is much easier to read and maintain than your current approach, and looks more idiomatic.
ByteBuffer.allocate(capacity).putInt(yourInt).array();
The text representation of "200" requires you to write 3 characters. All files are just a bunch of bytes in the end so there needs to be a mapping from character to some byte value. Assuming ASCII(*) the data to write into the file would be
// '2','0','0'
byte[] textVersion = { 50, 48, 48 }
int on the other hand is a 32bit numeric value, i.e. has 4 bytes and 200 is equivalent to
byte[] intVersion = { 0, 0, 0, 200 }
When using a ByteBuffer, you'll get this. If you write that into a file and a text viewer tries to display that it would display something like ◻◻◻Č if you're lucky. A 0 is actually a non printable control character and therefore often either skipped when printing or replaced with strange looking character like boxes. The 200 would be equivalent to Č in Windows-CP1250. It has no meaning on it's own when interpreted as UTF8 - it's the start of a 2 byte sequence and so the next 2 byte are required to determine which character to display.
You could have used
String.valueOf(200).getBytes( /* you should specify which encoding to use here */ );
which will create the "200" string first, then return you the required bytes for those 3 characters.
You should however use Java's character based IO facility: The numerous (and confusing) Reader & Writer implementations. They all(*^2) wrap an InputStream or OutputStream in the end and do the text to byte conversion for you.
PrintWriter is probably the most convenient to use but not without flaw: https://stackoverflow.com/a/15803472/995891
FileWriter should be avoided because you can't specify the encoding
The longer alternative route would be
BufferedWriter writer = new BufferedWriter(
new OutputStreamWriter(
new FileOutputStream(file), encoding));
writer.write("Hello ");
writer.write(String.valueOf(200));
writer.newLine();
(*) most encodings are ASCII compatible for the first 127 characters which basically covers normal english text.
(*^2) nothing forces a Writer to output the characters into a stream, e.g. StringWriter. But they are used mostly that way.
I am trying to implement an OTP generator for Blackberry OS10. I already use the reference implementation on Android side, you can find it here:
So I would like to convert it to C++ / QNX code and I have some troubles with hexadecimal conversion...
In java:
private static byte[] hexStr2Bytes(String hex){
// Adding one byte to get the right conversion
// Values starting with "0" can be converted
byte[] bArray = new BigInteger("10" + hex,16).toByteArray();
// Copy all the REAL bytes, not the "first"
byte[] ret = new byte[bArray.length - 1];
for (int i = 0; i < ret.length; i++)
ret[i] = bArray[i+1];
return ret;
}
In QNX:
QByteArray msg = QByteArray::fromHex(m.toLocal8Bit());
Problem is "m" start with '00' and so my final msg array is 0 length...
For example I try to encode the hex qstring:0000000002ca4e32
In blackberry: m=""
In Android: m="?M?"
So you can someone explain me how to deal with such a conversion ?
Thanks!
What I would do is to translate your Java function to plain C++, i.e. not QT format. Then adapt data type to QT.
I got to port some chat code from iOS to Android. Before sending the chat message to the socket, the iOS code uses the NSNonLossyASCIIStringEncoding class as parameter of the NSString::dataUsingEncoding.
How would you do it in Android? Same question about the opposite decoding.
Without doing that, for instance, the line breaks disappear in the message received on the other mobile.
Code on iOS:
NSData *data1 = [myStringTosend dataUsingEncoding:NSNonLossyASCIIStringEncoding];
NSString *goodValue = [[[NSString alloc] initWithData:data1 encoding:NSUTF8StringEncoding] autorelease];
And decoding:
NSData *data = [[NSData alloc] initWithData:[response dataUsingEncoding:NSASCIIStringEncoding]];
So far (and not correct), encoding on the Android side:
OutputStream os = socket.getOutputStream();
os.write(request.getBytes("UTF-8"));
os.flush();
And decoding:
while ((bytesRead = is.read(buffer, 0, BUFFER_SIZE)) >= 0) {
if (bytesRead > 0) response.append(new String(buffer, 0, bytesRead, "UTF-8"));
if (bytesRead < BUFFER_SIZE) break;
}
#portforwardpodcast is absolutely correct that you should, if possible, avoid ASCII encoding your utf8 and instead set up your stack to handle/store utf8 directly. That said, if you don't have the ability to change the behavior, the following code may be helpful.
While there's no published explanation of how NSNonLossyASCIIStringEncoding works, based on its output it looks like:
Bytes in the extended ASCII range (decimal values 128 - 255) are escaped using an octal encoding (e.g. ñ with decimal value 241 -> \361)
Non-ASCII code points are escaped in two byte chunks using a hex encoding (e.g. 😥 which takes up 32 bits with decimal value 128549 -> \ud83d\ude25)
So to encode:
public static String encodeToNonLossyAscii(String original) {
Charset asciiCharset = Charset.forName("US-ASCII");
if (asciiCharset.newEncoder().canEncode(original)) {
return original;
}
StringBuffer stringBuffer = new StringBuffer();
for (int i = 0; i < original.length(); i++) {
char c = original.charAt(i);
if (c < 128) {
stringBuffer.append(c);
} else if (c < 256) {
String octal = Integer.toOctalString(c);
stringBuffer.append("\\");
stringBuffer.append(octal);
} else {
String hex = Integer.toHexString(c);
stringBuffer.append("\\u");
stringBuffer.append(hex);
}
}
return stringBuffer.toString();
}
And to decode (this can be made more efficient by parsing the two types of encodings in lock step, rather as two separate passes):
private static final Pattern UNICODE_HEX_PATTERN = Pattern.compile("\\\\u([0-9A-Fa-f]{4})");
private static final Pattern UNICODE_OCT_PATTERN = Pattern.compile("\\\\([0-7]{3})");
public static String decodeFromNonLossyAscii(String original) {
Matcher matcher = UNICODE_HEX_PATTERN.matcher(original);
StringBuffer charBuffer = new StringBuffer(original.length());
while (matcher.find()) {
String match = matcher.group(1);
char unicodeChar = (char) Integer.parseInt(match, 16);
matcher.appendReplacement(charBuffer, Character.toString(unicodeChar));
}
matcher.appendTail(charBuffer);
String parsedUnicode = charBuffer.toString();
matcher = UNICODE_OCT_PATTERN.matcher(parsedUnicode);
charBuffer = new StringBuffer(parsedUnicode.length());
while (matcher.find()) {
String match = matcher.group(1);
char unicodeChar = (char) Integer.parseInt(match, 8);
matcher.appendReplacement(charBuffer, Character.toString(unicodeChar));
}
matcher.appendTail(charBuffer);
return charBuffer.toString();
}
Don't use NSNonLossyASCIIStringEncoding, use utf-8 encoding. I just solved this problem myself on ios+android+java spring backend, and it took me around 4 full days to figure everything out. Android can't display emojis, but this gives me full character support in almost all (or all not sure) languages. Here are the articles that helped me:
Must Read: http://blog.manbolo.com/2012/10/29/supporting-new-emojis-on-ios-6 http://blog.manbolo.com/2011/12/12/supporting-ios-5-new-emoji-encoding
See the hex bytes of a string inside the DB: How can I see raw bytes stored in a MySQL column?
Details about how to setup MySQL: http://technovergence-en.blogspot.com/2012/03/mysql-from-utf8-to-utf8mb4.html
In depth FAQ of utf8- http://www.unicode.org/faq/utf_bom.html#utf8-4
Details about the difference from notation: \ud83d\udc7d and hex value in memory: 0xF09F91BD http://en.wikipedia.org/wiki/UTF-8#Description
Use this to copy and paste characters in to see real hex byte values (works for emojis): http://perishablepress.com/tools/utf8-hex/index.php
Get Spring to support utf8 in urls (for GET params) http://forum.springsource.org/showthread.php?93728-RequestParam-doesn-t-seem-to-be-decoded Get Parameter Encoding http://forum.springsource.org/showthread.php?112181-Unable-to-Override-the-Spring-MVC-URL-decoding-which-uses-default-quot-ISO-8859-1-quot
My answer code is equivalent to IOS NSNonLossyASCIIStringEncoding for Android.
In your gradle put below depandancy.
compile 'org.apache.commons:commons-lang3:3.4'
then Put method to your Utils Class Like this
public static String encode(String s)
{
return StringEscapeUtils.escapeJava(s);
}
public static String decode(String s)
{
return StringEscapeUtils.unescapeJava(s);
}
then Simply call this method where you want to encode string or decode String like this
//for encode
String stencode = Utils.encode("mystring");
//for decode
String stdecode = Utils.decode("mystring")
All I need is convert byte[] to String. Then do something with that string and convert back to byte[] array. But in this testing I'm just convert byte[] to string and convert back to byte[] and the result is different.
to convert byte[] to string by using this:
byte[] byteEntity = EntityUtils.toByteArray(entity);
String s = new String(byteEntity,"UTF-8");
Then i tried:
byte[] byteTest = s.getBytes("UTF-8");
Then i complared it:
if (byteEntity.equals(byteTest) Log.i("test","equal");
else Log.i("test","diff");
So the result is different.
I searched in stackoverflow about this but it doesn't match my case. The point is my data is .png picture so the string converted is unreadable. Thanks in advance.
Solved
Using something like this.
byte[] mByteEntity = EntityUtils.toByteArray(entity);
byte[] mByteDecrypted = clip_xor(mByteEntity,"your_key".getBytes());
baos.write(mByteDecrypted);
InputStream in = new ByteArrayInputStream(baos.toByteArray());
and this is function clip_xor
protected byte[] clip_xor(byte[] data, byte[] key) {
int num_key = key.length;
int num_data = data.length;
try {
if (num_key > 0) {
for (int i = 0, j = 0; i < num_data; i++, j = (j + 1)
% num_key) {
data[i] ^= key[j];
}
}
} catch (Exception ex) {
Log.i("error", ex.toString());
}
return data;
}
Hope this will useful for someone face same problem. Thanks you your all for helping me solve this.
Special thanks for P'krit_s
primitive arrays are actually Objects (that's why they have .equals method) but they do not implement the contract of equality (hashCode and equals) needed for comparison. You cannot also use == since according to docs, .getBytes will return a new instance byte[]. You should use Arrays.equals(byteEntity, byteTest) to test equality.
Have a look to the answer here.
In that case my target was transform a png image in a bytestream to display it in embedded browser (it was a particular case where browser did not show directly the png).
You may use the logic of that solution to convert png to byte and then to String.
Then reverse the order of operations to get back to the original file.