开发者

Translate a byte sequence given an InputStream

In Java, is there a library anywhere that will, given a开发者_Go百科 byte sequence (preferable expressed as hex), translate to another byte sequence given an InputStream? For example:

InputStream input = new FileInputStream(new File(...));
OutputStream output = new FileOutputStream(new File(...));
String fromHex = "C3BEAB";
String toHex = "EAF6"
MyMagicLibrary.translate(fromHex, toHex, input, output)

So if the input file (in hex looked like)

00 00 12 18 33 C3 BE AB 00 23 C3 BE AB 00

after translation, the result would be

00 00 12 18 33 EA F6 00 23 EA F6 00


Once I did something like this (for trivially patching exe-files) using regexes. I read the whole input into a byte[] and converted into String using latin1, then did the substitution and converted back. It wasn't efficient but it didn't matter at all. You don't need regexes, simple String.replace would do.

But in your case it can be done quite simply and very efficiently:

int count = 0;
while (true) {
    int n = input.read();
    if (n == (fromAsByteArray[count] & 255)) {
        ++count;
        if (count==fromAsByteArray.length) { // match found
            output.write(toAsByteArray);
            count = 0;
        }
    } else { // mismatch
        output.write(fromAsByteArray, 0, count); // flush matching chars so far
        count = 0;
        if (n == -1) break;
        output.write(n);
        }
    }
}


If u mean that u want to use a class whch translate from hex and to hex here's two methods I usualluy use, u can put them inside a class and reuse it any where u want

public static String toHex(byte buf[]) {
    StringBuffer strbuf = new StringBuffer(buf.length * 2);
    int i;

    for (i = 0; i < buf.length; i++) {
        if (((int) buf[i] & 0xff) < 0x10) {
            strbuf.append("0");
        }

        strbuf.append(Long.toString((int) buf[i] & 0xff, 16));
    }

    return strbuf.toString();
}

public static byte[] fromHexString(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;
}

Actually I don't understand each line in the code, but I usually reuse them.


Since your input can have spaces then you first need to scrub your input to remove the spaces. After reading a pair of characters just use Byte.parseByte(twoCharString, 16) then use String.format to convert back to a String.

Doing it byte by byte would most likely be VERY inefficient, though easy to test. Once you get the result you want, you can tweak it by reading and parsing a whole buffer and spitting out more than one resulting byte a time, maybe 16 "byte" characters per line for formatting. It is all up to you at that point.


One way to implement this is to use IOUtils and String replace method.

public static void translate(byte[] fromHex, byte[] toHex, InputStream input, OutputStream output) throws IOException {
    IOUtils.write(translate(fromHex, toHex, IOUtils.toByteArray(input)), output);
}

public static byte[] translate(byte[] fromHex, byte[] toHex, byte[] inBytes) throws UnsupportedEncodingException {
    String inputText = new String(inBytes, "ISO-8859-1");
    String outputText = inputText.replace(new String(fromHex, "ISO-8859-1"), new String(toHex, "ISO-8859-1"));
    return outputText.getBytes("ISO-8859-1");
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜