49.7. 4.FixedLengthRecord
FixedLengthRecord 注解用于识别模型的根类。它代表了一个记录,即 "一个文件/message 行,其中包含数据固定长度格式",并可链接到多个子模型类。这个格式非常重要,因为字段的数据可以与右侧或左侧保持一致。
当数据的大小没有完全填写字段的长度时,我们可以添加"平板"字符。
| 注解名称 | 记录类型 | 级别 |
|---|---|---|
| FixedLengthRecord | 已修复 | 类 |
| 参数名称 | type | 必填 | 默认值 | info |
|---|---|---|---|---|
| countGrapheme | 布尔值 | false | 表示如何计算收费。 | |
| CRLF | string | WINDOWS | 用于在每个记录后添加回车的字符(可选)。可能的值有:WINDOWS、UNIX、MAC 或自定义。这个选项仅在 marshalling 期间使用,unmarshalling 使用系统默认 JDK 提供的行分隔符,除非自定义了 eol。 | |
| EOL | string | 在 unmarshalling 时,要在每个记录后处理行尾的字符(可选 - default = ""),这有助于使用默认 JDK 提供的行分隔符,除非提供任何其他行分隔符)。这个选项只在 unmarshalling 期间使用,其中 marshalling 使用系统默认提供的行分隔符为"WINDOWS",除非提供了任何其他值。 | ||
| footer | 类 | void | 表示此类型的记录可能后跟一个文件末尾的一个页脚记录。 | |
| header | 表示此类型的记录前面可能在文件的开头有一个标题记录。 | |||
| ignoreMissingChars | 指明是否忽略了太短行 | |||
| ignoreTrailingChars | 表示当 unmarshalling / 解析时,可以忽略除最后一个映射的文件以外的字符。此注解与模型的根类关联,必须被声明一次。 | |||
| length | int | 0 | 记录的固定长度(字符数)。这意味着记录始终是默认使用 {""paddingChar ()} 的 padded。 | |
| name | 字符串 | 描述记录的名称(可选)。 | ||
| paddingChar | char | 使用 pad 进行字符. | ||
| skipFooter | 布尔值 | false | 配置数据格式,以跳过页脚记录的 marshalling / unmarshalling,在主记录上配置此参数(例如,而不是标头或页脚)。 | |
| skipHeader | 布尔值 | false | 配置数据格式,以跳过标题记录的 / unmarshalling。在主记录上配置此参数(例如,而不是标头或页脚)。 |
记录可能不是标头/页脚和主固定长度记录。
问题单 1:简单固定长度记录
这个简单示例演示了如何设计模型来解析/格式化固定消息。
10A9PaulineMISINXD12345678BUYShare2500.45USD01-08-2009
fixed-simple
@FixedLengthRecord(length=54, paddingChar=' ')
public static class Order {
@DataField(pos = 1, length=2)
private int orderNr;
@DataField(pos = 3, length=2)
private String clientNr;
@DataField(pos = 5, length=7)
private String firstName;
@DataField(pos = 12, length=1, align="L")
private String lastName;
@DataField(pos = 13, length=4)
private String instrumentCode;
@DataField(pos = 17, length=10)
private String instrumentNumber;
@DataField(pos = 27, length=3)
private String orderType;
@DataField(pos = 30, length=5)
private String instrumentType;
@DataField(pos = 35, precision = 2, length=7)
private BigDecimal amount;
@DataField(pos = 42, length=3)
private String currency;
@DataField(pos = 45, length=10, pattern = "dd-MM-yyyy")
private Date orderDate;
}
问题单 2:使用对齐和填充修复长度记录
这更详细的示例演示了如何为字段定义对齐以及如何分配 padding 字符(本例中为 ':
10A9 PaulineM ISINXD12345678BUYShare2500.45USD01-08-2009
fixed-padding-align
@FixedLengthRecord(length=60, paddingChar=' ')
public static class Order {
@DataField(pos = 1, length=2)
private int orderNr;
@DataField(pos = 3, length=2)
private String clientNr;
@DataField(pos = 5, length=9)
private String firstName;
@DataField(pos = 14, length=5, align="L") // align text to the LEFT zone of the block
private String lastName;
@DataField(pos = 19, length=4)
private String instrumentCode;
@DataField(pos = 23, length=10)
private String instrumentNumber;
@DataField(pos = 33, length=3)
private String orderType;
@DataField(pos = 36, length=5)
private String instrumentType;
@DataField(pos = 41, precision = 2, length=7)
private BigDecimal amount;
@DataField(pos = 48, length=3)
private String currency;
@DataField(pos = 51, length=10, pattern = "dd-MM-yyyy")
private Date orderDate;
}
case 3:字段填充
有时,为记录定义的默认 padding 不能应用于字段,因为我们有一个数字格式,我们将希望使用 '0' 而不是 ''。在这种情况下,在模型中,您可以使用 @DataField 上的属性 paddingChar 来设置这个值。
10A9 PaulineM ISINXD12345678BUYShare000002500.45USD01-08-2009
fixed-padding-field
@FixedLengthRecord(length = 65, paddingChar = ' ')
public static class Order {
@DataField(pos = 1, length = 2)
private int orderNr;
@DataField(pos = 3, length = 2)
private String clientNr;
@DataField(pos = 5, length = 9)
private String firstName;
@DataField(pos = 14, length = 5, align = "L")
private String lastName;
@DataField(pos = 19, length = 4)
private String instrumentCode;
@DataField(pos = 23, length = 10)
private String instrumentNumber;
@DataField(pos = 33, length = 3)
private String orderType;
@DataField(pos = 36, length = 5)
private String instrumentType;
@DataField(pos = 41, precision = 2, length = 12, paddingChar = '0')
private BigDecimal amount;
@DataField(pos = 53, length = 3)
private String currency;
@DataField(pos = 56, length = 10, pattern = "dd-MM-yyyy")
private Date orderDate;
}
问题单 4:使用分隔符修复长度记录
固定长度记录有时会在记录中有分隔的内容。在以下示例中,firstName 和 lastName 字段用以下示例中的 ^ 字符分隔:
10A9Pauline^M^ISINXD12345678BUYShare000002500.45USD01-08-2009
fixed-delimited
@FixedLengthRecord
public static class Order {
@DataField(pos = 1, length = 2)
private int orderNr;
@DataField(pos = 2, length = 2)
private String clientNr;
@DataField(pos = 3, delimiter = "^")
private String firstName;
@DataField(pos = 4, delimiter = "^")
private String lastName;
@DataField(pos = 5, length = 4)
private String instrumentCode;
@DataField(pos = 6, length = 10)
private String instrumentNumber;
@DataField(pos = 7, length = 3)
private String orderType;
@DataField(pos = 8, length = 5)
private String instrumentType;
@DataField(pos = 9, precision = 2, length = 12, paddingChar = '0')
private BigDecimal amount;
@DataField(pos = 10, length = 3)
private String currency;
@DataField(pos = 11, length = 10, pattern = "dd-MM-yyyy")
private Date orderDate;
}
可以使用 ordinal 或 sequential 值而不是精确列号来定义固定长度记录中的 pos 值。
问题单 5 :使用记录定义字段长度修复长度记录
有时,固定长度记录可能包含一个字段,用于定义同一记录中另一个字段的预期长度。在以下示例中,inst Number 字段值 的长度由记录中的 instrumentNumberLen 字段的值定义。
10A9Pauline^M^ISIN10XD12345678BUYShare000002500.45USD01-08-2009
fixed-delimited
@FixedLengthRecord
public static class Order {
@DataField(pos = 1, length = 2)
private int orderNr;
@DataField(pos = 2, length = 2)
private String clientNr;
@DataField(pos = 3, delimiter = "^")
private String firstName;
@DataField(pos = 4, delimiter = "^")
private String lastName;
@DataField(pos = 5, length = 4)
private String instrumentCode;
@DataField(pos = 6, length = 2, align = "R", paddingChar = '0')
private int instrumentNumberLen;
@DataField(pos = 7, lengthPos=6)
private String instrumentNumber;
@DataField(pos = 8, length = 3)
private String orderType;
@DataField(pos = 9, length = 5)
private String instrumentType;
@DataField(pos = 10, precision = 2, length = 12, paddingChar = '0')
private BigDecimal amount;
@DataField(pos = 11, length = 3)
private String currency;
@DataField(pos = 12, length = 10, pattern = "dd-MM-yyyy")
private Date orderDate;
}
case 6 :使用标头和页脚修复长度记录
bindy 将发现配置为模型的一部分的固定长度标头和页脚记录,这些模型与主 @FixedLengthRecord 类位于同一个软件包中,或者在其中一个配置的扫描软件包中存在。以下文本演示了两个已由头记录和页脚记录的固定长度记录。
101-08-2009
10A9 PaulineM ISINXD12345678BUYShare000002500.45USD01-08-2009
10A9 RichN ISINXD12345678BUYShare000002700.45USD01-08-2009
9000000002
fixed-header-and-footer-main-class
@FixedLengthRecord(header = OrderHeader.class, footer = OrderFooter.class)
public class Order {
@DataField(pos = 1, length = 2)
private int orderNr;
@DataField(pos = 2, length = 2)
private String clientNr;
@DataField(pos = 3, length = 9)
private String firstName;
@DataField(pos = 4, length = 5, align = "L")
private String lastName;
@DataField(pos = 5, length = 4)
private String instrumentCode;
@DataField(pos = 6, length = 10)
private String instrumentNumber;
@DataField(pos = 7, length = 3)
private String orderType;
@DataField(pos = 8, length = 5)
private String instrumentType;
@DataField(pos = 9, precision = 2, length = 12, paddingChar = '0')
private BigDecimal amount;
@DataField(pos = 10, length = 3)
private String currency;
@DataField(pos = 11, length = 10, pattern = "dd-MM-yyyy")
private Date orderDate;
}
@FixedLengthRecord
public class OrderHeader {
@DataField(pos = 1, length = 1)
private int recordType = 1;
@DataField(pos = 2, length = 10, pattern = "dd-MM-yyyy")
private Date recordDate;
}
@FixedLengthRecord
public class OrderFooter {
@DataField(pos = 1, length = 1)
private int recordType = 9;
@DataField(pos = 2, length = 9, align = "R", paddingChar = '0')
private int numberOfRecordsInTheFile;
}
case 7 : 在解析固定长度记录时跳过内容。
通常,与提供固定长度记录的系统集成,这些记录包含比目标用例所需的信息多。在这种情况下,跳过我们不需要的那些字段的声明和解析非常有用。为了说明这一点,Bindy 将跳过转发到记录中下一个映射字段(如果下一个声明的字段的 pos 值超出了最后一个解析字段的光标位置)的下一个映射字段。对感兴趣的字段使用绝对 pos 位置(而不是 ordinal 值)会导致 Bindy 在两个字段之间跳过内容。
同样,某些字段以外的任何内容都不可能值得关注。在这种情况下,您可以通过设置 @FixedLengthRecord 声明上的 ignoreTrailingChars 属性,告知 Bindy 跳过上次映射字段之外的所有内容的解析。
@FixedLengthRecord(ignoreTrailingChars = true)
public static class Order {
@DataField(pos = 1, length = 2)
private int orderNr;
@DataField(pos = 3, length = 2)
private String clientNr;
// any characters that appear beyond the last mapped field will be ignored
}