gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-02 07:11:58 25 4
gpt4 key购买 nike

这是老手(er)的一个:-)

我正在从大型机 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 数据读取到字符数组中,使用
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 我在缓冲区 (1) 中得到 0,在缓冲区 (0) 中得到 3 - 很好。但是当两个字节是 00 20 时,我将 128 读入缓冲区(0)!

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

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

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

最佳答案

您无法将 EBCDIC 文件转储之类的内容作为流读取。 StreamReader 类是 TextReader 的一种类型,用于阅读 字符 .您正在阅读 记录 -- 包含混合二进制和文本的复杂数据结构。

您需要使用 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 表示这是跨区记录的“内部”段,即“除第一个或最后一个段之外的多段记录的段”。

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

    关于.net - 如何使用非标准代码页读取 EBCDIC 数据,而不是弄乱数字?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5109302/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com