我试图将文件从ECDIC格式转换为ASCII格式,但遇到了一个有趣的问题。这些文件包含一些字段为带符号二进制整数(在记录布局中描述为B4)和长精度数字值(在记录布局中描述为L8)的固定长度记录。我已经成功地转换了字符数据,但不确定如何转换这些数字值。从原系统(IBM 5110)的参考手册中可以找到以下字段描述。
B表示数字数据项的长度(2、4或8个字节),这些数据项采用定点有符号二进制整数格式,需要转换为BASIC内部数据格式。对于记录I/O文件输入,记录中的下一个2、4或8个字节包含要由系统转换为内部数据格式并分配给使用FORM语句指定的变量的有符号二进制值,这些变量在READ FILE或REREAD FILE语句中指定。
和
L表示数字值的长精度(8个字符)。对于输入,此条目表示记录中的八位长精度值将分配给在READ FILE或REREAD FILE语句中指定的相应数字变量,而无需进行转换。
编辑:这是我用于转换的代码
private void ConvertFile(EbcdicFile file)
{
if (file == null) return;
var filePath = Path.Combine(file.Path, file.FileName);
if (!File.Exists(filePath))
{
this.Logger.Info(string.Format("Cannot convert file {0}. It does not exist.", filePath));
return;
}
var ebcdic = Encoding.GetEncoding(37);
string convertedFilepath = Path.Combine(file.Path, file.ConvertedFileName);
byte[] fileData = File.ReadAllBytes(filePath);
if (!file.HasNumericFields)
File.WriteAllBytes(convertedFilepath, Encoding.Convert(ebcdic, Encoding.ASCII, fileData));
else
{
var convertedFileData = new List<byte>();
for (int position = 0; position < fileData.Length; position += file.RecordLength)
{
var segment = new ArraySegment<byte>(fileData, position, file.RecordLength);
file.Fields.ForEach(field =>
{
var fieldSegment = segment.Array.Skip(segment.Offset + field.Start - 1).Take(field.Length);
if (field.Type.Equals("string", StringComparison.OrdinalIgnoreCase))
{
convertedFileData.AddRange(
Encoding.Convert(ebcdic, Encoding.ASCII, fieldSegment.ToArray())
);
}
else if (field.Type.Equals("B4", StringComparison.OrdinalIgnoreCase))
{
// Not sure how to convert this field
}
else if (field.Type.Equals("L8", StringComparison.OrdinalIgnoreCase))
{
// Not sure how to convert this field
}
});
}
File.WriteAllBytes(convertedFilepath, convertedFileData.ToArray());
}
}