繁体   English   中英

使用Java 8流将十六进制字符串转换为ByteBuffer

[英]Hex string to ByteBuffer conversion with Java 8 streams

我正在寻找一种从文件中逐行读取十六进制字符串并将其作为转换后的字节附加到某个ByteBuffer的方法。

ByteBuffer byteBuffer = ByteBuffer.allocate(1024);

Files.lines(filePath).foreach( l -> 

        byteBuffer.put(
            // first of all strip newlines and normalize string
            l.replaceAll("/\n|\r/g", "").toUpperCase()

            // but what to do here?
            // is there something like
            //   take next 2 characters (-> Consumer)
            //   and replace them with the converted byte?
            //     E.g. "C8" -> 0xC8
            //   until the end of the string is reached
        )

);

这已经回答了一百万次了。 但是我想知道是否有解决方案使用像Files.lines()返回的流。

一般来说,我喜欢这个答案。 有人可以帮助我将其转换为基于Java-8流的解决方案,还是从上面完成我的示例?

谢谢!

您可以使用实用程序方法将行作为十六进制字符串解析为字节数组:

public static byte[] hexStringToByteArray(String str) {
    if(str.startsWith("0x")) { // Get rid of potential prefix
        str = str.substring(2);
    }

    if(str.length() % 2 != 0) { // If string is not of even length
        str = '0' + str; // Assume leading zeroes were left out
    }

    byte[] result = new byte[str.length() / 2];
    for(int i = 0; i < str.length(); i += 2) {
        String nextByte = str.charAt(i) + "" + str.charAt(i + 1);
        // To avoid overflow, parse as int and truncate:
        result[i / 2] = (byte) Integer.parseInt(nextByte, 16);
    }
    return result;
}

ByteBuffer byteBuffer = ByteBuffer.allocate(1024);

Files.lines(filePath).forEach( l -> 
    byteBuffer.put(
        hexStringToByteArray(l.replaceAll("/\n|\r/g", "").toUpperCase())
    )
);

这看起来有点像xy问题 ,因为“ 逐行 ”读取文件已经是您尝试的解决方案的一部分,而您的实际任务不包含任何“逐行”读取文件的要求。

实际上,无论行终止符是什么,您都希望处理源的所有十六进制数,这是java.util.Scanner的工作。 它也允许使用Stream API处理项目,尽管与循环相比,此特定任务并不能从中受益很多:

ByteBuffer bb = ByteBuffer.allocate(1024);
try(Scanner s = new Scanner(yourFile)) {
    s.findAll("[0-9A-Fa-f]{2}")
     .mapToInt(m -> Integer.parseInt(m.group(), 16))
     .forEachOrdered(i -> { if(bb.hasRemaining()) bb.put((byte)i); });
}
try(Scanner s = new Scanner(yourFile)) {
    Pattern p = Pattern.compile("[0-9A-Fa-f]{2}");
    for(;;) {
        String next = s.findWithinHorizon(p, 0);
        if(next == null) break;
        if(!bb.hasRemaining()) // the thing hard to do with Stream API
            bb = ByteBuffer.allocate(bb.capacity()*2).put(bb.flip());
        bb.put((byte)Integer.parseInt(next, 16));
    }
}

请注意,这些例子中使用Java 9.在Java 8中, Buffer返回由Buffer.flip()需要转换回一个类型ByteBufferScanner.findAll不可用,但必须由像在背端口替换此回答

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM