【问题标题】:Converting an array of bytes to an array of floats将字节数组转换为浮点数组
【发布时间】:2009-02-20 16:52:47
【问题描述】:

我目前正在将用于随机二进制文件访问的 Delphi 方法转换为 Java。 Delphi 程序使用:

TSingleArray  = Array[0..MAXSIZE] of Single
...
procedure GetLinkValues(const LinkVar: Integer;  const TimePeriod: Integer; var Value: PSingleArray);
...
BlockRead(Fout, Value^, Nlinks*SizeOf(Single));

将一个字节数组读入一个Single数组。在 Java 中是否有一种等效的方法可以在不遍历数组的情况下执行此操作?

我正在使用

List<Float> l = new ArrayList<Float>();
…
for (int i = 0 ; i < nLinks ; i++ )
l.add( resultsFile.readFloat());

但我担心速度。字节序不是问题。

【问题讨论】:

    标签: java delphi arrays


    【解决方案1】:

    您是否分析过代码并实际上发现它是一个问题? 有些东西将不得不循环......你确定这是你代码中的瓶颈吗?

    说了这么多,您应该可以使用我怀疑可以满足您要求的 FloatBuffer。不幸的是,Sun 的 JavaDoc 已关闭,因此我现在无法轻松链接或查看文档。

    要使用 FloatBuffer,您可能需要:

    • 创建与文件关联的 FileChannel(例如,使用 FileInputStream.getChannel)
    • 创建一个字节缓冲区
    • 使用 ByteBuffer.asFloatBuffer 创建一个封装 ByteBuffer 的 FloatBuffer
    • 使用 FileChannel.read(byteBuffer) 读入 ByteBuffer
    • 从 FloatBuffer 读取

    我对 java.nio 不是特别熟悉/不熟悉,所以我希望这一切都是正确的 - 但它可能非常繁琐。你当前的循环几乎肯定更简单,所以我强烈建议你先检查一下它的性能!您可能希望将当前的 FileInputStream 包装在 BufferedInputStream 中,顺便说一句。

    【讨论】:

    • 对我有用,至少我第三次尝试过。 java.sun.com/javase/6/docs/api/java/nio/FloatBuffer.html
    • 我认为这意味着答案是否定的。我一直在寻找一种在 Java 中复制指针操作的方法,用字节填充 Simple(float)数组,因为我相信(可能是错误的)这可以避免迭代。稍后我可以使用 myArray[n] 读取值
    • @GrahamA:您可以使用 FloatBuffer 进行块复制,这将是高效的 - 但代码会更加复杂。基本上你可以有效率或简单,但不能两者兼而有之。你测试过简单代码的速度了吗?
    • 使用 System.currentTimeMillis() 和 65Mb 文件进行分析。读取 27446 条记录。 List 140 毫秒 ByteBuffer 0 遍历列表和字节缓冲区(转换为数组后)为 16 毫秒。我尝试了几种不同大小的结果文件,得到了一致的答案。
    • 您是否确保先刷新文件系统缓存?否则第一次读取它会命中磁盘,而第二次则不会。此外,16ms 对您来说真的是个问题吗?即使 ByteBuffer 快很多,这肯定对你来说是个瓶颈吗?
    【解决方案2】:

    根据 Jon 提供的帮助,最终代码如下所示:

    byte[] bt = new byte[nLinks * 4];
    List<Float> l = new ArrayList<Float>();
    if (linkVar != 0 && timePeriod < nPeriods) {
        long p1 = RECORDSIZE * (nNodes * NODEVARS + nLinks * LINKVARS);
        long p2 = RECORDSIZE * (nNodes * NODEVARS + nLinks * (linkVar - 1));
        long p3 = offset2 + (timePeriod * p1) + p2;
        resultsFile.seek(p3);
    
        resultsFile.read(bt, 0, nLinks * 4);
        ByteBuffer bb = ByteBuffer.wrap(bt);
        bb.rewind();
        bb.asFloatBuffer().get(values);
    }
    

    【讨论】:

      【解决方案3】:

      总会有一个循环——无论是你自己的,还是在缓冲区复制方法/操作内部。加快速度的唯一方法是找到支持向量运算的硬件和编译器。

      【讨论】:

        猜你喜欢
        • 2016-08-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-03-25
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多