Visual FoxPro (VFP) Функции CTOBIN и BINTOC — эквивалентны в .Net

Мы переписываем некоторые приложения, ранее разработанные в Visual FoxPro, и переделываем их с использованием .Net (используя C#).

Вот наш сценарий: Наше приложение использует смарт-карты. Мы считываем данные со смарт-карты, у которой есть имя и номер. Имя возвращается в читаемом тексте, но число, в данном случае «900», возвращается в виде 2-байтового представления символов (131 и 132) и выглядит так: ƒ„

Эти 2 специальных символа можно увидеть в расширенной таблице Ascii. Теперь, как вы можете видеть, 2 байта равны 131 и 132 и могут различаться, поскольку не существует единой стандартной расширенной таблицы ascii (насколько я могу судить, читая некоторые сообщения Здесь )

Итак... смарт-карта была ранее записана с использованием функции BINTOC в VFP, и поэтому 900 было записано на карту как ƒ„. И в FoxPro эти 2 специальных символа могут быть преобразованы обратно в целочисленный формат с помощью функции CTOBIN.. еще одна встроенная функция в FoxPro..

Итак (наконец-то добравшись до сути). До сих пор нам не удалось преобразовать эти 2 специальных символа обратно в int (900), и нам интересно, возможно ли это в .NET для чтения символьного представления целого числа обратно в фактическое целое число.

Или есть способ переписать логику этих двух функций VFP на С#?

ОБНОВЛЕНИЕ: После некоторой возни мы поняли, что для преобразования 900 в 2 байта нам нужно преобразовать 900 в 16-битное двоичное значение, а затем нам нужно преобразовать это 16-битное двоичное значение в десятичное значение.

Итак, как и выше, мы получаем обратно 131 и 132 и их соответствующие двоичные значения как 10000011 (десятичное значение 131) и 10000100 (десятичное значение 132). Когда мы объединяем эти 2 значения в «1000001110000100», это дает десятичное значение 33668, однако, если мы удаляем ведущую 1 и преобразуем «000001110000100» в десятичное, это дает правильное значение 900...

Хотя не совсем понятно, почему это...

Любая помощь будет оценена по достоинству.


person Kev    schedule 16.02.2012    source источник
comment
Проблема решена. Мы преобразовали число 900 в двоичное, взяли значения от 9 до 16 (invlusive) в качестве второго байта, взяли оставшиеся значения и обновили их с ведущей 1, поскольку число равно › 127. Это работает в обоих направлениях, преобразуя любое число › 127 (и менее 32,7?? независимо от максимального значения)   -  person Kev    schedule 16.02.2012
comment
Пример: 900 в двоичном формате = 1110000100. Возьмите последние 8 цифр (10000100) и преобразуйте в десятичное число = 132. Возьмите первые 2 цифры (11) и примените 5 последующих нулей и начните двоичное значение с 1, чтобы оно выглядело так - 10000011. Преобразуйте это в десятичное число, и это будет 131. Теперь, чтобы вернуть десятичные значения 131, 132 обратно в одно двоичное значение, чтобы преобразовать обратно в десятичное число, мы преобразуем их по отдельности и объединим их, чтобы получить 1000001110000100. Теперь просто замените 1 в позиции 1 с 0, чтобы получить исходное 16-битное двоичное значение, нам нужна только 1 в начале, если мы работаем с 2 x битовыми фрагментами   -  person Kev    schedule 16.02.2012
comment
Если вы считаете, что ответили на свой вопрос адекватно, не стесняйтесь опубликовать его как ответ на свой вопрос. Это позволит вам пометить этот вопрос как отвеченный.   -  person Kit Roed    schedule 17.02.2012
comment
Вы можете переписать весь этот вопрос как «Как мне преобразовать 16-битное целое число со знаком, хранящееся с использованием функции VFP BINTOC(), в десятичное число с использованием С#, что сделает его гораздо более полезным для других читателей и с меньшей вероятностью будет закрыто как слишком локализованное .   -  person Caltor    schedule 07.11.2012


Ответы (2)


Похоже, что VFP хранит ваше значение как 16-битное (короткое) целое число со знаком. Кажется, у меня есть странная точка переключения для отрицательных чисел, но она добавляет 128 к 8-битным числам и добавляет 32768 к 16-битным числам.

Таким образом, преобразование ваших 16-битных чисел из строки должно быть таким же простым, как чтение его как 16-битного целого числа, а затем удаление из него 32768. Если вам нужно сделать это вручную, то первое число нужно умножить на 256, а затем добавить второе число, чтобы получить сохраненное значение. Затем отнимите от этого числа 32768, чтобы получить значение.

Примеры:

131 * 256 = 33536
33536 + 132 = 33668
33668 - 32768 = 900

Вы можете попробовать использовать преобразования С# в соответствии с http://msdn.microsoft.com/en-us/library/ms131059.aspx и http://msdn.microsoft.com/en-us/library/tw38dw27.aspx, чтобы сделать хотя бы часть работы за вас, но если нет, то не должно быть слишком сложно написать код выше вручную.

person Caltor    schedule 07.11.2012

С опозданием на несколько лет, но вот рабочий пример.

public ulong CharToBin(byte[] s)
{
  if (s == null || s.Length < 1 || s.Length > 8)
    return 0ul;

  var v = s.Select(c => (ulong)c).ToArray();
  var result = 0ul;
  var multiplier = 1ul;
  for (var i = 0; i < v.Length; i++)
  {
    if (i > 0)
      multiplier *= 256ul;

    result += v[i] * multiplier;
  }

  return result;
}

Это эквивалент VFP 8 и более ранних версий для CTOBIN, который охватывает ваш сценарий. Вы должны быть в состоянии написать свой собственный BINTOC на основе приведенного выше кода. В VFP 9 добавлена ​​поддержка нескольких параметров, таких как нереверсированные двоичные данные, типы данных currency и double, а также значения со знаком. Этот образец охватывает только перевернутые двоичные файлы без знака, как поддерживаются более старые версии VFP.

Некоторые примечания:

  • Код поддерживает 1, 2, 4 и 8-байтовые значения, которые охватывают все числовые значения без знака до System.UInt64.
  • Прежде чем привести результат к ожидаемому числовому типу, вы должны проверить потолок. Например, если вам нужен Int32, проверьте результат на Int32.MaxValue перед выполнением приведения.
  • Образец позволяет избежать сложности кодирования строк, принимая массив байтов. Вам нужно будет понять, какая кодировка использовалась для чтения строки, а затем применить ту же кодировку для получения массива байтов перед вызовом этой функции. В мире VFP это часто Encoding.ASCII, но это зависит от приложения.
person RMart    schedule 07.04.2021