【发布时间】:2013-01-09 07:02:37
【问题描述】:
我正在尝试将文件从 ECDIC 转换为 ASCII 格式,但遇到了一个有趣的问题。这些文件包含固定长度的记录,其中一些字段是有符号二进制整数(在记录布局中描述为 B4)和 长精度数字值(在记录中描述为 L8布局)。我已经能够毫无问题地转换字符数据,但我不确定如何转换这些数值。来自原始系统的参考手册(IBM 5110),字段如下所述。
B 表示数字数据项的长度(2、4 或 8 字节) 要转换为的定点有符号二进制整数格式 BASIC 内部数据格式。对于记录 I/O 文件输入,接下来的 2, 记录中的 4 或 8 个字节包含有符号二进制值 由系统转换为内部数据格式并分配给 在 READ FILE 或 REREAD FILE 语句中指定的变量使用 一个 FORM 语句。
和
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());
}
}
【问题讨论】:
-
您已经描述了您目前的情况,但没有提出任何问题:-)。我想您想说“如何从 IBM 5110 BASIC 编写的数据文件中转换 B4 和 L8 字段类型”......您需要向我们展示一些示例数据(十六进制转储),最好还有正确的解释。