I tried the different ways to convert hex to byte, there are four methods in the code, three of them I comment it out, only one there is no error when I run it, but I confused that when I repeated to run the code, it gave me the different result (should be generate "byte").
There is a question is when I use "method1", it gave me the result (byte), but once I changed to "method2", it will not generate the result, I don't know why. I thought it should generate same result, when I have same string.
public class Convert {
/**
* #param args
* #throws IOException
*/
// String everything;
public static void main(String[] args) throws IOException {
//String everything;
// TODO Auto-generated method stub
BufferedReader br = null;
try {
br = new BufferedReader(new FileReader("C:\\TEMP1\\Doctor.txt"));
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
StringBuilder sb = new StringBuilder();
String line = null;
try {
line = br.readLine();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
while (line != null) {
sb.append(line);
sb.append('\n');
line = br.readLine();
}
//*********Method 1****************
//String r="1ee079746828d7c6f9af46f93c1ef2555ff4b14b2378ad53a258d18dc6a8363fb57f3448783833722bd9ef291ba53153afca31a96de404755e78f68b76fd5a77e4be3b984ea25244842e92a8ed40da1f1a588fb3da26b8bc21d74cd8476534f26ee454df086567c4d7cf3334f794cede41a9b051a5c393a35584afcf";
//byte[] b = new BigInteger(r,16).toByteArray();
//System.out.println("Byte for public key: "+b);
//*********Method 2****************
//String r2 = sb.toString();
//System.out.println("Doctor contect file: "+r2);
//byte[] b = new BigInteger(r2,16).toByteArray();
//System.out.println("Byte for public key: "+b);
//********Method 3*****************
String r="1ee079746828d7c6f9af46f93c1ef2555ff4b14b2378ad53a258d18dc6a8363fb57f3448783833722bd9ef291ba53153afca31a96de404755e78f68b76fd5a77e4be3b984ea25244842e92a8ed40da1f1a588fb3da26b8bc21d74cd8476534f26ee454df086567c4d7cf3334f794cede41a9b051a5c393a35584afcf";
int len = r.length();
byte[] data = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
data[i / 2] = (byte) ((Character.digit(r.charAt(i), 16) << 4)
+ Character.digit(r.charAt(i+1), 16));
System.out.println(data);
}
//********Method4******************
/*
String r2 = sb.toString();
int len = r2.length();
byte[] data = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
data[i / 2] = (byte) ((Character.digit(r2.charAt(i), 16) << 4)
+ Character.digit(r2.charAt(i+1), 16));
System.out.println(data);
}
*/
//String r=everything;
// String r="1ee079746828d7c6f9af46f93c1ef2555ff4b14b2378ad53a258d18dc6a8363fb57f3448783833722bd9ef291ba53153afca31a96de404755e78f68b76fd5a77e4be3b984ea25244842e92a8ed40da1f1a588fb3da26b8bc21d74cd8476534f26ee454df086567c4d7cf3334f794cede41a9b051a5c393a35584afcf";
// double convert=Double.parseDouble(r);
// long convert=(long)(Integer.parseInt(r,32)&0xFF);
// byte convert=Byte.parseByte(r,32);
// byte convert=Integer.parseInt(everything,16);
// System.out.println("Byte for public key: "+convert);
} finally {
br.close();
}
}
}
You're printing the result of calling toString on a byte[]. That's not going to give you what you want.
For diagnostic purposes, use System.out.println(Arrays.toString(data)). And do that at the end of the loop rather than within it:
for (int i = 0; i < len; i += 2) {
...
}
System.out.println(Arrays.toString(data));
There are plenty of alternative approaches to parsing a hex string, mind you. I don't personally like the idea of using an XML-focused API (as recommended in the question comments) when you're not dealing with XML, but it would certainly work - and any number of third party APIs have hex conversion routines.
EDIT: As noted in comments, I believe your hex conversion code is also broken at the moment - but that should probably be fixed by using a prebuilt one from elsewhere. The main purpose of this answer was to explain why you're getting results such as "[B#40a0dcd9". Once you can see the data, you can verify it.
I'm unsure on why you do that, so this answer may not reflect your intend.
I tried to comprehend your stuff and came to the conclusion that you want to split that string into two character blocks, treat them as a hex number and convert them to a byte.
That wont work, as the second block e0 is larger that Byte.MAX_VALUE. So, heres my latest guess on what could be the code that you are looking for (using Integer).
public static void main(String[] args) {
String r = "1ee079746828d7c6f9af46f93c1ef2555ff4b14b2378ad53a258d18dc6a8363fb57f3448783833722bd9ef291ba53153afca31a96de404755e78f68b76fd5a77e4be3b984ea25244842e92a8ed40da1f1a588fb3da26b8bc21d74cd8476534f26ee454df086567c4d7cf3334f794cede41a9b051a5c393a35584afcf";
char[] rA = r.toCharArray();
int len = r.length();
int[] data = new int[len / 2];
for (int i = 0; i < len; i += 2) {
String base = "#" + rA[i] + rA[i+1];
System.out.println("base: " + base);
data[i / 2] = Integer.decode(base);
System.out.println(data[i/2]);
}
}
After reading your question again, it seems that you describe that when you use the String directly (method1) it works, but if you read if from a file (method2) it does not.
The reason is simple: You add a \n at the end of the String you read from file. You do not do so in your method1.
Related
I am a computer science student - second year. I was asked to prepare a project - by Hoffman Code.
During the project I got stuck in the fault, I am in the project phase building the encoder. I get a file - and I have to encode it in bytes - according to the Hoffman code.
My question is how to encode the file in bytes - what I did: for example:
I received the word "abca cadbara" in the file. And into another file I put the encoding but using a string and not in bytes.
the part of the code:
public static void writeOutputFile (String[] input_names, String[] output_names, Map<Character, String> codes)
{
FileInputStream input;
FileOutputStream output;
try
{
input = new FileInputStream(input_names[0]);
output = new FileOutputStream(output_names[0]);
for (int i = 0; i < (int) input.getChannel().size(); i++)
{
int x = input.read();
String codeOutput = codes.get((char) x);
//output.write(Integer.parseInt(codeOutput, 2));
for (int j = 0; j < codeOutput.length(); j++) {
output.write((int) codeOutput.charAt(j));
}
}
input.close();
output.close();
}
catch (Exception e)
{
e.printStackTrace();
}
}
How can I use bytes and not the string?
Thanks for the help.
public static void writeOutputFile (String[] input_names,
String[] output_names,
Map<Character, String> codes) {
try (FileInputStream input = new FileInputStream(input_names[0]);
FileOutputStream output = new FileOutputStream(output_names[0])) {
StringBuilder toWrite = new StringBuilder();
for (int i = 0; i < (int) input.getChannel().size(); i++) {
toWrite.append(codes.get((char) input.read()));
}
output.write(toWrite.toString().getBytes());
} catch (IOException e) {
e.printStackTrace();
}
}
Use String.getBytes() to write bytes to the file.
Use try-with-resources and don't worry about closing the resources. Use ; to separate multiple resources.
Don't write in a loop. Build the string first and then write it once. I/O is slow.
When concatenating in a loop, use StringBuilder avoid creating new Strings.
I made your code a bit more concise, you can rewrite as you like.
i'm creating the md5 hash generator. i first test it with an original file, then i altered the file to see whether the md5 hash codes is changed or not. the hash code did not change even after i altered the same file. what is the problem?
public class MD5CheckSum {
public byte [] createChecksum (String filename) throws Exception {
InputStream fis = new FileInputStream(filename);
byte[] buffer = new byte[1024];
MessageDigest complete = MessageDigest.getInstance("MD5");
int numRead;
do {
numRead = fis.read(buffer);
if (numRead > 0){
complete.update(buffer,0,numRead);
}
}while (numRead !=1);
fis.close();
return complete.digest();
}
public String getMD5Checksum(String filename) throws Exception {
/*byte[] b = createChecksum(filename);
String result = "";
for (int i=0; i < b.length; i++){
result += Integer.toString(( b[i] & 0xff) + 0x100, 16).substring( 1 );
}
return result;*/
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] messageDigest = md.digest(filename.getBytes());
BigInteger number = new BigInteger(1, messageDigest);
String hashtext = number.toString(16);
// Now we need to zero pad it if you actually want the full 32 chars.
while (hashtext.length() < 32) {
hashtext = "0" + hashtext;
}
return hashtext;
}
public MD5CheckSum() throws Exception{
String path = "C:/Users/user/Downloads/Documents/ECOMM SUMMER BLOSSOM.docx";
System.out.println("MD5 Hash Succeed");
System.out.println(getMD5Checksum(path));
}
EDITED: I changed some code
public static String getMD5Checksum(String filename) throws Exception {
byte[] b = createChecksum(filename);
String result = "";
for (int i=0; i < b.length; i++) {
result += Integer.toString( ( b[i] & 0xff ) + 0x100, 16).substring( 1 );
}
return result;
}
public static void main(String args[]) {
try {
System.out.println("Start hashing....");
System.out.println(getMD5Checksum("C:/Users/user/Downloads/Documents/21.pdf"));
System.out.println("Done hashing....");
}
catch (Exception e) {
e.printStackTrace();
}
}
But it takes too long to generate the hash and currently the hash still not generated till now.
filename.getBytes() gets bytes of the filename, not the file contents.
I could tell you how to load the entire file into a byte array, but that would be bad, because it could take up huge amounts of memory when it just isn't necessary to keep the entire file in memory while the hash is calculated.
Instead you should open a stream and get the hash of that. See this answer for that: https://stackoverflow.com/a/304350/360211
You're seem to calculate the MD5-sum of the filename not the content of the file. What you should have done to avoid this is to use a file with a known MD5-sum (by for example run md5sum on it) and check if your code yields the same result.
Also I can't help noting that your createCheckSum seem to be a better candidate to be working as it seem to actually work on the content of the file.
Just verifying that you get different value for different input may show that you've got a candidate for check summing, but it's a poor check that it's actually the correct algorithm used.
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.
Im reading image files off an sdcard of an android device. This results in an out of memory fatal error due to a memory leak. I have narrowed it down to an allocation of 1 byte arrays that are not being removed by the GC. I use FileInputStream to read in the file is there a more efficient way to do this? Can you see the cause of the memory leak? Thanks
private String getHexFileString(File _file)
{
byte[] byteStream = new byte[(int) _file.length()];
String fileHexString = null;
try
{
FileInputStream fis = new FileInputStream(_file);
fis.read(byteStream);
fis.close();
fis = null;
fileHexString = byteArrayToHexString(byteStream);
}
catch (FileNotFoundException e1)
{ actLog.addMessage(new ErrorMessage(e1)); }
catch (IOException e2)
{ actLog.addMessage(new ErrorMessage(e2)); }
catch(OutOfMemoryError e3)
{ actLog.addMessage(new ErrorMessage(e3)); }
return fileHexString;
}
/**
* This method formats a byte-array into a hex string
*
* #param b byte-array
* #return hex string
*/
public String byteArrayToHexString(byte[] b)
{
char[] hexVal = new char[b.length * 2];
int value = 0;
for (int i = 0; i < b.length; i++)
{
value = (b[i] + 256) % 256;
hexVal[i * 2 + 0] = kDigits[value >> 4];
hexVal[i * 2 + 1] = kDigits[value & 0x0f];
}
return new String(hexVal);
}
If some exception occure while you read you will not close the file. It's better to use block finally
You are likely to find that converting to a hex String is far more expensive in time and memory than reading the file. i.e. the String will be 4x bigger.
If you want to improve efficiency and avoid running out of memory you should use a method which returns a byte[] and you operate on this array.
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.