如何使用非标准代码页读取 EBCDIC 数据,而不弄乱数字?

2023-12-05

这是给老手的:-)

我正在从大型机 DB2 表中读取二进制转储。该表具有 varchar、char、smallint、integer 和 float 列。有趣的是,DB2 使用代码页 424(希伯来语)。我需要我的代码独立于代码页。

因此,我使用 System.Text.Encoding 使用流阅读器打开文件,如下所示:

Dim encoding As System.Text.Encoding = System.Text.Encoding.GetEncoding(20424)
Dim sr As New StreamReader(item.Key, encoding)

并继续根据长度将 VARCHAR 和 CHAR 数据读取到 char 数组中,使用

sr.ReadBlock(buffer, 0, iFieldBufferSize)

始终记住 VARCHAR 列中的前 2 个字节应该被丢弃 并获得正确的字符串

SringValue = encoding.GetString(encoding.GetBytes(buffer))

一切都很棒!

但现在我进入 SMALLINT 列,我遇到了麻烦。有符号数的值存储在 2 个字节中,并且因为它是大尾数,所以我这样做

Dim buffer(iFieldBufferSize - 1) As Byte
buffer(1) = sr.Read ''switch the bytes around!
buffer(0) = sr.Read
Dim byteBuffer(iFieldBufferSize - 1) As Byte
Dim i16 As Int16 = BitConverter.ToUInt16(buffer, 0)

我得到了错误的数字!例如,如果字节是 00 03,我在 buffer(1) 中得到 0,在 buffer(0) 中得到 3 - 很好。但是当两个字节为 00 20 时,我将 128 读入缓冲区(0)!

因此,经过半天的拉扯我的头发后,我从流读取器声明中删除了编码器,现在我将 32 个读入缓冲区(0),就像它应该的那样!

最重要的是,非标准代码页编码器弄乱了字节读数!

知道如何解决这个问题吗?


您无法将 EBCDIC 文件转储之类的内容读取为流。 StreamReader 类是 TextReader 的一种类型,存在用于读取人物。你正在读一本record-- 包含混合二进制和文本的复杂数据结构。

您需要使用 FileStream 进行读取,并根据需要读取八位字节块。您将需要一些简单的辅助方法,如下所示:

private byte[] ReadOctets( Stream input , int size )
{
    if ( size < 0 ) throw new ArgumentOutOfRangeException() ;

    byte[] octets      = new byte[size] ;
    int    octets_read = input.Read( octets , 0 , size ) ;

    if ( octets_read != size ) throw new InvalidDataException() ;

    return octets ;
}

public string readCharVarying( Stream input )
{
    short    size        = readShort( input ) ;

    return readCharFixed( input , size ) ;
}

public string readCharFixed( Stream input , int size )
{
    Encoding e           = System.Text.Encoding.GetEncoding(20424) ;
    byte[]   octets      = ReadOctets( input , size ) ;
    string   value       = e.GetString( octets ) ;

    return value ;
}

private short readShort( Stream input )
{
    byte[] octets            = ReadOctets(input,2) ;
    short  bigEndianValue    = BitConverter.ToInt16(octets,0) ;
    short  littleEndianValue = System.Net.IPAddress.NetworkToHostOrder( bigEndianValue ) ;

    return littleEndianValue ;
}

private int readInt( Stream input )
{
    byte[] octets            = ReadOctets(input,4) ;
    int    bigEndianValue    = BitConverter.ToInt32(octets,0) ;
    int    littleEndianValue = System.Net.IPAddress.NetworkToHostOrder( bigEndianValue ) ;

    return littleEndianValue ;
}

private long readLong( Stream input )
{
    byte[] octets            = ReadOctets(input,8) ;
    long   bigEndianValue    = BitConverter.ToInt64(octets,0) ;
    long   littleEndianValue = System.Net.IPAddress.NetworkToHostOrder( bigEndianValue ) ;

    return littleEndianValue ;
}

IBM 大型机的文件系统中通常有固定或可变长度的记录。固定长度很简单:您只需要知道记录长度,并且可以通过一次调用 Read() 方法读取记录的所有字节,然后根据需要转换各个片段。

可变长度记录有点棘手,它们以 4 字节记录描述符字开头,由 2 字节(16 位)逻辑记录长度组成,后跟 2 字节(16 位)0 值。逻辑记录长度不包括 4 个八位字节的记录描述符字。

您可能还会看到可变的跨记录。它们与可变长度记录类似,只是 4 个八位字节的前缀是段描述符字。前 2 个八位位组包含段长度,下一个八位位组标识段类型,最后一个八位位组为 NUL (0x00)。段类型如下:

  • 0x00表示一条完整的逻辑记录
  • 0x01 表示这是跨区记录的第一段
  • 0x10 表示这是跨区记录的最后一段
  • 0x11 表示这是跨区记录的“内部”段,即“除第一个或最后一个段之外的多段记录的段”。

您可以将可变长度和可变跨度记录视为相同。要读取其中一个,您首先需要解析出段/记录/描述符字,并将完整记录从其组成段读取/组装成 byte[],然后执行任何需要执行的操作来转换该字节[] 转换为您可以使用的形式。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何使用非标准代码页读取 EBCDIC 数据,而不弄乱数字? 的相关文章

随机推荐

  • 子文档中的 SD MongoDB 多态性

    我刚刚开始使用 spring data mongodb 用 Ja va 开发一些应用程序 并遇到了一些我无法解决的问题 有几个像这样的文档 bean Document collection myBeanBar public class Ba
  • 显示站点根目录外部的图像

    类似的问题在这里被问到 从文档根目录外部提供图像 给出并接受的解决方案是使用 Apache Aliases 但是 文件夹的 Apache 别名是否也会将其公开 我想服务于一个形象并保持它在公众视野中的隐形性 除了别名之外 有谁知道在文档根目
  • Git 从浅克隆中查找自 以来修改的文件

    我在 CI 盒子上运行测试 为了加快速度 我只是做了一个浅克隆 git clone depth 1 email protected JoshCheek some repo git 假设所有测试都通过 我想触发管道中的下一步 触发的内容取决于
  • bigquery 流缓冲区会持续多长时间

    我目前正在将数据从sql server数据库系统迁移到bigquery 并且在尝试从具有活动流缓冲区的bigquery表中删除记录时遇到了问题 您能否确认流缓冲区在被删除之前会持续多长时间那么删除操作可以运行吗 我发现这给开发过程带来了不必
  • 在 C# 中解析阿拉伯日期?

    我在解析日期时遇到了问题 该程序被阿拉伯日期绊倒了 因为某些原因DateTime TryParse 为这种文化输出垃圾 这是说明我的问题的示例代码 var culture CultureInfo CreateSpecificCulture
  • Android 类似 TreeView 的功能

    我正在实施TreeView对于我的应用程序 我在网上搜索了一下 找到了一个ListView执行TreeView这太乱了 是否可以实现n级TreeView using ExpandableListView 请分享您的想法或给我参考一些例子 提
  • Robot Framework - 将 Appium 驱动程序传递给 python 脚本

    我正在使用 Python 将 Robot Framework 与 Appium 集成 但是我不知道如何将 Robot Framework 中创建的 Appium 驱动程序传递给自定义 python 脚本 我的环境 Mac 操作系统 小牛队
  • 通过 firebase 函数发送电子邮件

    有一种方法可以使用像 sendgrid mailgun 这样的API通过Firebase云功能发送电子邮件 或者它被视为出站连接 假设您这么问是因为您使用的是免费 Firebase 计划 正如上所解释的Firebase 定价页面 Spark
  • Bash:变量未正确扩展[重复]

    这个问题在这里已经有答案了 我正在尝试使用变量重命名文件 但是 当我将变量插入到文件名的开头时 事情没有按预期工作 情况如下 我有一个文件名测试 ls test 和一个变量i 1 将变量添加到文件名的末尾或中间时 它可以工作 mv test
  • 将字符串转换为日期,即将完成! [复制]

    这个问题在这里已经有答案了 可能的重复 将符合 ISO8601 的字符串转换为 java util Date 我正在尝试转换这个字符串 2011 06 07T14 08 59 697 07 00 对于 Java Date 到目前为止 我做了
  • CSS 边框样式:波浪

    我在 w3 org 上看到了这个文档 http www w3 org TR 2002 WD css3 border 20021107 borderstyles png显示 border style wave 属性 我急于尝试 在 Firef
  • 可以将一系列键映射到值的数据结构

    我试图找到一种数据结构 该结构从一系列值中获取特定值并将其映射到键 例如 我有以下条件 从1到2 9 我想把它映射到A 从4到6 我想将其映射到B 从6 5到10 我想将其映射到C 我的值为 5 我想将其映射到一个键 所以根据以上条件 我应
  • 使用 SnakeYaml 转储带引号的值

    有一个简单的 yml 文件test yml如下 color red 我按如下方式加载和转储文件 final DumperOptions yamlOptions new DumperOptions yamlOptions setDefault
  • Power Query:通过乘以另一列来转换列

    我想做类似的事情Power Query 根据另一列转换一列 但我陷入了如何修改语法以实现我的特定目标的困境 与链接的问题类似 假设我有下表 Table 1 Column A Column B Column C 1 4 7 2 5 8 3 6
  • 我可以在 Python 中多次等待同一个任务吗?

    我需要做很多工作 但幸运的是 很容易解耦到不同的任务中进行异步执行 其中一些是相互依赖的 我很清楚任务如何能够await其他多个人来获取他们的结果 但是 我不知道如何让多个不同的任务等待同一个协程 并且都得到结果 这文档据我所知也没有提到这
  • input 与 raw_input:Python 交互式 Shell 应用程序?

    我正在研究这个问题的答案 Python 交互式 Shell 类型应用程序 我的代码看起来像这样 def main while True s input gt if s hello print hi if s exit break if na
  • 将未知长度的切片中的值分配给 Go 中的结构体?

    我从github上的一些有用的包中找到了下面的案例 它看起来是如此丑陋和愚蠢 我认为更好的代码设计可以避免这种情况 但是如果遇到这种情况 是不是可以写得更简洁呢 有没有更好的方法来代替连续检查切片长度 package main type N
  • 真实设备产生过多日志

    我正在为 Android 开发一个简单的程序 我在真实设备 samsung young android 2 3 上进行了测试 我的程序会生成一些日志输出以用于调试目的 一切都很好 但我的设备开始在 Eclipse LogCat 窗口中生成大
  • hibernate中的cascade和inverse有什么区别,它们的用途是什么?

    如何在hibernate中使用级联和逆 定义它们的过程 标签是什么 它们彼此相关吗 它们有何用处 通过中间表建立多对多关系的情况 Cascade 表示是否将在子表中创建 更新记录 而 Inverse 表示是否会在中间表中创建 更新记录 例如
  • 如何使用非标准代码页读取 EBCDIC 数据,而不弄乱数字?

    这是给老手的 我正在从大型机 DB2 表中读取二进制转储 该表具有 varchar char smallint integer 和 float 列 有趣的是 DB2 使用代码页 424 希伯来语 我需要我的代码独立于代码页 因此 我使用 S