vba 在VBA中将大端转换为小端,反之亦然

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2666874/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-11 11:33:56  来源:igfitidea点击:

Converting big-endian into little-endian and vice-versa in VBA

vbaexcel-vbaendiannessexcel

提问by Jean-Fran?ois Corbett

My machine is little-endian (Intel byte order). I need to read a binary file containing 16-bit signed integer data in Motorola/IEEE byte order ("big-endian"), then do some calculations, and finally write the resulting integerdata in a big-endian binary file.

我的机器是小端(英特尔字节顺序)。我需要读取一个包含摩托罗拉/IEEE 字节顺序(“big-endian”)中的 16 位有符号整数数据的二进制文件,然后进行一些计算,最后将结果integer数据写入一个 big-endian 二进制文件中。

How do I do the above in VBA, i.e. convert big-endian into little-endian and vice-versa?

我如何在 VBA 中执行上述操作,即将大端转换为小端,反之亦然?

The reason is, I'm processing NASA Shuttle Radar Topography Missiondata (HGT file format).

原因是,我正在处理 NASA Shuttle Radar Topography Mission数据(HGT 文件格式)。

采纳答案by Martin Liversage

Here is a subroutine that may get you started:

这是一个可以帮助您入门的子程序:

Public Sub ProcessData()
  Dim inputFileName As String
  Dim outputFileName As String
  Dim wordCount As Integer
  Dim i As Integer
  Dim msb As Byte
  Dim lsb As Byte
  Dim unsignedWord As Long
  Dim word As Integer

  inputFileName = "C:\Input.bin"
  outputFileName = "C:\Output.bin"

  wordCount = FileLen(inputFileName) / 2

  Open inputFileName For Binary Access Read As #1
  Open outputFileName For Binary Access Write As #2

  For i = 1 To wordCount
    Get #1, , msb
    Get #1, , lsb

    unsignedWord = CLng(msb) * 256 + lsb
    If unsignedWord > 32768 Then
      word = -CInt(65536 - unsignedWord)
    Else
      word = CInt(unsignedWord)
    End If

    ' Do something with each word.
    word = -word

    If word < 0 Then
      unsignedWord = 65536 + word
    Else
      unsignedWord = word
    End If
    msb = CByte(unsignedWord / 256)
    lsb = CByte(unsignedWord Mod 256)

    Put #2, , msb
    Put #2, , lsb
  Next

  Close #1
  Close #2
End Sub

回答by GSerg

By using simple bitwise logic.

通过使用简单的按位逻辑。

Public Function SwapBytes(ByVal i As Integer) As Integer
  Dim b1 As Byte, b2 As Byte

  b1 = i And &HFF

  If i And &H8000 Then
    b2 = ((i And &H7F00) / 256) Or &H80
  Else
    b2 = (i And &HFF00) / 256
  End If

  If b1 And &H80 Then
    SwapBytes = (b1 And &H7F) * 256 Or b2 Or &H8000
  Else
    SwapBytes = b1 * 256 Or b2
  End If

End Function

Well, not so simple due to VBA limitations. Still, I believe that will be much faster than calling CopyMemory function twice.

好吧,由于 VBA 的限制,并不是那么简单。不过,我相信这比两次调用 CopyMemory 函数要快得多。

回答by Elimar

Here is a simple ASCII conversion:

这是一个简单的 ASCII 转换:

Public Function SwapLong(Data As Long) As Long

    Const Sz As Integer = 3
    Dim Bytes(Sz) As Byte
    Dim n As Integer
    Dim HexStr As String
    Dim SwpStr As String

    HexStr = Right("00000000" + Hex(Data), 2 * (Sz + 1))
    SwpStr = vbNullString

    For n = 0 To Sz
        SwpStr = SwpStr + Mid(HexStr, (Sz - n) * 2 + 1, 2)
    Next n

    SwapLong = CLng("&h" + SwpStr)

End Function

Public Function SwapInt(Data As Integer) As Integer

    Const Sz As Integer = 1
    Dim Bytes(Sz) As Byte
    Dim n As Integer
    Dim HexStr As String
    Dim SwpStr As String

    HexStr = Right("0000" + Hex(Data), 2 * (Sz + 1))
    SwpStr = vbNullString

    For n = 0 To Sz
        SwpStr = SwpStr + Mid(HexStr, (Sz - n) * 2 + 1, 2)
    Next n

    SwapInt = CInt("&h" + SwpStr)

End Function