Я пытаюсь преобразовать файлы из формата ECDIC в формат ASCII и столкнулся с интересной проблемой. Файлы содержат записи фиксированной длины, некоторые поля которых представляют собой целые двоичные числа со знаком (обозначаются как B4 в макете записи) и числовые значения высокой точности (обозначаются как L8 в записи). макет). Мне удалось преобразовать символьные данные без проблем, но я не знаю, как преобразовать эти числовые значения. Из справочного руководства для исходной системы (IBM 5110), поля описаны ниже.
B указывает длину (2, 4 или 8 байтов) числовых элементов данных в двоичном целочисленном формате с фиксированной точкой со знаком, которые должны быть преобразованы во внутренний формат данных BASIC. Для записи файла ввода-вывода следующие 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());
}
}