【问题标题】:How to convert a float array to a single byte string?如何将浮点数组转换为单字节字符串?
【发布时间】:2018-02-28 10:40:48
【问题描述】:

我正在尝试向谷歌云的 ml 引擎上的模型发送 Json 请求。这需要表单中的 json

为此,我需要将浮点数组转换为单个 base64 编码字符串

我认为google protobuf ByteString 可能是我正在寻找的,但这似乎与字节数组(stackoverflow question on the difference between the two) 的行为方式相同。

我目前为“b64”键创建值的方法会创建一个字节字符串数组,这会导致谷歌云错误(see other question)

  public static String[] convertToBase64Bytes(float[] audio) {
    String[] data = new String[audio.length];
    for (int i = 0; i < audio.length; i++) {
      float amplitude = audio[i];
      byte[] byteArray = ByteBuffer.allocate(4).putFloat(amplitude).array();
      data[i] = Base64.encodeToString(byteArray, Base64.DEFAULT);
    }
    return data;
  }

我一直无法找到如何将整个浮点数组转换为单个 base64 字节字符串,然后 ml 引擎可以将其转换回原始数组。

如果它有用,我这样做的方式是 Python

bytes_string = audio_array.tostring() #audio_array is a numpy array
encoded = base64.b64encode(bytes_string)

有人可以帮忙吗?谢谢。

【问题讨论】:

  • 对不起,我错误地编辑了你的 questino 并删除了 json 示例。我似乎没有找到撤消它的方法。

标签: java android arrays google-cloud-platform google-cloud-ml


【解决方案1】:
public static String convertToBase64Bytes(float[] audio) { 
     ByteBuffer buff = ByteBuffer.allocate(4 * audio.length);
     for (int i = 0; i < audio.length; i++) {
       float amplitude = audio[i]; 
       buff.putFloat(amplitude);
     }
     String data = Base64.getEncoder().encodeToString(buff.array(), Base64.DEFAULT);
     return data; 
   }

【讨论】:

    【解决方案2】:

    对于这个解决方案,我使用 Gson() (you can the jar or the maven dependencies from here) 来生成最终字符串,如您的示例所示。

    我还创建了几个帮助类,您可以将它们放在项目的其他位置(不一定是内部类)。

    main方法只是提供运行代码的手段。

    输出如下:

    已编辑我

    每个浮动一个 b64 项目的原始解决方案。

    {"instances":[{"b64":"QUczMw=="},{"b64":"QgpmZg=="},{"b64":"wgHS8g=="},{"b64":"QU+uFA=="}]}
    

    代码:

    public class FloatEncoder {
    
        public static void main(String args[]) {
            FloatEncoder encoder = new FloatEncoder();
    
            float [] floats = new float[] {12.45f, 34.6f, -32.456f, 12.98f};
            String encodedJson = encoder.encode(floats);
            System.out.println(encodedJson);
        }
    
        private String encode(float[] floats) {
            String rtn;
            DataHolder holder = new DataHolder();
    
    
            String [] audios = convertToBase64Bytes(floats);
    
            for(String audio : audios) {
                B64 b64 = new B64();
                b64.b64 = audio;
                holder.instances.add(b64);
            }
    
            Gson gson = new GsonBuilder().disableHtmlEscaping().create();
            rtn = gson.toJson(holder);
    
            return rtn;
        }
    
          public static String[] convertToBase64Bytes(float[] audio) {
            String[] data = new String[audio.length];
            for (int i = 0; i < audio.length; i++) {
              float amplitude = audio[i];
              byte[] byteArray = ByteBuffer.allocate(4).putFloat(amplitude).array();
              data[i] = Base64.getEncoder().encodeToString(byteArray);
            }
            return data;
          }
    
          public static class DataHolder{
              public ArrayList<B64> instances = new ArrayList<>();
          }
    
          public static class B64{
              public String b64;
          }
    }
    

    编辑二

    一个 b64 项目的解决方案,其中浮点数数组编码为单个 字符串。

    {"instances":[{"b64":"QUczM0IKZmbCAdLyQU+uFA=="}]}
    

    字符串是字节数组的 Base64 编码,其中前 4 个字节是第一个浮点数,后 4 个字节是第二个浮点数,依此类推。

    public class FloatEncoder {
    
        public static void main(String args[]) {
            FloatEncoder encoder = new FloatEncoder();
    
            float [] floats = new float[] {12.45f, 34.6f, -32.456f, 12.98f};
            String encodedJson = encoder.encode(floats);
            System.out.println(encodedJson);
        }
    
        private String encode(float[] floats) {
            String rtn;
            DataHolder holder = new DataHolder();
    
    
            String audios = convertToBase64Bytes(floats);
            B64 b64 = new B64();
            b64.b64 = audios;
            holder.instances.add(b64);
    
            Gson gson = new GsonBuilder().disableHtmlEscaping().create();
            rtn = gson.toJson(holder);
    
            return rtn;
        }
    
          public static String convertToBase64Bytes(float[] audio) {
            ByteBuffer byteBuffer = ByteBuffer.allocate(4 * audio.length);
            for (int i = 0; i < audio.length; i++) {
              float amplitude = audio[i];  
              byteBuffer.putFloat(amplitude);
            }
            byte[] data = byteBuffer.array();
            String rtn = Base64.getEncoder().encodeToString(data);
            return rtn;
          }
    
          public static class DataHolder{
              public ArrayList<B64> instances = new ArrayList<>();
          }
    
          public static class B64{
              public String b64;
          }
    }
    

    【讨论】:

    • 谢谢!一些澄清。 1)我的目标是为每个浮点数组创建一个字节字符串,您的示例将数组中的每个浮点数作为单独的字节字符串。我试图通过连接编码 for 循环中的音频字符串来创建一个字符串,但是它非常慢。你有更好的建议吗? 2)您知道为什么您的方法生成的字符串(“QUczMw\u003d\u003d\nQgpmZg\u003d\u003d\nwgHS8g\u003d\u003d\nQU+uFA\u003d\u003d\n”连接时)与@user不同: 4956493 答案 (QUczM0IKZmbCAdLyQU+uFA==)?
    • java 中的浮点数是 4 个字节。一个字节不能容纳 4 个字节。当您对 base64 进行编码时,字节数会增加,因为编码如何将值带入可打印字符域。默认情况下,json 会转义 html,因此我对其进行了更改,以便您可以看到 == 符号。
    • 您提到的串联不起作用。我认为您需要的格式是您公开的格式(我错误地删除了:()。您需要清楚信息必须如何到达目的地。如果是您在另一端接收json,您可以轻松撤消编码。
    • 我对这个例子不好,我的意思是显示可以发送多个音频阵列,我会更清楚地说明这一点。另一边是谷歌云,它会自动将数组的base64字符串解码为字节,所以我需要能够发送一个代表整个浮点数组的字符串。我已经设法在 python 中做到这一点,所以我希望它也可以在 java 中实现?
    • yosher lutskis 答案确实发送了谷歌云接受的单字节字符串,但您的答案看起来更像我以前见过的字节字符串的形式(即 [numpy_array].tostring() 的结果),所以我想知道您的版本是否可以制作成单个字符串
    猜你喜欢
    • 2011-11-25
    • 2019-09-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-15
    • 2011-12-18
    相关资源
    最近更新 更多