Socket pass value as Hex - java

I am trying to pass a String value in socket to another server. The other server should receive the value in hex format.
i.e If my String is s = "600185838e" at the server it should receive as 60 01 85 83 8e, but these values what I sent are been converted to ASCII & is not in the desired format.
I am using socket connection
BufferedWriter wr = new BufferedWriter(new OutputStreamWriter(this.socket.getOutputStream()));
wr.write(messageBody);
wr.flush();
How can I send my String value similar as Hex value?
Thanking you all in advance

You should convert the hex string to byte array and then send it as byte array:
OutputStream out = this.socket.getOutputStream();
out.write(yourBytearray);
This is the method for converting the hex string to byte[] this is a copy from the link I gave, but I copied it here to make clear what I'm talking about:
public static byte[] hexStringToByteArray(String s) {
int len = s.length();
byte[] data = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
+ Character.digit(s.charAt(i+1), 16));
}
return data;
}

You can also try splitting the string into 2-character long Strings and convert them to individual bytes via Byte.parseByte(my2CharString , 16) and then send them
Here's some code that will do what you want, just replace System.out.println() with write() <- must write only one byte:
String output = "ffee101";
while(output.length() > 0){
String byteToWrite;
if(output.length() <= 2){
byteToWrite = output;
output = "";
}
else{
byteToWrite = output.substring(0,2);
output = output.substring(2);
}
byte b = (byte)Short.parseShort(byteToWrite, 16);
System.out.println(b);
}

Related

How can i revert back hexa value of certain language word to UTF-8

I have converted regional language word to hex value and saved to DB. But How can i decode that hexa value back to regional language word.
Here is my Kannada/Telugu word to Hex value conversion
public String toHex(String b){
String s="";
for (int i=0; i<b.length(); ++i) s+=String.format("%04X",b.charAt(i)&0xffff);
System.out.println("Converted value:::"+s); //0C1C0C3E0C350C3E
return s;
}
Word i have saved is జావా
Hex value saved in database is 0C1C0C3E0C350C3E
Decoded output am getting is : >5>
Is there any way to decode the hex value back to జావా
Code used to decode is
byte[] bytes = DatatypeConverter.parseHexBinary(itemName);
String s= new String(bytes, "UTF-8");
System.out.println("Utf..."+s);
Please help...
public String fromHex(String b) {
char[] cs = new char[b.length() / 4];
for (int i = 0; i < cs.length; ++i) {
int c = Integer.parseInt(b.substring(4 * i, 4 * i + 4), 16) & 0xFFFF;
cs[i] = (char) c;
}
return new String(cs);
}
This assumes that the conversion did not meddle with negative hex values.
Or exploiting that char is UTF-16BE:
byte[] bytes = DatatypeConverter.parseHexBinary(itemName);
return new String(bytes, StandardCharsets.UTF_16);
char[] data = hexData.toCharArray();
byte[] bytes = new byte[data.length/2];
for (int i = 0; i < data.length; i += 2) {
String val = new String(data, i, 2);
bytes[i/2] = Integer.valueOf(val, 16).byteValue();
}
String text = new String(bytes, "UTF8");
You might add sanity checks, e.g. that the length of the input-array is even, etc.

how to read a byte from a text file as an actual byte in hex instead of characters?

Im really unsure how to phrase my question, but here is the situation.
I have data in a text file, for example: 0x7B 0x01 0x2C 0x00 0x00 0xEA these values are a hex representation of ASCII symbols. I need to read this data and be able to parse and translate accordingly.
My problem so far is that ive tried using a scanner via something like scan.getNextByte() and was directed towards the post: [using java.util.Scanner to read a file byte by byte]
After changing the file input format to a fileinputstream i found that while doing something like fis.read(), this is returning 48, the ascii value for the character 0 in 0x7B.
I am looking for a way to interpret the data being read in has hex so 0x7B will be equivalent to "{" in ASCII.
Hope this is clear enough to all,
Thanks,
Since your bytes are delimited by spaces, you can just use a Scanner to read them:
try (Scanner scanner = new Scanner(Paths.get(filename))) {
while (scanner.hasNext()) {
int byteValue = Integer.decode(scanner.next());
// Process byteValue ...
}
}
I encourage you to read about the Integer.decode method and the Scanner class.
If you need scalable solution, try to write your own InputStream
Basic example:
class ByteStringInputStream extends InputStream {
private final InputStream inputStream;
public ByteStringInputStream(InputStream inputStream) {
this.inputStream = inputStream;
}
private boolean isHexSymbol(char c) {
return (c >= '0' && c <= '9')
|| (c >= 'A' && c <= 'F')
|| (c == 'x');
}
#Override
public int read() throws IOException {
try {
int readed;
char[] buffer = new char[4];
int bufferIndex = 0;
while ((readed = inputStream.read()) != -1 && bufferIndex < 4) {
if (isHexSymbol((char) readed)) {
buffer[bufferIndex] = (char) readed;
}
bufferIndex++;
}
String stringBuffer = new String(buffer);
if (!stringBuffer.matches("^0x[0-9A-F]{2}$")) {
throw new NumberFormatException(stringBuffer);
}
return Integer.decode(stringBuffer);
} catch (Exception ex) {
inputStream.close();
throw new IOException("<YOUR_EXCEPTION_TEXT_HERE>", ex);
}
}
}
Usage:
ByteStringInputStream bsis = new ByteStringInputStream(new BufferedInputStream(System.in));
//you can use any InputStream instead
while (true) {
System.out.println(bsis.read());
}
Demo:
>0x7B 0x01 0x2C 0x00 0x00 0xEA
123
1
44
0
0
234
If you're in a position to use external libraries, the Apache Commons Codec library has a Hex utility class that can turn a character-array representation of hex bytes into a byte array:
final String hexChars = "0x48 0x45 0x4C 0x4C 0x4F";
// to get "48454C4C4F"
final String plainHexChars = hexChars.replaceAll("(0x| )", "");
final byte[] hexBytes = Hex.decodeHex(plainHexChars.toCharArray());
final String decodedBytes = new String(hexBytes, Charset.forName("UTF-8"));

String toByte and reverse, not bijective if bytes are modified

Following Code changes every byte of a string and creates a new string.
public static String convert(String s) {
byte[] bytes = s.getBytes();
byte[] convert = new byte[bytes.length];
for (int i = 0; i < bytes.length; i++) {
convert[i] = (byte) ~bytes[i];
}
return new String(convert);
}
Question: Why is convert() not bijective?
convert(convert("Test String")).equals("Test String") === false
when you use the constructor String(byte[]), it doesn't necesarily takes one letter per byte, it takes the default charset; if it is, say, UTF-8, then the constructor will try to decode some chars from two or three bytes rather than just one.
As you are using bit-complement to transform byte by byte, the result could be different when you apply the default charset.
If you are using only ASCII chars, you could try this version of your function:
// ONLY if you use ASCII as Charset
public static String convert(String s) {
Charset ASCII = Charset.forName("ASCII");
byte[] bytes = s.getBytes(ASCII);
byte[] convert = new byte[bytes.length];
for (int i = 0; i < bytes.length; i++) {
convert[i] = (byte) (~bytes[i] & 0x7F);
}
return new String(convert, ASCII);
}
Because information is lost when you converted the manipulated byte to String and vice versa
In this line below
for (int i = 0; i < bytes.length; i++) {
convert[i] = (byte) ~bytes[i];
}
return new String(convert);
If you go inside the implementation of String to byte conversion and viceversa you will find that CharSet and encoding are involved.
Read about them and you will get detailed explanation of this behavior.

From a byte[] in a string to a string?

I have a problem.
I sent some data over a socket in string form. With some substringing, I managed to get the byte[] in String form [B#58596d12. Now, my question is, this is a string. How do I convert it back to a byte array after which I can use String result = new String(byteArray);?
I tried casting the String to byte[], but that's not allowed.
Google only came up with the usual .getBytes() (which I can't use since they already are bytes) and new String(someByteArray)
This is what's being sent:
byte[] all = Files.readAllBytes(f.toPath());
this.out.println(destinationOfFile + "/" + file.getName() + "*" + all);
And this is what's being received:
private void writeToFile(String str) {
String file = str.substring(0, str.indexOf("*"));
String write = str.substring(str.indexOf("*")+1);
EDIT: I managed to do it in another way.
Instead of getting all the bytes from the file, I wen't through it line by line, sending each line over the socket. In the client, I store the data in a HashMap and when it receives "Done sending File" it writes all the strings to the file.
If you want to store raw bytes in a String, you should use an encoding designed for this purpose, such as Base64. Take a look at the Commons Codec library and Base64 class.
I'm using this code to convert String-Byte[], but I'm not sure if it will help you because I don't know if you have rawBytes as source or a Java-String. Could you clarify?
public static String byteToHexString(byte b) {
String result = "";
result += Integer.toHexString((int)(b >> 4) & 0xf);
result += Integer.toHexString((int)(b) & 0xf);
return result;
}
public static String bytesToHexString(final byte[] byteArray) {
if (byteArray == null) {
return null;
}
String result = "";
for (int i = 0; i < byteArray.length; ++i) {
result += byteToHexString(byteArray[i]);
}
return result;
}
public static byte[] hexStringToBytes(final String hexString) {
if (hexString == null) {
return null;
}
byte[] result = new byte[hexString.length() / 2];
for (int idx = 0; idx < result.length; ++idx) {
int strIdx = idx * 2;
result[idx] = (byte) ((Character.digit(hexString.charAt(strIdx), 16) << 4)
+ Character.digit(hexString.charAt(strIdx + 1), 16));
}
return result;
}
Edit:
If you are converting String-byte[] and byte[]-String I would recommend using the charset or charsetname parameter for String.getBytes() and for the String-constructor. For example:
byte[] bytes = "text".getBytes("UTF-8");
String text = new String(bytes, "UTF-8");
Remember not every platform or jvm may support the same charsets. For a list of charsets have a look here.
If you are reading bytes from a File and want to interpret them as String, you also have to care about using the right charset.

How can I write a sequence of strings and then a byte array to a file?

I want to write first a sequence of strings and then a sequence of bytes into a file, using Java. I started by using FileOutputStream because of the array of bytes. After searching the API, I realised that FileOutputStream cannot write Strings, only ints and bytes, so I switched to DataOutputStream. When I run the program, I get an exception. Why?
Here's a portion of my code:
try {
// Create the file
FileOutputStream fos;
DataOutputStream dos; // = new DataOutputStream("compressedfile.ecs_h");
File file= new File("C:\\MyFile.txt");
fos = new FileOutputStream(file);
dos=new DataOutputStream(fos);
/* saves the characters as a dictionary into the file before the binary seq*/
for (int i = 0; i < al.size(); i++) {
String name= al.get(i).name; //gets the string from a global arraylist, don't pay attention to this!
dos.writeChars(name); //saving the name in the file
}
System.out.println("\nIS SUCCESFULLY WRITTEN INTO FILE! ");
dos.writeChars("><");
String strseq;
/*write all elements from the arraylist into a string variable*/
strseq= seq.toString();
System.out.println("sTringSeq: " + strseq);
/*transpose the sequence string into a byte array*/
byte[] data = new byte[strseq.length() / 8];
for (int i = 0; i < data.length; i++) {
data[i] = (byte) Integer.parseInt(strseq.substring(i * 8, (i + 1) * 8), 2);
dos.write(data[i]);
}
dos.flush();
//Close the output stream
dos.close();
} catch(Exception e){}
The problem with your code is that the last for loop was counting over the wrong number of bytes. The code below fixes your problem writing your test data to a file. This works on my machine.
public static void main(String[] args) {
ArrayList<String> al = new ArrayList<String>();
al.add("String1");
al.add("String2");
try {
// Create the file
FileOutputStream fos = new FileOutputStream("MyFile.txt");
DataOutputStream dos = new DataOutputStream(fos);
/* saves the characters as a dictionary into the file before the binary seq */
for (String str : al) {
dos.writeChars(str);
}
System.out.println("\nIS SUCCESFULLY WRITTEN INTO FILE! ");
dos.writeChars("><");
String strseq = "001100111100101000101010111010100100111000000000";
// Ensure that you have a string of the correct size
if (strseq.length() % 8 != 0) {
throw new IllegalStateException(
"Input String is cannot be converted to bytes - wrong size: "
+ strseq.length());
}
int numBytes = strseq.length() / 8;
for (int i = 0; i < numBytes; i++) {
int start = i * 8;
int end = (i + 1) * 8;
byte output = (byte) Integer.parseInt(strseq.substring(start, end), 2);
dos.write(output);
}
dos.writeChars("> Enf of File");
dos.flush();
// Close the output stream
dos.close();
} catch (Exception e) {
e.printStackTrace();
}
}
The approach of writing bytes directly to a test file does have a few problems (I assume that it's a text file in that your test file name ends with .txt), the most obvious one being that some text editors don't handle/display null characters very well (your last test byte was: 00000000 or null). If you want to see the bytes as readable bytes then you could investigate encoding them using Base64 encoding.
Line:
data[i] = (byte) Integer.parseInt(strseq.substring(i * 8, (i + 1) * 8), 2);
looks very suspiciously...
can you provide move details about strseq and its value?
What about this code ?
this code :
byte[] data = new byte[strseq.length() / 8];
for (int i = 0; i < data.length; i++) {
data[i] = (byte) Integer.parseInt(strseq.substring(i * 8, (i + 1) * 8), 2);
dos.write(data[i]);
}
becomes
byte[] data = strseq.getBytes();
With the FileWriter class you have a nice abstraction of a file writing operation.
May this class can help you to write your file...
You can substitute the other OutputStreams by only this class. It have all the methods of you want for write a string and a byte array in a file.

Categories

Resources