【问题标题】:List<Byte> to String, can you help refactor this ( small ) method?List<Byte> 到 String,你能帮忙重构这个(小)方法吗?
【发布时间】:2009-07-08 08:42:26
【问题描述】:

我们使用这种小型实用方法。但我们不喜欢它。由于它不是很重要(无论如何它都有效......),我们已经忘记了它。
但这很难看,因为我们必须遍历整个数组,才能转换 从Byte[]byte[]
我在看:

  • 寻找一种无需经过即可将Byte[] 转换为byte[] 的方法
  • 或用于将列表转换为字符串的实用方法

public static String byteListToString(List<Byte> l, Charset charset) {
    if (l == null) {
        return "";
    }
    byte[] array = new byte[l.size()];
    int i = 0;
    for (Byte current : l) {
        array[i] = current;
        i++;
    }
    return new String(array, charset);
}

【问题讨论】:

  • 第一个想法……你是在把方法称为“她”吗?
  • 为什么不是她?女士们是合乎逻辑的
  • 提问者是法国人; method 的法语是“la methode”(法语是一种有性别的语言);自然翻译成英语会产生“她”。我认为这很有趣 :) 如果汽车和轮船传统上可以是女性,那为什么不可以呢?
  • Java 中没有优雅的方法可以将数组作为一个整体拆箱
  • 尚未对此进行测试,但是否可行:new String(l.toArray(new byte[0])); ?

标签: java arrays bytearray


【解决方案1】:

您的方法几乎是唯一的方法。您可能会发现一个外部库可以完成全部或部分功能,但它本质上会做同样的事情。

但是,您的代码中有一个潜在问题:调用new String(array) 时,您使用的是平台默认编码将字节转换为字符。操作系统和区域设置之间的平台编码不同 - 使用它几乎总是一个等待发生的错误。这取决于您从哪里获取这些字节,但它们的编码应该在某处指定,作为参数传递给方法并用于转换(通过使用带有第二个参数的 String 构造函数)。

【讨论】:

    【解决方案2】:
    import org.apache.commons.lang.ArrayUtils;
    
    ...
    
    Byte[] bytes = new Byte[l.size()];
    l.toArray(bytes);
    
    byte[] b =  ArrayUtils.toPrimitive(bytes);
    

    【讨论】:

    • 我不认为这是一个很大的改进 - 您正在向 3rd 方库添加一个依赖项,它在内部可能会执行与上述代码类似的操作。
    • @Jon:我部分同意——我不喜欢仅仅为奇怪的实用程序添加第三方依赖项。方法,但如果这种依赖已经存在,那么我认为它会使代码更加简洁和可读。
    • @Jon 我也部分同意,但 commons-lang 可能是最安全的第三方库之一,asd 正如 Adamski 所说,您最终可能会多次使用它。跨度>
    【解决方案3】:

    没有任何额外的库(例如 apache commons)你的方法很好

    【讨论】:

      【解决方案4】:

      次要:

      if (l == null || l.isEmpty() ) {
          return "" ;
      }
      

      避免为空列表创建空字符串。

      【讨论】:

        【解决方案5】:

        Guava 提供了许多有用的primitive utilities,包括一个Bytes 类,它使Bytes 集合上的这个和其他操作变得微不足道。

        private static String toString(List<Byte> bytes) {
          return new String(Bytes.toArray(bytes), StandardCharsets.UTF_8);
        }
        

        【讨论】:

          【解决方案6】:

          你可以使用 java.nio 并想出类似的东西

          public static String byteListToString(List<Byte> l, Charset cs)
          throws IOException
          {
              final int CBUF_SIZE = 8;
              final int BBUF_SIZE = 8;
          
              CharBuffer cbuf = CharBuffer.allocate(CBUF_SIZE);
              char[] chArr = cbuf.array();
              ByteBuffer bbuf = ByteBuffer.allocate(BBUF_SIZE);
              CharsetDecoder dec = cs.newDecoder();
              StringWriter sw = new StringWriter((int)(l.size() * dec.averageCharsPerByte()));
          
              Iterator<Byte> itInput = l.iterator();
              int bytesRemaining = l.size();
              boolean finished = false;
              while (! finished)
              {
                  // work out how much data we are likely to be able to read
                  final int bPos = bbuf.position();
                  final int bLim = bbuf.limit();
                  int bSize = bLim-bPos;
                  bSize = Math.min(bSize, bytesRemaining);
                  while ((--bSize >= 0) && itInput.hasNext()) 
                  {
                      bbuf.put(itInput.next().byteValue());
                      --bytesRemaining;
                  }
                  bbuf.flip();
                  final int cStartPos = cbuf.position();
                  CoderResult cr = dec.decode(bbuf, cbuf, (bytesRemaining <= 0));
                  if (cr.isError()) cr.throwException();
                  bbuf.compact();
                  finished = (bytesRemaining <= 0) && (cr == CoderResult.UNDERFLOW);
                  final int cEndPos = cbuf.position();
                  final int cSize = cEndPos - cStartPos;
                  sw.write(chArr, cStartPos, cSize);
                  cbuf.clear();
              }
              return sw.toString();
          }
          

          但我真的不认为我会推荐这么简单的东西。

          【讨论】:

            【解决方案7】:

            一种选择可能是使用 StringBuilder:

            public static String byteListToString(List<Byte> l) {
                if (l == null) {
                    return "" ;
                }
                StringBuilder sb = new StringBuilder(l.size());
            
                for (Byte current : l) {
                    sb.append((char)current);
                }
            
                return sb.toString();
            }
            

            或者,如果您需要字符转换

            public static String byteListToString(List<Byte> l) {
                if (l == null) {
                    return "" ;
                }
                ByteArrayOutputStream bout = new ByteArrayOutputStream(l.size());
            
                for (Byte current : l) {
                    bout.write(current);
                }
            
                return bout.toString("UTF-8");
            }
            

            如果您正在聚合字节,请首先尝试 ByteArrayOutputStream 而不是字节列表。注意:注意 UnsupportedEncodingException - 您需要在某个地方尝试捕捉它。

            【讨论】:

            • 与 OP 发布的相比,两个 sn-ps 都更慢且内存效率低。
            【解决方案8】:

            查看BitConverter 课程,我认为它可以满足您的需求。与 List.toArray() 方法结合使用。

            【讨论】:

            • 这是一个 java 问题,不是 .net。
            • 虽然代码看起来与 C# 完全一样,但还是很有趣的。如果不是“Java”标签,那么就没有办法分辨了。也许我们需要一种更清晰的方式来指出编程问题中可能存在歧义的语言。
            • "for (Byte current : l)"
            • 您几乎总能通过查看字符串中的 s 来区分。字符串 = c#,字符串 = java。 :)
            • String 也可以在 .NET 中使用,它是类名而不是 C# 关键字。
            猜你喜欢
            • 2012-12-04
            • 1970-01-01
            • 1970-01-01
            • 2011-05-20
            • 1970-01-01
            • 2021-12-22
            • 1970-01-01
            • 2014-03-01
            • 1970-01-01
            相关资源
            最近更新 更多