提问人:Candy 提问时间:12/28/2019 最后编辑:zx485Candy 更新时间:11/7/2023 访问量:3979
C 语言中的 Swift MT940 解析器#
Swift MT940 parser in C#
问:
如何使用 C# 解析 MT940 swift 消息?
以下是我必须解析的消息:
:20:MT940-1411201901
:25:1234567837710016
:28C:008/201
:60F:C171224SAR145597,13
:61:2107221722D17000,NCHK219120//14218-102431Abnamb
:61:2107221722D17000,NCHK219120//14218-102431Abnamb VSP
:62F:C291124SAR145597,13
我怎样才能意识到这一点?
答:
-1赞
jdweng
12/28/2019
#1
尝试如下代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Text.RegularExpressions;
using System.Globalization;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = @"c:\temp\test.txt";
static void Main(string[] args)
{
MT940 mt940 = new MT940(FILENAME);
}
}
public class MT940
{
const string TAG_PATTERN = @"^:(?'tag'[^:]+):(?'value'.*)";
public string senderReference { get; set; } //code 20
public string authorisation { get; set; } // tag 25
public string messageIndexTotal { get; set; } //tag 28D
public Currency openingBalance { get; set; } //60F
public string firstTransaction { get; set; } //61
public string secondTransaction { get; set; } //61
public Currency closingBalance { get; set; } //62F
public MT940(string filename)
{
StreamReader reader = new StreamReader(filename);
string line = "";
int transactionCount = 0;
while ((line = reader.ReadLine()) != null)
{
if (line.StartsWith(":"))
{
Match match = Regex.Match(line, TAG_PATTERN);
string tag = match.Groups["tag"].Value;
string value = match.Groups["value"].Value;
switch (tag)
{
case "20":
senderReference = value;
break;
case "25":
authorisation = value;
break;
case "28C":
messageIndexTotal = value;
break;
case "60F":
openingBalance = new Currency(value);
break;
case "61":
if (++transactionCount == 1)
{
firstTransaction = value;
}
else
{
secondTransaction = value;
}
break;
case "62F":
closingBalance = new Currency(value);
break;
default:
break;
}
}
}
}
}
public class Currency
{
const string BALANCE_PATTERN = @"^(?'credit_debit'.)(?'date'.{6})(?'country_code'.{3})(?'amount'.*)";
static CultureInfo culture = CultureInfo.GetCultureInfoByIetfLanguageTag("da");
public DateTime date { get; set; }
public string currencyCode { get; set; }
public decimal amount { get; set; }
public Currency(string input)
{
Match match = Regex.Match(input, BALANCE_PATTERN);
string credit_debit = match.Groups["credit_debit"].Value;
string dateStr = match.Groups["date"].Value;
date = DateTime.ParseExact(dateStr, "yyMMdd", CultureInfo.InvariantCulture);
currencyCode = match.Groups["country_code"].Value;
string amountStr = match.Groups["amount"].Value;
amount = decimal.Parse(amountStr, culture);
amount *= credit_debit == "D" ? -1 : 1;
}
}
}
评论
1赞
oleksa
12/28/2019
要正确编写解析器,您必须了解业务规则。940 消息可以包含许多 61 个字段(两个以上)。此外,61 字段后面可以跟着 86 字段。86 是多行字段,因此逐行读取文件有点棘手。示例代码分析了在实际 MT940 上提供但失败的特定示例。解析 Swift MT 格式需要良好的知识,并且比 SA 应该提供的要多得多。
0赞
oleksa
12/28/2019
line.Split(new char[] {':'}
如果字段值包含 ':' char,则将丢失该字段值,例如:86:the reason: to return funds
0赞
jdweng
12/28/2019
@oleksa:您提供的链接未指定字段可以包含冒号。你能提供参考吗?
0赞
oleksa
12/28/2019
好吧,86 字段没有任何限制,可以包含“:”。61 实际上是多行字段,可以在新行上。Swift 消息解析意味着字段 61(例如)必须解析为“值日期”、“条目日期”、“Amoun”、“代码”、“编号”、“参考”必填字段。隐藏的 gem 太多,无法使用 SO 解析 Swift MT。这个问题最终可以作为使用 SO 的学生教育的一部分来解决,但不适用于生产代码Supplementary Details
0赞
jdweng
12/28/2019
除非必要,否则我不喜欢去正则表达式。我更喜欢效率更高的字符串方法。我将更改代码。
1赞
Bellash
11/7/2023
#2
你应该使用这个库,这个库,而不是重新发明轮子!
我试图创建一个可以工作的解析器,直到我遇到一些符合 MT940 的银行自定义,但我的代码无法管理它。
评论
0赞
starball
11/7/2023
请展开。meta.stackexchange.com/a/8259/997587
评论
^:\d\d\w?:.*