【问题标题】:How to convert Strings to and from UTF8 byte arrays in Java如何在 Java 中将字符串与 UTF8 字节数组相互转换
【发布时间】:2008-09-18 00:11:21
【问题描述】:

在 Java 中,我有一个字符串,我想将它编码为一个字节数组(在 UTF8 或其他编码中)。或者,我有一个字节数组(在一些已知的编码中),我想将它转换为 Java 字符串。如何进行这些转换?

【问题讨论】:

    标签: java string encoding character-encoding


    【解决方案1】:

    String 转换为byte[]

    String s = "some text here";
    byte[] b = s.getBytes(StandardCharsets.UTF_8);
    

    byte[] 转换为String

    byte[] b = {(byte) 99, (byte)97, (byte)116};
    String s = new String(b, StandardCharsets.US_ASCII);
    

    当然,您应该使用正确的编码名称。我的示例使用了 US-ASCII 和 UTF-8,这两种常用的编码。

    【讨论】:

    • 这种方法,但是,不会报告转换中的任何问题。这可能是你想要的。如果没有,建议改用 CharsetEncoder。
    • 你为什么用UTF-8而不是utf8(我一直用)?
    • @Pacerier 因为the docs for Charset 将“UTF-8”列为标准字符集之一。我相信您的拼写也被接受,但我按照文档所说的进行。
    • 使用两个这样的 Strngs 存在问题:比较时它不起作用
    • 从JDK7开始可以使用StandardCharsets.UTF_8 docs.oracle.com/javase/7/docs/api/java/nio/charset/…
    【解决方案2】:

    这是一个避免每次转换都执行字符集查找的解决方案:

    import java.nio.charset.Charset;
    
    private final Charset UTF8_CHARSET = Charset.forName("UTF-8");
    
    String decodeUTF8(byte[] bytes) {
        return new String(bytes, UTF8_CHARSET);
    }
    
    byte[] encodeUTF8(String string) {
        return string.getBytes(UTF8_CHARSET);
    }
    

    【讨论】:

    • @mcherm:即使性能差异很小,我更喜欢尽可能使用对象(字符集、URL 等)而不是字符串形式。
    • 注意:“自 1.6” public String(byte[] bytes, Charset charset)
    • 关于“避免为每次转换执行字符集查找”...请引用一些来源。 java.nio.charset.Charset 不是 在 String.getBytes 之上 构建的,因此开销比 String.getBytes 多吗?
    • 文档确实声明:“当此字符串无法在给定字符集中编码时,此方法的行为未指定。当需要对编码过程进行更多控制时,应使用 CharsetEncoder 类。”
    • 注意:从 Java 1.7 开始,您可以使用 StandardCharsets.UTF_8 以恒定方式访问 UTF-8 字符集。
    【解决方案3】:
    String original = "hello world";
    byte[] utf8Bytes = original.getBytes("UTF-8");
    

    【讨论】:

    • 谢谢!我自己又写了一遍,添加了另一个转换方向。
    • @smink 中的破折号不是可选的。这应该使用“UTF-8”
    【解决方案4】:

    您可以直接通过String(byte[], String) 构造函数和getBytes(String) 方法进行转换。 Java 通过Charset 类公开可用的字符集。 JDK 文档lists supported encodings

    90% 的情况下,此类转换是在流上执行的,因此您将使用 Reader/Writer 类。您不会在任意字节流上使用 String 方法进行增量解码 - 您可能会遇到涉及多字节字符的错误。

    【讨论】:

    • 您能详细说明一下吗?如果我的应用程序对UTF-8 中的字符串进行编码和解码,那么多字节字符有什么问题?
    • @raffian 如果您不一次性转换所有字符数据,则可能会出现问题。有关示例,请参阅 here
    【解决方案5】:

    我的 tomcat7 实现接受字符串为 ISO-8859-1;尽管 HTTP 请求的内容类型。在尝试正确解释像 'é' 这样的字符时,以下解决方案对我有用。

    byte[] b1 = szP1.getBytes("ISO-8859-1");
    System.out.println(b1.toString());
    
    String szUT8 = new String(b1, "UTF-8");
    System.out.println(szUT8);
    

    尝试将字符串解释为 US-ASCII 时,字节信息未正确解释。

    b1 = szP1.getBytes("US-ASCII");
    System.out.println(b1.toString());
    

    【讨论】:

    【解决方案6】:

    作为替代方案,可以使用来自 Apache Commons 的 StringUtils

     byte[] bytes = {(byte) 1};
     String convertedString = StringUtils.newStringUtf8(bytes);
    

     String myString = "example";
     byte[] convertedBytes = StringUtils.getBytesUtf8(myString);
    

    如果您有非标准字符集,您可以相应地使用getBytesUnchecked()newString()

    【讨论】:

    • 请注意,这个 StringUtils 来自 Commons Codec,而不是 Commons Lang。
    • 是的,有点问题!对于 Gradle、Maven 用户:"commons-codec:commons-codec:1.10"(在撰写本文时)。例如,这也作为与 Apache POI 的依赖项捆绑在一起。除了那个 Apache Commons 来救援,一如既往!
    【解决方案7】:

    我无法发表评论,但不想开始新的话题。但这行不通。一次简单的往返:

    byte[] b = new byte[]{ 0, 0, 0, -127 };  // 0x00000081
    String s = new String(b,StandardCharsets.UTF_8); // UTF8 = 0x0000, 0x0000,  0x0000, 0xfffd
    b = s.getBytes(StandardCharsets.UTF_8); // [0, 0, 0, -17, -65, -67] 0x000000efbfbd != 0x00000081
    

    在编码前后我需要 b[] 相同的数组,但它不是(这个指向第一个答案)。

    【讨论】:

      【解决方案8】:

      为了将一系列字节解码为普通的字符串消息,我终于用 UTF-8 编码使用了这个代码:

      /* Convert a list of UTF-8 numbers to a normal String
       * Usefull for decoding a jms message that is delivered as a sequence of bytes instead of plain text
       */
      public String convertUtf8NumbersToString(String[] numbers){
          int length = numbers.length;
          byte[] data = new byte[length];
      
          for(int i = 0; i< length; i++){
              data[i] = Byte.parseByte(numbers[i]);
          }
          return new String(data, Charset.forName("UTF-8"));
      }
      

      【讨论】:

        【解决方案9】:

        如果您使用 7 位 ASCII 或 ISO-8859-1(一种非常常见的格式),那么您根本不必创建新的 java.lang.String。简单地将字节转换为 char 的性能要高得多:

        完整的工作示例:

        for (byte b : new byte[] { 43, 45, (byte) 215, (byte) 247 }) {
            char c = (char) b;
            System.out.print(c);
        }
        

        如果您使用 扩展字符,如 Ä、Æ、Å、Ç、Ï、Ê ,则可以确定只有传输的值是前 128 个 Unicode 字符,那么此代码也适用于 UTF-8 和扩展 ASCII(如 cp-1252)。

        【讨论】:

          【解决方案10】:
          Charset UTF8_CHARSET = Charset.forName("UTF-8");
          String strISO = "{\"name\":\"א\"}";
          System.out.println(strISO);
          byte[] b = strISO.getBytes();
          for (byte c: b) {
              System.out.print("[" + c + "]");
          }
          String str = new String(b, UTF8_CHARSET);
          System.out.println(str);
          

          【讨论】:

            【解决方案11】:
            //query is your json   
            
             DefaultHttpClient httpClient = new DefaultHttpClient();
             HttpPost postRequest = new HttpPost("http://my.site/test/v1/product/search?qy=");
            
             StringEntity input = new StringEntity(query, "UTF-8");
             input.setContentType("application/json");
             postRequest.setEntity(input);   
             HttpResponse response=response = httpClient.execute(postRequest);
            

            【讨论】:

            • 字符串实体是否将“查询”转换为 utf-8 或仅在附加实体时记住?
            【解决方案12】:
            Reader reader = new BufferedReader(
                new InputStreamReader(
                    new ByteArrayInputStream(
                        string.getBytes(StandardCharsets.UTF_8)), StandardCharsets.UTF_8));
            

            【讨论】:

              【解决方案13】:

              太晚了,但我刚刚遇到了这个问题,这是我的解决方法:

              private static String removeNonUtf8CompliantCharacters( final String inString ) {
                  if (null == inString ) return null;
                  byte[] byteArr = inString.getBytes();
                  for ( int i=0; i < byteArr.length; i++ ) {
                      byte ch= byteArr[i]; 
                      // remove any characters outside the valid UTF-8 range as well as all control characters
                      // except tabs and new lines
                      if ( !( (ch > 31 && ch < 253 ) || ch == '\t' || ch == '\n' || ch == '\r') ) {
                          byteArr[i]=' ';
                      }
                  }
                  return new String( byteArr );
              }
              

              【讨论】:

              • 首先,这不是转换:它是删除不可打印的字节。其次,它假定底层操作系统的默认编码实际上是基于 ASCII 的可打印字符(例如,不适用于使用 EBCDIC 的 IBM 大型机)。
              猜你喜欢
              • 2012-07-17
              • 2013-09-14
              • 2013-09-12
              • 2011-01-18
              • 2017-05-18
              • 2012-09-02
              • 1970-01-01
              • 2012-07-18
              • 1970-01-01
              相关资源
              最近更新 更多