将Fortran二进制输出转换为Visual Basic .NET

如何解决将Fortran二进制输出转换为Visual Basic .NET

我们有一个基于Intel编译器的小型Fortran程序,该程序可输出二进制数据。我正在尝试将该代码重构为.NET。我研究了Fortran中的二进制编写方式是如何工作的,但是有点迷茫。使用相同的输入,我们不会获得相同的二进制输出。我想念什么?

Fortran程序基本上如下所示:

CHARACTER * 3  dept(400)
CHARACTER * 4  code(30)
CHARACTER * 7  zdate(400)
REAL           wt(400),WT99(400),WT90(400),WT50(400) 
Integer        ops(400),J,K

OPEN( 7,FILE = 'C\stats.BIN',ACCESS='SEQUENTIAL',FORM='UNFORMATTED')

for each record
    Write(7) code(I),( dept(K),wt(K),ops(K),zdate(K),WT99(K),WT90(K),WT50(K),K = 1,J )
next record

我尝试重写.NET

Public Class CityStats
    Public Property Dept As String
    Public Property Weight As Integer
    Public Property NumOps As Integer
    Public Property LastOpDate As DateTime
    Public Property CheckDate As DateTime
    Public Property 99Percentile As Double
    Public Property 90Percentile As Double
    Public Property 50Percentile As Double
End Class


Dim city As String = "BB",xcode as Integer = 1

Dim str As Stream = File.Open"C:\stats.BIN",FileMode.Create)
Using bw As BinaryWriter = New BinaryWriter(str)
      Dim sb As New StringBuilder(4,4)
      sb.Append(city & xcode.ToString("00"))
      bw.Write(sb.ToString)
      bw.Write(cityStats.Count)

      'cycle through all the records
      For Each out In CityStats
          bw.Write(out.Dept)
          bw.Write(out.Weight)
          bw.Write(out.NumOps)
          bw.Write(out.CheckDate.ToString("ddMMMyy").ToUpper)
          bw.Write(out.99Percentile)
          bw.Write(out.90Percentile)
          bw.Write(out.50Percentile)
      Next out
 End Using

解决方法

好吧,我被束缚了,但最终找到了解决我问题的方法。最后,关键是理解数据类型以及它们在FORTRAN和.NET之间的映射。如果我们以上述示例为例,那么我将更新代码以复制由FORTRAN程序生成的二进制文件。

我通过获取两个二进制文件并通过F90二进制读取器运行它们来进行验证。所有数据均具有可比性。就是说,字符串和整数是精确的,而单打则相当接近。对于此过程,单个数据在十分之一以内,对我来说已经足够了,因为一些数据是四舍五入的。

Public Class CityStats
    Public Property Dept As String
    Public Property Weight As Integer
    Public Property NumOps As Integer
    Public Property LastOpDate As DateTime
    Public Property CheckDate As DateTime
    Public Property 99Percentile As Double
    Public Property 90Percentile As Double
    Public Property 50Percentile As Double
End Class


Dim city As String = "BB",xcode as Integer = 1

'open a main BinaryWriter
Dim str As Stream = File.Open"C:\stats.BIN",FileMode.Create)
Using bw As BinaryWriter = New BinaryWriter(str)
      'write to a temp BinaryWriter so we can determine the record length before we write it to the main BinaryWriter.
      Dim msRec As New MemoryStream
      Dim bwRec As New BinaryWriter(msRec)

      Dim cx As String = F90FixedString(city & xcode.ToString("00"),3)
      bwRec.Write(cx.ToCharArray)   'see note below about strings vs char arrays
      bwRec.Write(cityStats.Count)

      'cycle through all the records for one X code and write out to binary. in this case a FORTRAN REAL defaults
      'to a 4 byte single precision float or in .NET it is a type Single. Also we do not write out a string as the
      'BinaryWriter will prepend it with the string length. instead we convert the string to an array of characters.
      'The Fortran Integer is a 4-byte signed integer by default so that is equivalent to the .NET Integer type.
      For Each out In CityStats
          bwRec.Write(out.Dept.ToCharArray)
          bwRec.Write(out.Weight)
          bwRec.Write(out.NumOps)
          bwRec.Write(out.CheckDate.ToString("ddMMMyy").ToUpper.ToCharArray)
          bwRec.Write(CSng(out.99Percentile))
          bwRec.Write(CSng(out.90Percentile))
          bwRec.Write(CSng(out.50Percentile))
      Next out

      'get record length in bytes. Note: BaseStream.Length is 64-bit but my data is rather small so am confident I will never get to > 32-bit
      Dim recLenInBytes As Integer = CInt(bwRec.BaseStream.Length)

      'now write the temp BinaryWriter to our main BinaryWriter. preceded and followed by a 32-bit integer
      'containing the record length.
      bw.Write(recLenInBytes)
      bw.Write(msRec.ToArray)
      bw.Write(recLenInBytes)
 End Using


'a fixed length string in FORTRAN is left-justified and by default conisist of spaces.
Public Function F90FixedString(ByVal inp As String,ByVal strLen As Integer) As String
    'checks
    If inp Is Nothing Then Throw New Exception("Null string. Can't create a fixed length string.")

    'if the string is already the required length then just return the input string
    If inp.Length = strLen Then Return inp

    'pad the string to the right with spaces if required
    Dim out As String = inp.PadRight(strLen," "c)

    'now check to see if the new string is longer than required and if so then we take the
    'proper amount of characters starting from the left.
    If out.Length > strLen Then out = out.Substring(0,strLen)

    'return the new string
    Return out
End Function

信息很难找到,其中有些已经过时了。有了这些链接和一些反复试验,一切都解决了。我使用的是Lahey F90编译器,因此根据您使用的特定编译器和设置,您的结果可能会有所不同。

Opening Binary Files in Fortran: Status,Form,Access https://software.intel.com/content/www/us/en/develop/documentation/fortran-compiler-developer-guide-and-reference/top/compiler-reference/data-and-i-o/fortran-i-o/record-length.html

未格式化的文件(FORM ='UNFORMATTED'):以4字节为单位指定记录长度,除非您指定了bytebytel编译器假定为1字节为单位。

https://community.intel.com/t5/Intel-Fortran-Compiler/Convert-REAL-8-Unformatted-Sequential-file/td-p/771973

Visual Fortran SEQUENTIAL UNFORMATTED文件格式在UNIX系统(包括DIGITAL UNIX)上非常常见。每个Fortran“记录”的前面和后面 由包含记录长度的32位整数组成(该整数存储在“ little-endian”布局中,最低有效位位于最低寻址字节中。)此记录长度是应用Fortran记录语义所必需的,包括使用BACKSPACE的能力。不幸的是,这在《程序员指南》中没有正确记录-所描述的布局实际上是Microsoft Fortran PowerStation的布局。这将在以后的版本中得到纠正。

Why does BinaryWriter prepend gibberish to the start of a stream? How do you avoid it? https://software.intel.com/content/www/us/en/develop/documentation/fortran-compiler-developer-guide-and-reference/top/compiler-reference/data-and-i-o/fortran-i-o/record-length.html

.NET BinaryWriter.Write() Method -- Writing Multiple Datatypes Simultaneously https://docs.microsoft.com/en-us/dotnet/api/system.io.binarywriter.write?view=netframework-4.7

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 <select id="xxx"> SELECT di.id, di.name, di.work_type, di.updated... <where> <if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 <property name="dynamic.classpath" value="tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams['font.sans-serif'] = ['SimHei'] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -> systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping("/hires") public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate<String
使用vite构建项目报错 C:\Users\ychen\work>npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-