如何将二进制数据转换为字符串并返回Java?

时间:2008-08-21 18:51:53

标签: java serialization

我在文件中有二进制数据,我可以将其读入字节数组并且处理没有问题。现在,我需要通过网络连接将部分数据作为XML文档中的元素发送。我的问题是,当我将数据从一个字节数组转换为一个字符串并返回一个字节数组时,数据就会被破坏。我已经在一台机器上对此进行了测试,以将问题与String转换隔离开来,所以我现在知道它不会被XML解析器或网络传输损坏。

我现在所拥有的是

byte[] buffer = ...; // read from file
// a few lines that prove I can process the data successfully
String element = new String(buffer);
byte[] newBuffer = element.getBytes();
// a few lines that try to process newBuffer and fail because it is not the same data anymore

有没有人知道如何将二进制转换为String并返回而不会丢失数据?

回答:谢谢Sam。我觉得自己像个白痴。我昨天得到了回答,因为我的SAX解析器在抱怨。出于某些原因,当我遇到这个看似独立的问题时,我并没有想到它是同一问题的新症状。

编辑:为了完整起见,我使用Base64 Apache Commons包中的Codec类来解决此问题。

4 个答案:

答案 0 :(得分:35)

String(byte[])将数据视为默认字符编码。因此,字节从8位值转换为16位Java Unicode字符的方式不仅会因操作系统而异,甚至可能因同一台计算机上使用不同代码页的不同用户而异。此构造函数仅适用于解码您自己的一个文本文件。不要尝试将任意字节转换为Java中的字符!

编码为base64是一个很好的解决方案。这是通过SMTP(电子邮件)发送文件的方式。 (免费)Apache Commons Codec项目将完成这项工作。

byte[] bytes = loadFile(file);          
//all chars in encoded are guaranteed to be 7-bit ASCII
byte[] encoded = Base64.encodeBase64(bytes);
String printMe = new String(encoded, "US-ASCII");
System.out.println(printMe);
byte[] decoded = Base64.decodeBase64(encoded);

或者,您可以使用Java 6 DatatypeConverter

import java.io.*;
import java.nio.channels.*;
import javax.xml.bind.DatatypeConverter;

public class EncodeDecode {    
  public static void main(String[] args) throws Exception {
    File file = new File("/bin/ls");
    byte[] bytes = loadFile(file, new ByteArrayOutputStream()).toByteArray();
    String encoded = DatatypeConverter.printBase64Binary(bytes);
    System.out.println(encoded);
    byte[] decoded = DatatypeConverter.parseBase64Binary(encoded);
    // check
    for (int i = 0; i < bytes.length; i++) {
      assert bytes[i] == decoded[i];
    }
  }

  private static <T extends OutputStream> T loadFile(File file, T out)
                                                       throws IOException {
    FileChannel in = new FileInputStream(file).getChannel();
    try {
      assert in.size() == in.transferTo(0, in.size(), Channels.newChannel(out));
      return out;
    } finally {
      in.close();
    }
  }
}

答案 1 :(得分:19)

如果您在base64中对其进行编码,则会将任何数据转换为ascii安全文本,但base64编码数据大于原始数据

答案 2 :(得分:2)

查看此问题,How do you embed binary data in XML? 而不是将byte []转换为String然后在某处推送到XML,通过BASE64编码将byte []转换为String(某些XML库有一个类型可以为您执行此操作)。一旦从XML获得String,BASE64就会解码。

使用http://commons.apache.org/codec/

由于各种奇怪的字符集限制和非引用字符的存在,您的数据可能会变得混乱。坚持使用BASE64。

答案 3 :(得分:0)

您是如何构建XML文档的?如果你使用java的内置XML类,那么应该为你处理字符串编码。

查看javax.xml和org.xml包。这就是我们用于生成XML文档的内容,它可以很好地处理所有字符串编码和解码。

---编辑:

嗯,我想我误解了这个问题。您不是要编写常规字符串,而是编写一些任意二进制数据?在这种情况下,早期评论中建议的Base64编码可能就是这样。我相信这是用XML编码二进制数据的一种相当标准的方法。