How to convert byte array to string and vice versa?
我必须在Android中将字节数组转换为字符串,但我的字节数组包含负值。
如果我再次将该字符串转换为字节数组,我得到的值与原始字节数组值不同。
我该怎么做才能得到正确的转换呢?我用来进行转换的代码如下:
1 2 3 4 5 6 7 8 9 |
我陷入了这个问题。
字节数组必须有一些编码。如果有负值,则编码不能是ASCII。一旦您了解了这一点,就可以使用以下方法将一组字节转换为字符串:
您可以使用许多编码,看看Sun JavaDocs中的charset类。
如果您真的必须使用
根本问题是(我认为)您无意中使用的字符集:
1 | bytes != encode(decode(bytes)) |
在某些情况下。UTF-8就是这样一个字符集的例子。具体来说,某些字节序列不是有效的UTF-8编码。如果UTF-8解码器遇到这些序列中的一个,它可能会丢弃有问题的字节,或者将它们作为"无此类字符"的Unicode码位进行解码。当然,当您尝试将字符编码为字节时,结果会有所不同。
解决方案是:
我们只需要用数组构造一个新的
结果字符串的字节因使用的字符集而异。调用string getbytes()时,new string(bytes)、new string(bytes、charset.forname("utf-8")和new string(bytes、charset.forname("utf-16")都将具有不同的字节数组(取决于默认字符集)
使用
问题的原因:正如某人已经指定的那样:如果以字节[]开头,但它实际上不包含文本数据,则不存在"正确的转换"。字符串用于文本,字节[]用于二进制数据,唯一真正明智的做法是避免它们之间的转换,除非必须这样做。
当我试图从PDF文件创建byte[]并将其转换为字符串,然后将字符串作为输入并转换回文件时,我观察到了这个问题。
所以确保你的编码和解码逻辑和我一样。我将字节[]显式编码为base64,然后对其进行解码以再次创建文件。
用例:由于某些限制,我试图发送
PDF文件>>base64.encodebase64(byte[])>>string>>发送请求(post)>>接收字符串>>base64.decodebase64(byte[])>>创建二进制文件
试试这个,这个对我有用……
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | File file = new File("filePath"); byte[] byteArray = new byte[(int) file.length()]; try { FileInputStream fileInputStream = new FileInputStream(file); fileInputStream.read(byteArray); String byteArrayStr= new String(Base64.encodeBase64(byteArray)); FileOutputStream fos = new FileOutputStream("newFilePath"); fos.write(Base64.decodeBase64(byteArrayStr.getBytes())); fos.close(); } catch (FileNotFoundException e) { System.out.println("File Not Found."); e.printStackTrace(); } catch (IOException e1) { System.out.println("Error Reading The File."); e1.printStackTrace(); } |
这对我来说很好:
1 |
从字符串转换为字节[]:
1 | byte[] cookie = new sun.misc.BASE64Decoder().decodeBuffer(cd); |
从字节[]转换为字符串:
1 | cd = new sun.misc.BASE64Encoder().encode(cookie); |
1 2 3 4 5 6 7 8 9 |
我确实注意到了一些答案中没有的东西。您可以将字节数组中的每个字节强制转换为字符,并将它们放入char数组中。然后字符串是
1 |
,其中cbuf是char数组。要进行转换,请通过字符串进行循环,将每个字符转换为要放入字节数组的字节,该字节数组将与第一个相同。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | public class StringByteArrTest { public static void main(String[] args) { // put whatever byte array here byte[] arr = new byte[] {-12, -100, -49, 100, -63, 0, -90}; for (byte b: arr) System.out.println(b); // put data into this char array char[] cbuf = new char[arr.length]; for (int i = 0; i < arr.length; i++) { cbuf[i] = (char) arr[i]; } // this is the string String s = new String(cbuf); System.out.println(s); // converting back byte[] out = new byte[s.length()]; for (int i = 0; i < s.length(); i++) { out[i] = (byte) s.charAt(i); } for (byte b: out) System.out.println(b); } } |
下面是一些将字节数组转换为字符串的方法。我已经测试过了,它们工作得很好。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | public String getStringFromByteArray(byte[] settingsData) { ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(settingsData); Reader reader = new BufferedReader(new InputStreamReader(byteArrayInputStream)); StringBuilder sb = new StringBuilder(); int byteChar; try { while((byteChar = reader.read()) != -1) { sb.append((char) byteChar); } } catch(IOException e) { e.printStackTrace(); } return sb.toString(); } public String getStringFromByteArray(byte[] settingsData) { StringBuilder sb = new StringBuilder(); for(byte willBeChar: settingsData) { sb.append((char) willBeChar); } return sb.toString(); } |
1 2 | byte [] b = javax.xml.bind.DatatypeConverter.parseHexBinary("E62DB"); String s = javax.xml.bind.DatatypeConverter.printHexBinary(b); |
虽然Base64编码是安全的,可以说"正确答案",但我来到这里寻找一种将Java字节数组转换成Java字符串的方法。也就是说,字节数组的每个成员在对应的字符串中保持完整,不需要额外的空间来进行编码/传输。
这个描述8位透明编码的答案对我很有帮助。我在数兆字节的二进制数据上使用
这也有助于解释何时/是否应该进行实验。
我使用以下方法成功地将字节数组转换为字符串:
1 2 3 4 5 6 7 8 9 10 11 12 13 | public static String byteArrayToString(byte[] data){ String response = Arrays.toString(data); String[] byteValues = response.substring(1, response.length() - 1).split(","); byte[] bytes = new byte[byteValues.length]; for (int i=0, len=bytes.length; i<len; i++) { bytes[i] = Byte.parseByte(byteValues[i].trim()); } String str = new String(bytes); return str.toLowerCase(); } |
尽管
1 |
是正确的,它抛出一个
1 |
这个不会引发任何异常。
还应使用
1 | "test".getBytes(StandardCharsets.UTF_8) |
同样,您可以避免处理选中的异常。
1 2 3 4 5 6 7 8 9 10 11 12 | import sun.misc.BASE64Decoder; import sun.misc.BASE64Encoder; private static String base64Encode(byte[] bytes) { return new BASE64Encoder().encode(bytes); } private static byte[] base64Decode(String s) throws IOException { return new BASE64Decoder().decodeBuffer(s); } |
使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | package com.cs.sajal; import java.io.BufferedReader; import java.io.ByteArrayInputStream; import java.io.InputStreamReader; import java.io.UnsupportedEncodingException; public class TestCls { public static void main(String[] args) { String s=new String("Sajal is a good boy"); try { ByteArrayInputStream bis; bis=new ByteArrayInputStream(s.getBytes("UTF-8")); BufferedReader br=new BufferedReader(new InputStreamReader(bis)); System.out.println(br.readLine()); } catch(Exception e) { e.printStackTrace(); } } } |
输出为:
Sajal is a good boy
这里是工作代码。
1 2 3 4 5 6 7 8 | // Encode byte array into string . TemplateBuffer1 is my bytearry variable. String finger_buffer = Base64.encodeToString(templateBuffer1, Base64.DEFAULT); Log.d(TAG,"Captured biometric device->" + finger_buffer); // Decode String into Byte Array. decodedString is my bytearray[] decodedString = Base64.decode(finger_buffer, Base64.DEFAULT); |
您可以使用简单的for循环进行转换:
1 2 3 4 5 6 7 8 9 |
尝试在两个转换中指定一个8位字符集。例如,ISO-8859-1。
1 2 | InputStream is = new FileInputStream("/home/kalt/Desktop/SUDIS/READY/ds.bin"); byte[] bytes = IOUtils.toByteArray(is); |
字符串是字符(16位无符号)的集合。所以如果你要把负数转换成一个字符串,它们会在翻译中丢失。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | public class byteString { /** * @param args */ public static void main(String[] args) throws Exception { // TODO Auto-generated method stub String msg ="Hello"; byte[] buff = new byte[1024]; buff = msg.getBytes("UTF-8"); System.out.println(buff); String m = new String(buff); System.out.println(m); } } |
使用base64来解决你的问题。它太容易使用了。http://iharder.sourceforge.net/current/java/base64/