Версия двоичных файлов iostream

Чтобы завершить ответы моего коллеги, вы можете обратить пристальное внимание на:

  • статические вызовы или вызовы экземпляров (в одном случае вам не нужен экземпляр класса, в другом - вам может потребоваться существующий конструктор по умолчанию , который может или не может быть там)
  • вызов открытого или закрытого метода (для последнего, вам нужно вызвать setAccessible) для метода в блоке doPrivileged , другие findbugs не будут счастливы )
  • , инкапсулируя в еще одно управляемое аппликативное исключение, если вы хотите отбросить многочисленные исключения из системы Java ( отсюда CCException в приведенном ниже коде)

Вот старый код java1.4, который учитывает эти моменты:

/**
 * Allow for instance call, avoiding certain class circular dependencies. 
* Calls even private method if java Security allows it. * @param aninstance instance on which method is invoked (if null, static call) * @param classname name of the class containing the method * (can be null - ignored, actually - if instance if provided, must be provided if static call) * @param amethodname name of the method to invoke * @param parameterTypes array of Classes * @param parameters array of Object * @return resulting Object * @throws CCException if any problem */ public static Object reflectionCall(final Object aninstance, final String classname, final String amethodname, final Class[] parameterTypes, final Object[] parameters) throws CCException { Object res;// = null; try { Class aclass;// = null; if(aninstance == null) { aclass = Class.forName(classname); } else { aclass = aninstance.getClass(); } //Class[] parameterTypes = new Class[]{String[].class}; final Method amethod = aclass.getDeclaredMethod(amethodname, parameterTypes); AccessController.doPrivileged(new PrivilegedAction() { public Object run() { amethod.setAccessible(true); return null; // nothing to return } }); res = amethod.invoke(aninstance, parameters); } catch (final ClassNotFoundException e) { throw new CCException.Error(PROBLEM_TO_ACCESS+classname+CLASS, e); } catch (final SecurityException e) { throw new CCException.Error(PROBLEM_TO_ACCESS+classname+GenericConstants.HASH_DIESE+ amethodname + METHOD_SECURITY_ISSUE, e); } catch (final NoSuchMethodException e) { throw new CCException.Error(PROBLEM_TO_ACCESS+classname+GenericConstants.HASH_DIESE+ amethodname + METHOD_NOT_FOUND, e); } catch (final IllegalArgumentException e) { throw new CCException.Error(PROBLEM_TO_ACCESS+classname+GenericConstants.HASH_DIESE+ amethodname + METHOD_ILLEGAL_ARGUMENTS+String.valueOf(parameters)+GenericConstants.CLOSING_ROUND_BRACKET, e); } catch (final IllegalAccessException e) { throw new CCException.Error(PROBLEM_TO_ACCESS+classname+GenericConstants.HASH_DIESE+ amethodname + METHOD_ACCESS_RESTRICTION, e); } catch (final InvocationTargetException e) { throw new CCException.Error(PROBLEM_TO_ACCESS+classname+GenericConstants.HASH_DIESE+ amethodname + METHOD_INVOCATION_ISSUE, e); } return res; }

7
задан Thanatos 20 July 2009 в 03:39
поделиться

4 ответа

Насколько я понимаю, свойства потока, которые вы Повторное использование для указания типов было бы более подходящим для указания порядка байтов, упаковки или других значений «метаданных». Обработка самих типов должна выполняться компилятором. По крайней мере, именно так выглядит STL.

Если вы используете перегрузки для автоматического разделения типов, вам нужно будет указать тип только в том случае, если он отличается от объявленного типа переменной:

Stream& operator<<(int8_t);
Stream& operator<<(uint8_t);
Stream& operator<<(int16_t);
Stream& operator<<(uint16_t);
etc.

uint32_t x;
stream << x << (uint16_t)x;

Чтение типы, отличные от объявленного, будут немного сложнее. В целом, однако, я думаю, следует избегать чтения или записи переменных типа, отличного от типа вывода.

Я считаю, что стандартная версия std :: codecvt ничего не делает, возвращая "noconv" для всего. Он действительно что-то делает только при использовании «широких» символьных потоков. Можно' Вы установили аналогичное определение для codecvt? Если по какой-то причине нецелесообразно определять для вашего потока безоперационный codecvt, то я не вижу никаких проблем с вашим решением для литья, тем более что оно изолировано в одном месте.

Наконец, вы уверены, что не стали бы Не лучше ли использовать какой-нибудь стандартный код сериализации, например Boost , чем накатывать свой собственный?

1
ответ дан 7 December 2019 в 16:44
поделиться

Нам нужно было сделать что-то похожее на то, что делаете вы, но мы пошли другим путем. Мне интересно, как вы определили свой интерфейс. Часть того, с чем я не знаю, как вы справитесь, - это манипуляторы , которые вы определили (binary :: u32le, binaryu16le).

С помощью basic_streams манипулятор управляет тем, как будут считываться все следующие элементы / написано, но в вашем случае это, вероятно, не имеет смысла, поскольку размер (часть информации вашего манипулятора) зависит от входящей и исходящей переменной.

binary_istream in;
int i;
int i2;
short s;
in >> binary::u16le >> i >> binary::u32le >> i2 >> s;

В приведенном выше коде может иметь смысл определить, будет ли переменная i - 32 бита (при условии, что int - 32 бита), вы хотите извлечь из сериализованного потока только 16 бит, а вы хотите извлечь все 32 бита в i2 . После того,

0
ответ дан 7 December 2019 в 16:44
поделиться

Я бы не стал использовать оператор <<, поскольку он слишком тесно связан с вводом-выводом форматированного текста.

Я бы вообще не стал использовать для этого перегрузку оператора. Я бы нашел другую идиому.

0
ответ дан 7 December 2019 в 16:44
поделиться

Я согласен с Legalize. Мне нужно было делать почти то же самое, что и вы, и я посмотрел на перегрузку << / >> , но пришел к выводу, что iostream просто не предназначен для этого. Во-первых, я не хотел создавать подклассы потоковых классов, чтобы иметь возможность определять свои перегрузки.

Мое решение (которое требовало только временной сериализации данных на одной машине и, следовательно, не требовало обращения к порядку следования байтов) было основано на следующем шаблоне:

// deducible template argument read
template <class T>
void read_raw(std::istream& stream, T& value,
    typename boost::enable_if< boost::is_pod<T> >::type* dummy = 0)
{
    stream.read(reinterpret_cast<char*>(&value), sizeof(value));
}

// explicit template argument read
template <class T>
T read_raw(std::istream& stream)
{
    T value;
    read_raw(stream, value);
    return value;
}

template <class T>
void write_raw(std::ostream& stream, const T& value,
    typename boost::enable_if< boost::is_pod<T> >::type* dummy = 0)
{
    stream.write(reinterpret_cast<const char*>(&value), sizeof(value));
}

Затем я дополнительно перегрузил read_raw / write_raw для любых типов, отличных от POD ( например, струны). Обратите внимание, что необходимо перегружать только первую версию read_raw; если вы правильно используете ADL , вторая версия (с 1 аргументом) может вызывать перегрузки с 2 аргументами, определенные позже и в других пространствах имен.

Пример записи:

int32_t x;
int64_t y;
int8_t z;
write_raw(is, x);
write_raw(is, y);
write_raw<int16_t>(is, z); // explicitly write int8_t as int16_t

Пример чтения:

int32_t x = read_raw<int32_t>(is); // explicit form
int64_t y;
read_raw(is, y); // implicit form
int8_t z = numeric_cast<int8_t>(read_raw<int16_t>(is));

Это не так привлекательно, как перегруженные операторы, и что-то не так легко помещается в одну строку (чего я все равно стараюсь избегать, поскольку точки останова отладки ориентированы на строки) , но, думаю, получилось проще, нагляднее и не намного многословнее.

2
ответ дан 7 December 2019 в 16:44
поделиться
Другие вопросы по тегам:

Похожие вопросы: