I have a requirement to convert a pdf file to hexadecimal using java.
Any quick help will be highly appreciated.
Regards.
Quick help would look like this
static String toHex(File file) throws IOException {
InputStream is = new BufferedInputStream(new FileInputStream(file));
int value = 0;
StringBuilder hex = new StringBuilder();
while ((value = inputStream.read()) != -1) {
hex.append(String.format("%02X ", value));
}
return hex.toString();
}
for a sake of simplicity i have skipped few edge cases. but i think this is good start. in reality you have to check whether a character is convertible to hex and handle all possible exceptions that can be thrown.
main method would look like this.
public static void main(String[] args) throws IOException {
File file = new File("sample.pdf");
String hex = toHex(file);
System.out.println(hex);
}
A nice use-case for ByteBuffer (though byte[] would suffice here):
byte[] toHex(Path path) {
byte[] content = Files.readAllBytes(path);
ByteBuffer buf = ByteBuffer.allocate(content.length * 2);
for (byte b : content) {
byte[] cc = String.format("%02x", 0xFF & b).getBytes(StandardCharsets.US_ASCII);
buf.put(cc);
}
return buf.array();
}
Speed improvement:
for (byte b : content) {
int c = (b >> 4) & 0xF;
int d = b & 0xF;
buf.put((byte) (c < 10 ? '0' + c : 'a' + c - 10));
buf.put((byte) (d < 10 ? '0' + d : 'a' + d - 10));
}
This assumes that the files are not huge. (But in that case hexadecimal would make no sense.)
Related
I'm trying to convert a hex representation of a .jpg stored in database as BLOB back to an image. In the following snippet I'm reading in the hex from the image.txt file which contains the hex string: 0xFFD8FFE000104A4649460001010100C800C80000FF...
public static void main(String[] args) throws IOException {
byte[] encoded = Files.readAllBytes(Paths.get("image.txt"));
String imageString = new String(encoded).trim();
ByteArrayInputStream bis = new ByteArrayInputStream(hexStringToByteArray(imageString));
BufferedImage image = ImageIO.read(bis);
File outputFile = new File("output.jpg");
ImageIO.write(image, "jpg", outputFile);
}
public static byte[] hexStringToByteArray(String str) {
String hexStr = str.substring(2);
byte[] buf = new byte[hexStr.length() / 2];
for (int i = 0; i < hexStr.length(); i += 2) {
if (i != hexStr.length() - 1) {
buf[i / 2] = (byte) ((Character.digit(str.charAt(i), 16) << 4)
+ Character.digit(str.charAt(i + 1), 16));
}
}
return buf;
}
For me the ImageIO.read is not working. It always returns null and therefore an IllegalArgumentException is thrown by ImageIO.write, because image must not be null.
Can anyone help or is there a better way to achieve this?
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"));
I've been doing research on a java problem I have with no success. I've read a whole bunch of similar questions here on StackOverflow but the solutions just doesn't seem to work as expected.
I'm trying to read a binary file byte by byte.
I've used:
while ((data = inputStream.read()) != -1)
loops...
for (int i = 0; i < bFile.length; i++) {
loops...
But I only get empty or blank output. The actual content of the file I'm trying to read is as follows:
¬í sr assignment6.PetI¿Z8kyQŸ I ageD weightL namet Ljava/lang/String;xp > #4 t andysq ~ #bÀ t simbasq ~ #I t wolletjiesq ~
#$ t rakker
I'm merely trying to read it byte for byte and feed it to a character array with the following line:
char[] charArray = Character.toChars(byteValue);
Bytevalue here represents an int of the byte it's reading.
What is going wrong where?
Since java 7 it is not needed to read byte by byte, there are two utility function in Files:
Path path = Paths.get("C:/temp/test.txt");
// Load as binary:
byte[] bytes = Files.readAllBytes(path);
String asText = new String(bytes, StandardCharset.ISO_8859_1);
// Load as text, with some Charset:
List<String> lines = Files.readAllLines(path, StandardCharsets.ISO_8859_1);
As you want to read binary data, one would use readAllBytes.
String and char is for text. As opposed to many other programming languages, this means Unicode, so all scripts of the world may be combined. char is 16 bit as opposed to the 8 bit byte.
For pure ASCII, the 7 bit subset of Unicode / UTF-8, byte and char values are identical.
Then you might have done the following (low-quality code):
int fileLength = (int) path.size();
char[] chars = new char[fileLength];
int i = 0;
int data;
while ((data = inputStream.read()) != -1) {
chars[i] = (char) data; // data actually being a byte
++i;
}
inputStream.close();
String text = new String(chars);
System.out.println(Arrays.toString(chars));
The problem you had, probably concerned the unwieldy fixed size array in java, and that a char[] still is not a String.
For binary usage, as you seem to be reading serialized data, you might like to dump the file:
int i = 0;
int data;
while ((data = inputStream.read()) != -1) {
char ch = 32 <= data && data < 127 ? (char) data : ' ';
System.out.println("[%06d] %02x %c%n", i, data, ch);
++i;
}
Dumping file position, hex value and char value.
it is simple example:
public class CopyBytes {
public static void main(String[] args) throws IOException {
FileInputStream in = null;
FileOutputStream out = null;
try {
in = new FileInputStream("xanadu.txt");
out = new FileOutputStream("outagain.txt");
int c;
while ((c = in.read()) != -1) {
out.write(c);
}
} finally {
if (in != null) {
in.close();
}
if (out != null) {
out.close();
}
}
}
}
If you want to read text(characters) - use Readers, if you want to read bytes - use Streams
Why not using Apache Commons:
byte[] bytes = IOUtils.toByteArray(inputStream);
Then you can convert it to char:
String str = new String(bytes);
Char[] chars = str.toCharArray();
Or like you did:
char[] charArray = Character.toChars(bytes);
To deserialize objects:
List<Object> results = new ArrayList<Object>();
FileInputStream fis = new FileInputStream("your_file.dat");
ObjectInputStream ois = new ObjectInputStream(fis);
try {
while (true) {
results.add(ois.readObject());
}
} catch (OptionalDataException e) {
if (!e.eof) throw e;
} finally {
ois.close();
}
Edit:
Use file.length() for they array size, and make a byte array. Then inputstream.read(b).
Edit again: if you want characters, use inputstreamreader(fileinputstream(file),charset), it even comes with charset.
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.
I want to use percent value encoding/decoding for some string operations in my Android application. I don't want to use a URI encode/decode function pair because I want to encode every character, not just the ones that are encoded when encoding URI's for making web requests. Are there any built-in functions in the Android libraries or Java libraries that can do this?
-- roschler
There's nothing built in to the API to do this directly, but it's pretty simple. It's better to use a specific character encoding (like UTF-8) to convert characters to bytes. This should do the trick for encoding:
static final String digits = "0123456789ABCDEF";
static void convert(String s, StringBuffer buf, String enc)
throws UnsupportedEncodingException {
byte[] bytes = s.getBytes(enc);
for (int j = 0; j < bytes.length; j++) {
buf.append('%');
buf.append(digits.charAt((bytes[j] & 0xf0) >> 4));
buf.append(digits.charAt(bytes[j] & 0xf));
}
}
Oh yes, you asked for decoding as well:
static String decode(String s, String enc)
throws UnsupportedEncodingException {
StringBuffer result = new StringBuffer(s.length());
ByteArrayOutputStream out = new ByteArrayOutputStream();
for (int i = 0; i < s.length();) {
char c = s.charAt(i);
if (c == '%') {
out.reset();
do {
if (i + 2 >= s.length()) {
throw new IllegalArgumentException(
"Incomplete trailing escape (%) pattern at " + i);
}
int d1 = Character.digit(s.charAt(i + 1), 16);
int d2 = Character.digit(s.charAt(i + 2), 16);
if (d1 == -1 || d2 == -1) {
throw new IllegalArgumentException(
"Illegal characters in escape (%) pattern at " + i
+ ": " + s.substring(i, i+3));
}
out.write((byte) ((d1 << 4) + d2));
i += 3;
} while (i < s.length() && s.charAt(i) == '%');
result.append(out.toString(enc));
continue;
} else {
result.append(c);
}
i++;
}
}
This is pretty trivial, and doesn't need library functions:
public static String escapeString(String input) {
String output = "";
for (byte b : input.getBytes()) output += String.format("%%%02x", b);
return output;
}
public static String unescapeString(String input) {
String output = "";
for (String hex: input.split("%")) if (!"".equals(hex)) output += (char)Integer.parseInt(hex, 16);
return output;
}
public static String unescapeMultiByteString(String input, String charset) {
ByteArrayOutputStream output = new ByteArrayOutputStream();
String result = null;
for (String hex: input.split("%")) if (!"".equals(hex)) output.write(Integer.parseInt(hex, 16));
try { result = new String(output.toByteArray(), charset); }
catch (Exception e) {}
return result;
}