在 C# 中读取 COBOL COMP 数据
Read COBOL COMP data in C#
我是 COBOL 新手,我一直在尝试从 table.
输出的文本文件中读取记录信息
大多数我都可以接受的非 comp 数据类型,这是 'COMP' 我被卡住的。
我今天一整天都在努力解决这个问题,尽我所能阅读。
下面的日期字段是我无法转换为日期字符串的字段:
05 VALDATE PIC 9(6) COMP
05 PAYDATE PIC 9(6) COMP
05 SYSDATE PIC 9(6) COMP
据我了解,上述所有类型在文件中各占 4 个字节。
它们应该是代表 YYMMDD
的日期,但数据似乎并没有那么小。我查看了 EBCDIC 并反转了 byte[]
数据并使用 BitConverter.ToUNIT32()
并更改了用于读取文件的编码,但没有成功。
我读到计算为整数的日期存储为从 1601 年 1 月 1 日开始的天数,因此下面的代码试图将值添加到 1601。(http://www.techtricky.com/cobol-date-functions-list-add-find-duration/)
我的问题是文本文件中的数据不正确,或者我缺少获取类似于 YYMMDD
.
的日期的步骤
以上3项数据如下:
[ 32] [237] [ 44] [ 4] | 00100000 11101101 00101100 00000100
[ 33] [ 14] [ 32] [237] | 00100001 00001110 00100000 11101101
[131] [ 48] [ 48] [ 48] | 10000011 00110000 00110000 00110000
以及我打开文件的方式,我已经将编码更改为 ascii 但没有运气:
using (BinaryReader reader = new BinaryReader(File.Open(nFilePath, FileMode.Open), Encoding.Default))
用于尝试读取 COMP 字段的代码:
public class DateFromUIntExtractor : LineExtractor
{
public DateFromUIntExtractor() : base(4)
{
}
public override string ExtractText(BinaryReader nReader)
{
// e.g 32,237,44,44, included but commented out things i've tried
byte[] data = nReader.ReadBytes(Length); // Length = 4
//Array.Reverse(data); - Makes num = 552414212
//data = ConvertAsciiToEbcdic(data);
int num = BitConverter.ToUInt32(data, 0);
// in this example num = 70053152
DateTime date = new DateTime(1601,1,1);
date = date.AddDays(num); // Error : num is too big
Extract = date.ToString("yyyyMMdd");
return Extract;
}
}
数据格式有误吗?或者我错过了什么?
更新
我要完成的任务是复制一个 COBOL 程序,该程序将数据从一个定义转换为另一个定义但采用 CSV 格式,因为该程序输出一个 .dat 文件。
来源
我对源定义的缺乏经验的解释是,文本文件中的数据要么是PUA-ICGROUP
,要么是PUA-PUGROUP
。查看 COBOL 程序它在 PUA-HEADER>PUA-KEY>PUA-RTYPE = "03"
时选择 PUA-ICGROUP
,其他一切都是 PUA-PUGROUP
.
C-WRITE-START.
IF PUA-RTYPE = 3 THEN
PERFORM C-WRITE-A
ELSE
PERFORM C-WRITE-B
END-IF.
C-WRITE-EXIT.
EXIT.
定义
01 DLRPUARC.
03 PUA-HEADER.
05 PUA-KEY.
07 PUA-CDELIM PIC 99.
07 PUA-SUPNO PIC 9(7).
07 PUA-RTYPE PIC 99.
07 PUA-REF PIC 9(9).
07 PUA-SEQ PIC 999.
05 PUA-ALTKEY.
07 PUA-ACDELIM PIC 99.
07 PUA-ASUPNO PIC 9(7).
07 PUA-ATRNDATE PIC 9(6).
07 PUA-ARTYPE PIC 99.
07 PUA-AREF PIC 9(9).
07 PUA-ASEQ PIC 999.
05 FILLER PIC X(82).
03 PUA-ICGROUP REDEFINES PUA-HEADER.
05 FILLER PIC X(52).
05 PUA-ICEXTREF PIC X(10).
05 PUA-ICORDNO PIC 9(11).
05 PUA-ICVALDATE PIC 9(6) COMP.
05 PUA-ICPAYDATE PIC 9(6) COMP.
05 PUA-ICSYSDATE PIC 9(6) COMP.
05 PUA-ICTRNVAL PIC S9(9).
05 PUA-ICCLRREF PIC 9(6).
05 PUA-ICDELDATE PIC 9(6) COMP.
05 PUA-ICOTHQRY PIC X.
05 PUA-ICPRCQRY PIC X.
05 PUA-ICMRSQRY PIC X.
05 PUA-ICDSCTYPE PIC 9.
05 PUA-ICDSCVAL PIC S9(9) COMP.
05 PUA-ICVATCODE PIC 9.
05 PUA-ICVATAMT PIC S9(8) COMP.
05 PUA-ICTAXAMT PIC S9(8) COMP.
05 PUA-ICMRSREF PIC 9(6).
05 PUA-ICSUBDIV PIC 9.
05 PUA-ICCOSTCTR PIC X(5).
05 PUA-ICSEQIND PIC X.
05 FILLER PIC X(4).
03 PUA-PUGROUP REDEFINES PUA-HEADER.
05 FILLER PIC X(52).
05 PUA-PUEXTREF PIC X(10).
05 PUA-PUORDNO PIC 9(11).
05 PUA-PUVALDATE PIC 9(6) COMP.
05 FILLER PIC XXX.
05 PUA-PUSYSDATE PIC 9(6) COMP.
05 PUA-PUTRNVAL PIC S9(9).
05 PUA-PUCLRREF PIC 9(6).
05 PUA-PUDELDATE PIC 9(6) COMP.
05 PUA-PUOTHQRY PIC X.
05 PUA-PUSUBDIV PIC 9.
05 FILLER PIC X(32).
输出定义
01 OUT-A-REC.
03 OUT-A-PUA-CDELIM PIC 99.
03 OUT-A-PUA-SUPNO PIC 9(7).
03 OUT-A-PUA-RTYPE PIC 99.
03 OUT-A-PUA-REF PIC 9(9).
03 OUT-A-PUA-SEQ PIC 999.
03 OUT-A-PUA-ATRNDATE PIC 9(8).
03 OUT-A-PUA-ICEXTREF PIC X(10).
03 OUT-A-PUA-ICORDNO PIC 9(11).
03 OUT-A-PUA-ICVALDATE PIC 9(8).
03 OUT-A-PUA-ICPAYDATE PIC 9(8).
03 OUT-A-PUA-ICSYSDATE PIC 9(8).
03 OUT-A-PUA-ICTRNVAL PIC S9(9) SIGN LEADING SEPARATE.
03 OUT-A-PUA-ICCLRREF PIC 9(6).
03 OUT-A-PUA-ICDELDATE PIC 9(8).
03 OUT-A-PUA-ICOTHQRY PIC X.
03 OUT-A-PUA-ICPRCQRY PIC X.
03 OUT-A-PUA-ICMRSQRY PIC X.
03 OUT-A-PUA-ICDSCTYPE PIC 9.
03 OUT-A-PUA-ICDSCVAL PIC S9(9) SIGN LEADING SEPARATE.
03 OUT-A-PUA-ICVATCODE PIC 9.
03 OUT-A-PUA-ICVATAMT PIC S9(8) SIGN LEADING SEPARATE.
03 OUT-A-PUA-ICTAXAMT PIC S9(8) SIGN LEADING SEPARATE.
03 OUT-A-PUA-ICMRSREF PIC 9(6).
03 OUT-A-PUA-ICSUBDIV PIC 9.
03 OUT-A-PUA-ICCOSTCTR PIC X(5).
03 OUT-A-PUA-ICSEQIND PIC X.
03 OUT-A-CTRL-M PIC X.
03 OUT-A-NL PIC X.
FD F-OUTPUTB
LABEL RECORDS OMITTED.
01 OUT-B-REC.
03 OUT-B-PUA-CDELIM PIC 99.
03 OUT-B-PUA-SUPNO PIC 9(7).
03 OUT-B-PUA-RTYPE PIC 99.
03 OUT-B-PUA-REF PIC 9(9).
03 OUT-B-PUA-SEQ PIC 999.
03 OUT-B-PUA-ATRNDATE PIC 9(8).
03 OUT-B-PUA-PUEXTREF PIC X(10).
03 OUT-B-PUA-PUORDNO PIC 9(11).
03 OUT-B-PUA-PUVALDATE PIC 9(8).
03 OUT-B-PUA-PUSYSDATE PIC 9(8).
03 OUT-B-PUA-PUTRNVAL PIC S9(9) SIGN LEADING SEPARATE.
03 OUT-B-PUA-PUCLRREF PIC 9(6).
03 OUT-B-PUA-PUDELDATE PIC 9(8).
03 OUT-B-PUA-PUOTHQRY PIC X.
03 OUT-B-PUA-PUSUBDIV PIC 9.
03 OUT-B-CTRL-M PIC X.
03 OUT-B-NL PIC X.
计划
下面是 cobol 程序对日期所做的一小部分摘录,无论日期的来源是否为 COMP。
(我没有写这段代码)。它似乎正在尝试解决 2kY 问题。
IF PUA-ATRNDATE IS ZERO THEN
MOVE ZERO TO OUT-A-PUA-ATRNDATE
ELSE
MOVE PUA-ATRNDATE TO W-DATE-6DIGIT
MOVE W-DATE-SEG1 TO W-DATE-YY
MOVE W-DATE-SEG2 TO W-DATE-MM
MOVE W-DATE-SEG3 TO W-DATE-DD
IF W-DATE-YY > 50 THEN
MOVE "19" TO W-DATE-CC
ELSE
MOVE "20" TO W-DATE-CC
END-IF
MOVE W-DATE-CCYYMMDD TO OUT-A-PUA-ATRNDATE
END-IF.
MOVE PUA-ICEXTREF TO OUT-A-PUA-ICEXTREF.
MOVE PUA-ICORDNO TO OUT-A-PUA-ICORDNO.
IF PUA-ICVALDATE IS ZERO THEN
MOVE ZERO TO OUT-A-PUA-ICVALDATE
ELSE
MOVE PUA-ICVALDATE TO W-DATE-6DIGIT
MOVE W-DATE-SEG1 TO W-DATE-YY
MOVE W-DATE-SEG2 TO W-DATE-MM
MOVE W-DATE-SEG3 TO W-DATE-DD
IF W-DATE-YY > 50 THEN
MOVE "19" TO W-DATE-CC
ELSE
MOVE "20" TO W-DATE-CC
END-IF
MOVE W-DATE-CCYYMMDD TO OUT-A-PUA-ICVALDATE
END-IF.
程序工作存储部分
01 W-DATE-6DIGIT PIC 9(6).
01 W-DATE-6DIGIT-REDEF REDEFINES W-DATE-6DIGIT.
03 W-DATE-SEG1 PIC 99.
03 W-DATE-SEG2 PIC 99.
03 W-DATE-SEG3 PIC 99.
01 W-DATE-CCYYMMDD PIC 9(8).
01 W-DATE-CCYYMMDD-REDEF REDEFINES W-DATE-CCYYMMDD.
03 W-DATE-CC PIC 99.
03 W-DATE-YY PIC 99.
03 W-DATE-MM PIC 99.
03 W-DATE-DD PIC 99.
数据
从 Notepad++ 复制,每行从“220...”开始,在进入下一行之前结束列为 135,这意味着长度为 134(?)
2200010010300005463400022000100106062003000054634000062703 09720200000 í,! íƒ00056319D001144ÕšNNN0 1 G¨ 000000197202G
2200010010300005463500022000100106062903000054635000062858 09720200000 í, í" íƒ00082838{050906±RNNN0 1 áð 000000197202G
2200010010300005465500022000100106073003000054655000063378 09720200000 í í† í00179637A050906±RNNN0 1 000000197202G
注意到上面缺少一些符号:
2200010010300005463400022000100106062003000054634000062703 09720200000 í,[EOT]![SO] íƒ00056319D001144[SOH]ÕšNNN0 1 [SOH]G¨ 000000197202G
2200010010300005463500022000100106062903000054635000062858 09720200000 í, í" íƒ00082838{050906[SOH]±RNNN0 1 [SOH]áð 000000197202G
2200010010300005465500022000100106073003000054655000063378 09720200000 í í† í00179637A050906[SOH]±RNNN0 1 [EOT][NAK][EM] 000000197202G
更新 2
我接受了 Rick Smith 在下面的回答,因为当我将他的数据放入其中时,我得到了正确的日期时间值。因此,要么我的数据被篡改,要么因为我的数据抛出错误或未来 1000 年的日期时间值而出现其他问题。
我已经能够得到这些日期时间实际应该是什么的 CSV 输出:
[使用:int n = ((b[0] << 16) + (b[1] << 8) + b[2]);]
HEX: 0x20 0xED 0x2C
BIN: 32 237 44
INT: 2157868 (longer than 6 digit)
Actual DATE: 2006-07-16
HEX: 0x04 0x21 0x0e
BIN: 4 33 14
INT: 270606 (correct but segments are in reverse)
Actual DATE: 2006-06-27
HEX: 0x20 0xED 0x83
BIN: 32 237 131
INT: 2157955 (longer than 6 digits)
Actual DATE: 2006-08-03
更新 3
原来是错误数据...
我使用示例数据的第一条记录中包含的值创建了一个包含三个日期字段的 COBOL 文件。第一个和第三个日期是 YYMMDD,第二个是 DDMMYY。
日期在代码中给出,与您尝试读取的日期具有相同的格式,3 字节,big-endian 二进制。
environment division.
input-output section.
file-control.
select out-file assign "dates.dat"
organization sequential
.
data division.
file section.
fd out-file.
01 date-rec.
02 date-1 comp pic 9(6).
02 date-2 comp pic 9(6).
02 date-3 comp pic 9(6).
procedure division.
begin.
open output out-file
move 060716 to date-1
move 270606 to date-2
move 060803 to date-3
write date-rec
close out-file
stop run
.
此 C# 程序然后读取带有 BinaryReader
的日期并显示字节、十进制值和转换后的日期。请注意,我评论了 /*, Encoding.Default*/
,因为不需要它。
using System;
using System.Globalization;
using System.IO;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
byte[] b = { 0, 0, 0 };
string s;
DateTime d = new DateTime();
using (BinaryReader reader = new BinaryReader(File.Open(@"y:\dates.dat", FileMode.Open)/*, Encoding.Default*/))
{
for (int i = 0; i < 3; i++) // Three dates in file
{
b = reader.ReadBytes(b.Length);
Console.WriteLine("Bytes: {0}, {1}, {2}", b[0].ToString("X2"), b[1].ToString("X2"), b[2].ToString("X2"));
int n = ((b[0] << 16) + (b[1] << 8) + b[2]);
s = n.ToString("D6");
switch (i)
{
case 0:
case 2:
Console.WriteLine("Date(YYMMDD): {0}", s);
d = DateTime.ParseExact(s, "yyMMdd", CultureInfo.InvariantCulture);
Console.WriteLine("Date(yyyyMMdd): {0}", d.ToString("yyyyMMdd"));
break;
case 1:
Console.WriteLine("Date(DDMMYY): {0}", s);
d = DateTime.ParseExact(s, "ddMMyy", CultureInfo.InvariantCulture);
Console.WriteLine("Date(yyyyMMdd): {0}", d.ToString("yyyyMMdd"));
break;
default:
break;
}
Console.WriteLine("");
}
}
}
}
}
这是输出:
Bytes: 00, ED, 2C
Date(YYMMDD): 060716
Date(yyyyMMdd): 20060716
Bytes: 04, 21, 0E
Date(DDMMYY): 270606
Date(yyyyMMdd): 20060627
Bytes: 00, ED, 83
Date(YYMMDD): 060803
Date(yyyyMMdd): 20060803
DateTime.ParseExact(s, "yyMMdd", CultureInfo.InvariantCulture);
来自对这个问题的回答,String to DateTime conversion as per specified format。
我是 COBOL 新手,我一直在尝试从 table.
输出的文本文件中读取记录信息大多数我都可以接受的非 comp 数据类型,这是 'COMP' 我被卡住的。
我今天一整天都在努力解决这个问题,尽我所能阅读。
下面的日期字段是我无法转换为日期字符串的字段:
05 VALDATE PIC 9(6) COMP
05 PAYDATE PIC 9(6) COMP
05 SYSDATE PIC 9(6) COMP
据我了解,上述所有类型在文件中各占 4 个字节。
它们应该是代表 YYMMDD
的日期,但数据似乎并没有那么小。我查看了 EBCDIC 并反转了 byte[]
数据并使用 BitConverter.ToUNIT32()
并更改了用于读取文件的编码,但没有成功。
我读到计算为整数的日期存储为从 1601 年 1 月 1 日开始的天数,因此下面的代码试图将值添加到 1601。(http://www.techtricky.com/cobol-date-functions-list-add-find-duration/)
我的问题是文本文件中的数据不正确,或者我缺少获取类似于 YYMMDD
.
以上3项数据如下:
[ 32] [237] [ 44] [ 4] | 00100000 11101101 00101100 00000100
[ 33] [ 14] [ 32] [237] | 00100001 00001110 00100000 11101101
[131] [ 48] [ 48] [ 48] | 10000011 00110000 00110000 00110000
以及我打开文件的方式,我已经将编码更改为 ascii 但没有运气:
using (BinaryReader reader = new BinaryReader(File.Open(nFilePath, FileMode.Open), Encoding.Default))
用于尝试读取 COMP 字段的代码:
public class DateFromUIntExtractor : LineExtractor
{
public DateFromUIntExtractor() : base(4)
{
}
public override string ExtractText(BinaryReader nReader)
{
// e.g 32,237,44,44, included but commented out things i've tried
byte[] data = nReader.ReadBytes(Length); // Length = 4
//Array.Reverse(data); - Makes num = 552414212
//data = ConvertAsciiToEbcdic(data);
int num = BitConverter.ToUInt32(data, 0);
// in this example num = 70053152
DateTime date = new DateTime(1601,1,1);
date = date.AddDays(num); // Error : num is too big
Extract = date.ToString("yyyyMMdd");
return Extract;
}
}
数据格式有误吗?或者我错过了什么?
更新
我要完成的任务是复制一个 COBOL 程序,该程序将数据从一个定义转换为另一个定义但采用 CSV 格式,因为该程序输出一个 .dat 文件。
来源
我对源定义的缺乏经验的解释是,文本文件中的数据要么是PUA-ICGROUP
,要么是PUA-PUGROUP
。查看 COBOL 程序它在 PUA-HEADER>PUA-KEY>PUA-RTYPE = "03"
时选择 PUA-ICGROUP
,其他一切都是 PUA-PUGROUP
.
C-WRITE-START.
IF PUA-RTYPE = 3 THEN
PERFORM C-WRITE-A
ELSE
PERFORM C-WRITE-B
END-IF.
C-WRITE-EXIT.
EXIT.
定义
01 DLRPUARC.
03 PUA-HEADER.
05 PUA-KEY.
07 PUA-CDELIM PIC 99.
07 PUA-SUPNO PIC 9(7).
07 PUA-RTYPE PIC 99.
07 PUA-REF PIC 9(9).
07 PUA-SEQ PIC 999.
05 PUA-ALTKEY.
07 PUA-ACDELIM PIC 99.
07 PUA-ASUPNO PIC 9(7).
07 PUA-ATRNDATE PIC 9(6).
07 PUA-ARTYPE PIC 99.
07 PUA-AREF PIC 9(9).
07 PUA-ASEQ PIC 999.
05 FILLER PIC X(82).
03 PUA-ICGROUP REDEFINES PUA-HEADER.
05 FILLER PIC X(52).
05 PUA-ICEXTREF PIC X(10).
05 PUA-ICORDNO PIC 9(11).
05 PUA-ICVALDATE PIC 9(6) COMP.
05 PUA-ICPAYDATE PIC 9(6) COMP.
05 PUA-ICSYSDATE PIC 9(6) COMP.
05 PUA-ICTRNVAL PIC S9(9).
05 PUA-ICCLRREF PIC 9(6).
05 PUA-ICDELDATE PIC 9(6) COMP.
05 PUA-ICOTHQRY PIC X.
05 PUA-ICPRCQRY PIC X.
05 PUA-ICMRSQRY PIC X.
05 PUA-ICDSCTYPE PIC 9.
05 PUA-ICDSCVAL PIC S9(9) COMP.
05 PUA-ICVATCODE PIC 9.
05 PUA-ICVATAMT PIC S9(8) COMP.
05 PUA-ICTAXAMT PIC S9(8) COMP.
05 PUA-ICMRSREF PIC 9(6).
05 PUA-ICSUBDIV PIC 9.
05 PUA-ICCOSTCTR PIC X(5).
05 PUA-ICSEQIND PIC X.
05 FILLER PIC X(4).
03 PUA-PUGROUP REDEFINES PUA-HEADER.
05 FILLER PIC X(52).
05 PUA-PUEXTREF PIC X(10).
05 PUA-PUORDNO PIC 9(11).
05 PUA-PUVALDATE PIC 9(6) COMP.
05 FILLER PIC XXX.
05 PUA-PUSYSDATE PIC 9(6) COMP.
05 PUA-PUTRNVAL PIC S9(9).
05 PUA-PUCLRREF PIC 9(6).
05 PUA-PUDELDATE PIC 9(6) COMP.
05 PUA-PUOTHQRY PIC X.
05 PUA-PUSUBDIV PIC 9.
05 FILLER PIC X(32).
输出定义
01 OUT-A-REC.
03 OUT-A-PUA-CDELIM PIC 99.
03 OUT-A-PUA-SUPNO PIC 9(7).
03 OUT-A-PUA-RTYPE PIC 99.
03 OUT-A-PUA-REF PIC 9(9).
03 OUT-A-PUA-SEQ PIC 999.
03 OUT-A-PUA-ATRNDATE PIC 9(8).
03 OUT-A-PUA-ICEXTREF PIC X(10).
03 OUT-A-PUA-ICORDNO PIC 9(11).
03 OUT-A-PUA-ICVALDATE PIC 9(8).
03 OUT-A-PUA-ICPAYDATE PIC 9(8).
03 OUT-A-PUA-ICSYSDATE PIC 9(8).
03 OUT-A-PUA-ICTRNVAL PIC S9(9) SIGN LEADING SEPARATE.
03 OUT-A-PUA-ICCLRREF PIC 9(6).
03 OUT-A-PUA-ICDELDATE PIC 9(8).
03 OUT-A-PUA-ICOTHQRY PIC X.
03 OUT-A-PUA-ICPRCQRY PIC X.
03 OUT-A-PUA-ICMRSQRY PIC X.
03 OUT-A-PUA-ICDSCTYPE PIC 9.
03 OUT-A-PUA-ICDSCVAL PIC S9(9) SIGN LEADING SEPARATE.
03 OUT-A-PUA-ICVATCODE PIC 9.
03 OUT-A-PUA-ICVATAMT PIC S9(8) SIGN LEADING SEPARATE.
03 OUT-A-PUA-ICTAXAMT PIC S9(8) SIGN LEADING SEPARATE.
03 OUT-A-PUA-ICMRSREF PIC 9(6).
03 OUT-A-PUA-ICSUBDIV PIC 9.
03 OUT-A-PUA-ICCOSTCTR PIC X(5).
03 OUT-A-PUA-ICSEQIND PIC X.
03 OUT-A-CTRL-M PIC X.
03 OUT-A-NL PIC X.
FD F-OUTPUTB
LABEL RECORDS OMITTED.
01 OUT-B-REC.
03 OUT-B-PUA-CDELIM PIC 99.
03 OUT-B-PUA-SUPNO PIC 9(7).
03 OUT-B-PUA-RTYPE PIC 99.
03 OUT-B-PUA-REF PIC 9(9).
03 OUT-B-PUA-SEQ PIC 999.
03 OUT-B-PUA-ATRNDATE PIC 9(8).
03 OUT-B-PUA-PUEXTREF PIC X(10).
03 OUT-B-PUA-PUORDNO PIC 9(11).
03 OUT-B-PUA-PUVALDATE PIC 9(8).
03 OUT-B-PUA-PUSYSDATE PIC 9(8).
03 OUT-B-PUA-PUTRNVAL PIC S9(9) SIGN LEADING SEPARATE.
03 OUT-B-PUA-PUCLRREF PIC 9(6).
03 OUT-B-PUA-PUDELDATE PIC 9(8).
03 OUT-B-PUA-PUOTHQRY PIC X.
03 OUT-B-PUA-PUSUBDIV PIC 9.
03 OUT-B-CTRL-M PIC X.
03 OUT-B-NL PIC X.
计划
下面是 cobol 程序对日期所做的一小部分摘录,无论日期的来源是否为 COMP。 (我没有写这段代码)。它似乎正在尝试解决 2kY 问题。
IF PUA-ATRNDATE IS ZERO THEN
MOVE ZERO TO OUT-A-PUA-ATRNDATE
ELSE
MOVE PUA-ATRNDATE TO W-DATE-6DIGIT
MOVE W-DATE-SEG1 TO W-DATE-YY
MOVE W-DATE-SEG2 TO W-DATE-MM
MOVE W-DATE-SEG3 TO W-DATE-DD
IF W-DATE-YY > 50 THEN
MOVE "19" TO W-DATE-CC
ELSE
MOVE "20" TO W-DATE-CC
END-IF
MOVE W-DATE-CCYYMMDD TO OUT-A-PUA-ATRNDATE
END-IF.
MOVE PUA-ICEXTREF TO OUT-A-PUA-ICEXTREF.
MOVE PUA-ICORDNO TO OUT-A-PUA-ICORDNO.
IF PUA-ICVALDATE IS ZERO THEN
MOVE ZERO TO OUT-A-PUA-ICVALDATE
ELSE
MOVE PUA-ICVALDATE TO W-DATE-6DIGIT
MOVE W-DATE-SEG1 TO W-DATE-YY
MOVE W-DATE-SEG2 TO W-DATE-MM
MOVE W-DATE-SEG3 TO W-DATE-DD
IF W-DATE-YY > 50 THEN
MOVE "19" TO W-DATE-CC
ELSE
MOVE "20" TO W-DATE-CC
END-IF
MOVE W-DATE-CCYYMMDD TO OUT-A-PUA-ICVALDATE
END-IF.
程序工作存储部分
01 W-DATE-6DIGIT PIC 9(6).
01 W-DATE-6DIGIT-REDEF REDEFINES W-DATE-6DIGIT.
03 W-DATE-SEG1 PIC 99.
03 W-DATE-SEG2 PIC 99.
03 W-DATE-SEG3 PIC 99.
01 W-DATE-CCYYMMDD PIC 9(8).
01 W-DATE-CCYYMMDD-REDEF REDEFINES W-DATE-CCYYMMDD.
03 W-DATE-CC PIC 99.
03 W-DATE-YY PIC 99.
03 W-DATE-MM PIC 99.
03 W-DATE-DD PIC 99.
数据
从 Notepad++ 复制,每行从“220...”开始,在进入下一行之前结束列为 135,这意味着长度为 134(?)
2200010010300005463400022000100106062003000054634000062703 09720200000 í,! íƒ00056319D001144ÕšNNN0 1 G¨ 000000197202G
2200010010300005463500022000100106062903000054635000062858 09720200000 í, í" íƒ00082838{050906±RNNN0 1 áð 000000197202G
2200010010300005465500022000100106073003000054655000063378 09720200000 í í† í00179637A050906±RNNN0 1 000000197202G
注意到上面缺少一些符号:
2200010010300005463400022000100106062003000054634000062703 09720200000 í,[EOT]![SO] íƒ00056319D001144[SOH]ÕšNNN0 1 [SOH]G¨ 000000197202G
2200010010300005463500022000100106062903000054635000062858 09720200000 í, í" íƒ00082838{050906[SOH]±RNNN0 1 [SOH]áð 000000197202G
2200010010300005465500022000100106073003000054655000063378 09720200000 í í† í00179637A050906[SOH]±RNNN0 1 [EOT][NAK][EM] 000000197202G
更新 2
我接受了 Rick Smith 在下面的回答,因为当我将他的数据放入其中时,我得到了正确的日期时间值。因此,要么我的数据被篡改,要么因为我的数据抛出错误或未来 1000 年的日期时间值而出现其他问题。
我已经能够得到这些日期时间实际应该是什么的 CSV 输出:
[使用:int n = ((b[0] << 16) + (b[1] << 8) + b[2]);]
HEX: 0x20 0xED 0x2C
BIN: 32 237 44
INT: 2157868 (longer than 6 digit)
Actual DATE: 2006-07-16
HEX: 0x04 0x21 0x0e
BIN: 4 33 14
INT: 270606 (correct but segments are in reverse)
Actual DATE: 2006-06-27
HEX: 0x20 0xED 0x83
BIN: 32 237 131
INT: 2157955 (longer than 6 digits)
Actual DATE: 2006-08-03
更新 3
原来是错误数据...
我使用示例数据的第一条记录中包含的值创建了一个包含三个日期字段的 COBOL 文件。第一个和第三个日期是 YYMMDD,第二个是 DDMMYY。
日期在代码中给出,与您尝试读取的日期具有相同的格式,3 字节,big-endian 二进制。
environment division.
input-output section.
file-control.
select out-file assign "dates.dat"
organization sequential
.
data division.
file section.
fd out-file.
01 date-rec.
02 date-1 comp pic 9(6).
02 date-2 comp pic 9(6).
02 date-3 comp pic 9(6).
procedure division.
begin.
open output out-file
move 060716 to date-1
move 270606 to date-2
move 060803 to date-3
write date-rec
close out-file
stop run
.
此 C# 程序然后读取带有 BinaryReader
的日期并显示字节、十进制值和转换后的日期。请注意,我评论了 /*, Encoding.Default*/
,因为不需要它。
using System;
using System.Globalization;
using System.IO;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
byte[] b = { 0, 0, 0 };
string s;
DateTime d = new DateTime();
using (BinaryReader reader = new BinaryReader(File.Open(@"y:\dates.dat", FileMode.Open)/*, Encoding.Default*/))
{
for (int i = 0; i < 3; i++) // Three dates in file
{
b = reader.ReadBytes(b.Length);
Console.WriteLine("Bytes: {0}, {1}, {2}", b[0].ToString("X2"), b[1].ToString("X2"), b[2].ToString("X2"));
int n = ((b[0] << 16) + (b[1] << 8) + b[2]);
s = n.ToString("D6");
switch (i)
{
case 0:
case 2:
Console.WriteLine("Date(YYMMDD): {0}", s);
d = DateTime.ParseExact(s, "yyMMdd", CultureInfo.InvariantCulture);
Console.WriteLine("Date(yyyyMMdd): {0}", d.ToString("yyyyMMdd"));
break;
case 1:
Console.WriteLine("Date(DDMMYY): {0}", s);
d = DateTime.ParseExact(s, "ddMMyy", CultureInfo.InvariantCulture);
Console.WriteLine("Date(yyyyMMdd): {0}", d.ToString("yyyyMMdd"));
break;
default:
break;
}
Console.WriteLine("");
}
}
}
}
}
这是输出:
Bytes: 00, ED, 2C
Date(YYMMDD): 060716
Date(yyyyMMdd): 20060716
Bytes: 04, 21, 0E
Date(DDMMYY): 270606
Date(yyyyMMdd): 20060627
Bytes: 00, ED, 83
Date(YYMMDD): 060803
Date(yyyyMMdd): 20060803
DateTime.ParseExact(s, "yyMMdd", CultureInfo.InvariantCulture);
来自对这个问题的回答,String to DateTime conversion as per specified format。