Страницы

Поиск по вопросам

пятница, 12 апреля 2019 г.

Удаленный веб-сервер для вычислений

Есть программа, написанная на Python3, выполняющая некоторые большие вычисления. Всё выполнение занимает примерно сутки.
На своей машине я запустить не могу, потому что мне она нужна для работы. Есть ли сервисы позволяющие удобно через облако выполнить такую программу и получить результат?
DigitalOcean или Google Compute Engine подойдут для этого?


Ответ

Можете еще посмотреть Microsoft Azure. Они себя иногда рекламируют в том числе и для задач научных расчетов.
Есть еще Amazon Elastic Compute Cloud (Amazon EC2). Вот цитата с их сайта:
Amazon Elastic Compute Cloud (Amazon EC2) – это веб-сервис, предоставляющий масштабируемые вычислительные ресурсы в облаке. Он упрощает процесс крупномасштабных вычислений в облаке для разработчиков.

Производительность алгоритмов std

Потихоньку учусь использовать алгоритмы стандартной библиотеки C++. Самодокументирование кода - это хорошо, но решил проверить и производительность. Например, std::accumulate. Qt Creator, mingw, windows, QTest. В объекте создаём приватные поля:
QVector results_; float sum_; static const size_t size_=65536; float arr_[size_];
В конструкторе пишем:
std::fill(arr_,arr_+size_,1.0);
Создаём три слота:
void Tester::benchmarkSimpleLoopOverArray() { sum_=0; QBENCHMARK { for (size_t i=0;ivoid Tester::benchmarkSmartLoopOverArray() { sum_=0; float * pf=arr_; float * pf0=pf+size_; QBENCHMARK { for (;pfvoid Tester::benchmarkAccumulateOverArray() { sum_=0; QBENCHMARK { sum_=std::accumulate(arr_,arr_+size_,0.0); } results_<В results_ результаты заносим, чтобы компилятор не выбросил ненароком весь цикл, увидев, что его результат не используется. Результаты меня обескуражили:
RESULT : Tester::benchmarkSimpleLoopOverArray(): 0.061 msecs per iteration (total: 63, iterations: 1024) PASS : Tester::benchmarkSimpleLoopOverArray() RESULT : Tester::benchmarkSmartLoopOverArray(): 0.0000046 msecs per iteration (total: 78, iterations: 16777216) PASS : Tester::benchmarkSmartLoopOverArray() RESULT : Tester::benchmarkAccumulateOverArray(): 0.0532 msecs per iteration (total: 109, iterations: 2048) PASS : Tester::benchmarkAccumulateOverArray()
На арифметике указателей получаем выигрыш на 4 порядка! Ради такого я готов написать пару лишних строк кода и строчку комментария.
Соответственно, вопросы:
Можно ли как-то улучшить производительность алгоритмов, как мы это сделали с обычным циклом? Я пробовал генерить два таких же указателя для начала и конца массива, результат получается хуже - таким же, как у наивного цикла. Может ли кто-нибудь проверить, сохранится ли такое соотношение результата под другими компиляторами/операционками? Ну и самый главный вопрос. Как получился такой огромный выигрыш у "хитрого" цикла? Я не настолько хорошо знаю ассемблер, чтобы залезть в код и посмотреть отличия, но получается, что в наивном цикле и стандартных алгоритмах используется какая-то очень тяжёлая операция, которой нет во втором примере. Какая?
Upd: спасибо zenden2k, проблема действительно была в том, что указатели я выставлял до входа в цикл. В результате второй тест полноценно выполнялся только один раз, а потом на входе в for проверял условие
pf, которое не выполнялось - отсюда бешеное количество итераций и, соответственно, малое время на итерацию.


Ответ

У вас ошибка в коде.
Вот это
float * pf=arr_; float * pf0=pf+size_;
должно быть внутри QBENCHMARK а не снаружи.
Также тесты у вас не равнозначны, потому что используется общая переменная sum_, она принимает разные значения в зависимости от кол-ва итераций. Ее надо инициализировать внутри QBENCHMARK
float sum_ = 0;
Тогда получите приблизительно одинаковые результаты
RESULT : TestClass::benchmarkSmartLoopOverArray(): 0.058 msecs per iteration (total: 60, iterations: 1024) PASS : TestClass::benchmarkSimpleLoopOverArray() RESULT : TestClass::benchmarkSimpleLoopOverArray(): 0.059 msecs per iteration (total: 61, iterations: 1024) PASS : TestClass::benchmarkAccumulateOverArray() RESULT : TestClass::benchmarkAccumulateOverArray(): 0.059 msecs per iteration (total: 61, iterations: 1024) PASS : TestClass::cleanupTestCase() Totals: 5 passed, 0 failed, 0 skipped, 0 blacklisted ********* Finished testing of TestClass *********

Как ускорить вычисление оптического потока алгоритмом Лукаса-Канаде?

В OpenCV имеется реализация алгоритма Лукаса-Канаде с использованием пирамид изображений. Работает относительно быстро и, в целом, скоростью своей обязана тому, что вычисляет оптический поток не между всеми пикселями предыдущего и следующего кадров, а исключительно в отношении точек интереса. Но если последних оказывается слишком много, то скорость может быть и снижена, причём довольно существенно.
Имеется ли возможность увеличить производительность, не ограничивая количество точек интереса?


Ответ

Для вычисления оптического потока алгоритмом Лукаса-Канаде с использованием пирамиды изображений используется функция:
void calcOpticalFlowPyrLK( InputArray prevImg, InputArray nextImg, InputArray prevPts, InputOutputArray nextPts, OutputArray status, OutputArray err, Size winSize = Size(21,21), int maxLevel = 3, TermCriteriacriteria = TermCriteria(TermCriteria::COUNT + TermCriteria::EPS, 30, 0.01), int flags = 0, double minEigThreshold = 1e-4)
Но интерес при решении задачи ускорения представляют лишь два её первых аргумента, в качестве которых традиционно подаются матрицы исходных изображений. Проблема заключается в том, что при каждом вызове calcOpticalFlowPyrLK(), последняя "молча" выполнит построение пирамид изображений для каждого из кадров: предыдущего и следующего
Получается, что на каждой межкадровой итерации вызова алгоритма, когда т.н. следующий кадр уже будет отмечен как предыдущий, а его место в качестве следующего займёт новый кадр, случится очевидный перерасход ресурсов. Оно и понятно, для вновь предыдущего кадра пирамида изображений уже вычислялась, была использована, но не была сохранена. В итоге, для каждой последующей межкадровой итерации производится повторное построение пирамиды изображений для одного из кадров в кадровой последовательности.
Непосредственно построением пирамиды изображений для последующего её использования в вычислении оптического потока занимается функция buildOpticalFlowPyramid(). Именно её прозрачно и вызывает calcOpticalFlowPyrLK() для каждого из кадров. Тем не менее, результат работы buildOpticalFlowPyramid(), как это недвусмысленно указано в справке, может быть задействован в calcOpticalFlowPyrLK() как поданый на вход извне вместо обычных изображений.
Рассмотрим два примера использования calcOpticalFlowPyrLK()
Традиционный:
cv::Mat prv_mat, nxt_mat;
while(true) { if(prv_mat.empty()) { prv_mat = readNewFrame(); if(prv_mat.empty()) break;
continue; }
nxt_mat = readNewFrame(); if(nxt_mat.empty()) break;
// Вычисляем оптический поток. cv::calcOpticalFlowPyrLK(prv_mat, nxt_mat, ...);
// Используем его. ...
// Меняем матрицы местами, чтобы текущий "следующий" кадр // стал в новой итерации "предыдущим". std::swap(prv_mat, nxt_mat); }
При использовании данного подхода на каждой итерации в while(true) {...} создание пирамиды изображений будет производиться для каждого кадра, т.е. два раза.
Подход с использованием внешнего вызова buildOpticalFlowPyramid()
std::vector prv_pyr, nxt_pyr;
while(true) { if(prv_pyr.empty()) { cv::Mat mat = readNewFrame(); if(mat.empty()) break;
// Строим пирамиду изображений для кадра. cv::buildOpticalFlowPyramid(mat, prv_pyr, ...);
continue; }
cv::Mat mat = readNewFrame(); if(mat.empty()) break;
// Строим пирамиду изображений для нового кадра. cv::buildOpticalFlowPyramid(mat, nxt_pyr, ...);
// Вычисляем оптический поток. cv::calcOpticalFlowPyrLK(prv_pyr, nxt_pyr, ...);
// Используем его. ...
// Меняем вектора местами, чтобы текущая "следующая" пирамида // стала в новой итерации "предыдущей". std::swap(prv_pyr, nxt_pyr); }
При использовании данного подхода на каждой итерации в while(true) {...} создание пирамиды изображений будет производиться только для одного кадра, т.е. один раз. Скорость работы алгоритма может увеличиться в отдельных случаях в два раза.

Java вызов WinApi функций или управление открытыми окнами чужих программ

Здравствуйте!
Есть программа написанная на JAVA(модуль запускаемый как надстройка одновременно со сторонним приложением).
Из этой java-программы (надстройки), необходимо менять заголовок окон сторонней программы.
Я имею неплохие навыки программирования на java, но с подобными задачами еще не сталкивался. Я знаю, что есть JNI и JNA и куча сторонних библиотек, но в этой области я пока не опытен.
Без проблем могу решить данную задачу на С++ или на Delphi.
Но задача состоит в том, чтобы сделать изменение заголовка чужой программы средствами JAVA
Начальство очень не хочет плодить в проекте модули написанные не полностью на java (если никак по-другому - смирятся)
Рассматриваю варианты по отлову handle, заголовков окна, по id-процесса, по классу окна... Боже! да как угодно -главное чтобы работало!
С радостью приму от вас советы, ссылки, комментарии, и кусочки кода.
Было бы отлично, если кто-то поделится исходником подобной задачи.
Примеры с JNA , JNI приму с радостью!


Ответ

Конечно, JNA — это ваш выбор. Надо скачать две JAR-ки здесь, либо подключить через maven. Вот набросал пример:
import com.sun.jna.Native; import com.sun.jna.platform.win32.WinDef.HWND; import com.sun.jna.win32.StdCallLibrary; import com.sun.jna.win32.W32APIOptions;
public class SetWindowTitle { public static interface User32 extends StdCallLibrary { final User32 instance = (User32) Native.loadLibrary ("user32", User32.class, W32APIOptions.UNICODE_OPTIONS); HWND FindWindow(String className, String windowName); boolean SetWindowText(HWND hwnd, String newText); }
public static void main(String[] args) { if(args.length != 2) { System.out.println("Нужно два аргумента: имя окна (или класс) и новое имя"); return; } HWND hwnd = User32.instance.FindWindow(args[0], null); if(hwnd == null) { hwnd = User32.instance.FindWindow(null, args[0]); } if(hwnd == null) { System.out.println("Окно не найдено"); return; } System.out.println("Нашли окно: "+hwnd); boolean result = User32.instance.SetWindowText(hwnd, args[1]); System.out.println(result ? "Успешно" : "Упс"); } }
Компилировать:
javac -cp jna-4.1.0.jar;jna-platform-4.1.0.jar;. SetWindowTitle.java
Запускать
java -cp jna-4.1.0.jar;jna-platform-4.1.0.jar;. SetWindowTitle "old-title" "new-title"
JNA очень удобно работает. Вы просто объявляете в вашем интерфейсе методы с теми же именами, что в user32 и с совместимой сигнатурой. Внутри JNA создаёт Proxy-класс, который для каждого метода поищет соответствующий внутри user32.dll и преобразует нужным образом аргументы.

Что происходит в интерактивном режиме (>>>) если ввести строку (или идентификатор проинициализированной переменной) и нажать Enter ?

Просто набираем строку с последующим нажатием Enter:
>>> r'hello\"world' 'hello\\"world'
Получил не то, что ожидал. Я думал, что должна вызваться функция print(r'hello\"world') и распечатать строку hello\"world
Теперь так:
>>> print(r'hello\"world') hello\"world
Получил то, что ожидал.
Что происходит в интерактивном режиме(>>>) после ввода строки и нажатия на Enter?


Ответ

Как при вызове print, так и при выводе в интерактивном режиме Python преобразует выражение в строку и выводит её на экран. Различия заключаются в том, что при этом вызываются различные методы преобразования. Если вы имеете понятие об ООП, то вот Вам небольшой пример:
class My: def __str__(self): return '__str__: Вызывается для print' def __repr__(self): return '__repr__: Вызывается в интерактивном режиме'
obj = My() print(obj)
После запуска выведет: __str__: Вызывается для print И далее, если в интерактивном режиме ввести сам объект:
>>> obj __repr__: Вызывается в интерактивном режиме
И __repr__, и __str__ возвращают строку, которая попадает на экран. И так происходит со всеми типами данных, в том числе и с Вашей строкой.
Таким образом:
>>> a = r'hello\"world' >>> a #равносильно вызову print(a.__repr__()) 'hello\\"world' >>> print(a) #равносильно вызову print(a.__str__()) hello\"world

Выполнение действия после завершения нескольких Task

Есть несколько объектов типа Task или Task. Необходимо дождаться завершения работы каждого из этих объектов и выполнить действия по завершению. Можно воспользоваться методом Task.Wait, например так:
public static void Foo() { var t1 = new Task(DoSomething1); var t2 = new Task(DoSomething2);
t1.Start(); t2.Start();
t1.Wait(); t2.Wait();
Console.WriteLine("Tasks completed"); }
private static void DoSomething2() { Console.WriteLine("Do something 2"); }
private static void DoSomething1() { Console.WriteLine("Do something 1"); }
Однако при большом количестве задач это будет выглядеть достаточно громоздко. Какие способы инфраструктура задач .NET предлагает для ожидания выполнения других задач?


Ответ

Существует несколько способов решения предложенной задачи.
Есть статический метод Task.WaitAll, который принимает в качестве аргументов массив задач и блокирует вызывающий поток до завершения всех этих задач. Кроме того, есть перегрузки этого метода, принимающие таймаут ожидания (и возвращающие признак, завершились ли задачи в указанное время) и/или токен отмены ожидания. Также есть перегрузка с параметром, принимающим переменное количество аргументов (ключевое слово params):
public static void Foo() { var t1 = new Task(DoSomething1); var t2 = new Task(DoSomething2);
t1.Start(); t2.Start();
Task.WaitAll(t1, t2); Console.WriteLine("Tasks completed"); }
private static void DoSomething2() { Console.WriteLine("Do something 2"); }
private static void DoSomething1() { Console.WriteLine("Do something 1"); }
Не надо путать метод Task.WaitAll с методом Task.WaitAny, ожидающим выполнения любой из переданных задач.
Если есть возможность писать, используя .NET 4.5, то можно воспользоваться ключевыми словами async/await для асинхронного ожидания выполнения задач. Метод Task.WhenAll создаст задачу, которая завершится, когда завершатся все задачи, переданные ему в качестве аргументов.
Код ниже будет выполняться синхронно, пока выполнение не дойдёт до инструкции await. В этот момент управление будет передано коду, вызвавшему метод Foo, а ожидание выполнения задач будет происходить в другом потоке. По завершению выполнения задач управление будет возвращено методу Foo и он продолжит работу:
public static async void Foo() { var t1 = new Task(DoSomething1); var t2 = new Task(DoSomething2);
t1.Start(); t2.Start();
await Task.WhenAll(t1, t2); Console.WriteLine("Tasks completed"); }
private static void DoSomething2() { Console.WriteLine("Do something 2"); }
private static void DoSomething1() { Console.WriteLine("Do something 1"); }
Кроме того, задача, порождаемая методом Task.WhenAll, является обычной задачей, а значит её можно синхронно подождать, используя метод Task.Wait
public static void Foo() { var t1 = new Task(DoSomething1); var t2 = new Task(DoSomething2);
t1.Start(); t2.Start();
Task.WhenAll(t1, t2).Wait(); Console.WriteLine("Tasks completed"); }
private static void DoSomething2() { Console.WriteLine("Do something 2"); }
private static void DoSomething1() { Console.WriteLine("Do something 1"); }
Ну и наконец, задачу порождённую методом Task.WhenAll можно продолжить, используя метод Task.ContinueWith. Этод метод запускает задачу, переданную ему в качестве аргумента, после завершения заданной задачи. В задаче-продолжении при это можно обработать результаты и исключения задач, которые изначально необходимо было подождать:
public static void Foo() { var t1 = new Task(DoSomething1); var t2 = new Task(DoSomething2);
t1.Start(); t2.Start();
var continuation = Task.WhenAll(t1, t2).ContinueWith( t => { Console.WriteLine("Tasks completed"); });
continuation.Wait(); }
private static void DoSomething2() { Console.WriteLine("Do something 2"); }
private static void DoSomething1() { Console.WriteLine("Do something 1"); }
P.S. Отдельное спасибо @NickVolynkin за предложение задать вопрос и самому ответить на него и @PavelMayorov за идею с ожиданием через Task.WhenAll

Почему не вызывается событие

Всем привет, есть такой вот код
using System; class a { public virtual event EventHandler MyEv; public void StartEvent() { MyEv(4, EventArgs.Empty); } } class b : a { public override event EventHandler MyEv; } class c { static void Main() { b B = new b(); B.MyEv += (o, e) => Console.WriteLine("From class B"); B.StartEvent(); } }
Почему не вызывается обработчик добавленный к типу B, ведь событие было переопределено в классе B ?


Ответ

Событие в C# это набор из:
приватного поля-делегата метода add метода remove метаданных
Т.к. в C# (и вообще .NET) нет виртуальных полей, то virtual на event делает виртуальными только методы add / remove. Неявная реализация события приводит к тому, что классы a и b получают каждый свое приватное поле-делегат. И свою пару add/remove, которая работает или с полем из a или с полем из b. Т.е. ваш код эквивалентен следующему:
class a { private EventHandler _MyEvField; public virtual event EventHandler MyEv { add { _MyEvField += value; } remove { _MyEvField -= value; } }
public void StartEvent() { _MyEvField(4, EventArgs.Empty); } }
class b : a { private EventHandler _MyEvField_2;
public override event EventHandler MyEv { add { _MyEvField_2 += value; } remove { _MyEvField_2 -= value; } } }
т.е. override переопределяет механизм подписки на событие. Но не переопределяет поле, которе используется для вызова в a.StartEvent. При этом поле остается приватным, и добраться до него из класса b не получится. Чтобы все заработало, вам придется делать виртуальным еще и метод StartEvent, и переопределять его в b
Это делает механизм virtual/override для событий полностью бессмысленным. Максимум, для чего его можно использовать - трассировка, логгирование или мокинг.

Интересные возможности vanilla.js - доступ по id

OneOne!
Может для кого то я и не открыл Америку, но сам столкнулся впервые. Т.е. я не должен писать document.getElementById('oneOne'); Т.к. любые "переменные" и функции, вызванные через объект window - это его свойства и методы, значит все ИД всех елементов заносятся в свойства этого объекта.
Вопрос:
Когда это вообще появилось?
На сколько это хорошо в использовании (явно удобней, чем через get)?
Какие ограничения и по какой причине не используется массово?
Или просто сейчас мало кто использует чистый JS?
У кого есть ссылки на спецификацию и / или статьи на эту тему?


Ответ

Если элементу назначен специальный атрибут id, то можно получить его прямо по переменной с именем из значения id. Это поведение соответствует стандарту. Оно существует, в первую очередь, для совместимости, как осколок далёкого прошлого и не очень приветствуется, поскольку использует глобальные переменные. Браузер пытается помочь нам, смешивая пространства имён JS и DOM, но при этом возможны конфликты. Более правильной и общепринятой практикой является доступ к элементу вызовом document.getElementById("идентификатор").
Отсюда
As a general rule, relying on this will lead to brittle code. Which IDs end up mapping to this API can vary over time, as new features are added to the Web platform, for example. Instead of this, use document.getElementById() or document.querySelector().
Спецификация
P.S. К vanilla.js это отношения не имеет.

Поменять расположение символов в строке

Есть у меня value в которой содержится строка наподобие руб.260000 (обязательно присутствуют символы & или #) Мне нужно поменять элементы передвинуть число 260000 вперед, а закодированную кирилицу руб. назад - вот так: 260000руб.
if(value.contains("&#")) { var out = value.replace(/^([^\d]*)([\d]*)/g,'$2 $1'); console.log(out); }
вот так получаю ошибку - value.contains is not a function


Ответ

Тут есть 2 проблемы:
В JavaScript нет метода String.prototype.contains Регулярное выражение в вашем примере кода не будет работать так, как вы того ожидаете.
Таким образом, правильный код выглядит как-то так:
if(value.toString().indexOf("&#") !== -1) { var out = value.replace(/^(.*?)([\d]*)$/, '$2$1'); console.log(out); }
UPD:
Если нужно каким-то образом изменить части строки перед перестановкой, можно использовать следующий подход:
if(value.toString().indexOf("&#") !== -1) { var out = value.replace(/^(.*?)([\d]*)$/, function(match, p1, p2) { // p1 и p2 группы, захваченные регулярным выражением. // Если value = 'руб.260000', то: // p1 = 'руб.' // p2 = '260000' // Для примера, склеим эти строки вместе в обратном порядке. return p2 + p1; }); }

Проблема с кодировкой windows-1251 на linux

Читаю txt-файлы в java/groovy в кодировке WINDOWS-1251
Часть файлов читается успешно, но один файл из читается успешно только под windows, а под linux кодировка обрабатывается неверно.
Код чтения из файла Groovy
String fileEncoding = "cp1251" file.eachLine(fileEncoding) { line -> esvData << line.split('=') System.out.println(line)}
В логе на Windows видны русские буквы, а на i686-redhat-linux(6.0) лог имеет следующий вид:
1CClientBankExchange ВерсияФормата=1.02 Кодировка=Windows Отправитель= Получатель= ДатаСоздания=23.03.2015 ВремяСоздания=01:46:15 ДатаНачала=20.03.2015 ДатаКонца=20.03.2015 РасчСчет=407028
При этом файлы в кодировке windows-1251 из других источников обрабатываются успешно на том же linux
В чем-то, кроме кодировки, может быть разница? Слышал, что могут присутствовать какие-то доп. символы в начале файла.
package com.peterservice.pays.filepay.camel.processors.inscriptproc;
import com.peterservice.pays.filepay.camel.processors.InScriptProc; import com.peterservice.pays.filepay.enums.CamelProperties; import com.peterservice.pays.filepay.enums.Directories; import com.peterservice.pays.filepay.model.Pay; import com.peterservice.pays.filepay.model.PayRoute; import org.apache.camel.Exchange; import org.apache.camel.impl.DefaultCamelContext; import org.apache.camel.impl.DefaultExchange; import org.junit.Assert; import org.junit.Ignore; import org.junit.Test;
import java.io.File; import java.math.BigDecimal; import java.util.HashMap; import java.util.Map;
/** * Created by Yuriy.Vinogradov on 06.08.2015. */ public class InScriptProc1CTest {
@Test public void test() throws Exception { InScriptProc processor = new InScriptProc(); Exchange exchange = prepareExchange(); processor.process(exchange); Pay[] payments = exchange.getIn().getBody(Pay[].class); Assert.assertEquals(256, payments.length); for (Pay payment : payments) { if (payment.number.equals("549")) { Assert.assertEquals(new BigDecimal("0.4"), payment.amount); Assert.assertEquals("2015-03-20", payment.inDate); Assert.assertEquals("770fgh320", payment.INN); Assert.assertEquals("770fhh001", payment.payerKpp); Assert.assertEquals("401058fgh000fh79", payment.payerAccount); Assert.assertEquals("УФК по г.Москве (ФКУ \"Дирекция космодрома \"Восточный\")", payment.payerTitle); Assert.assertEquals("25904fgh2221 0373fg910 Опл. за услуги сот.связи за декабрь2014, дог.от 12.12.14 №2350948, сч.14-1 от 26.12.2014, акт DV03/70761371/28 от 26,12,2014 , в т.ч. НДС-0,06 (л/с 15fg925)", payment.paymentReason); } else if(payment.number.equals("701")) { Assert.assertEquals(new BigDecimal("1.79"), payment.amount); Assert.assertEquals("2015-03-20", payment.inDate); Assert.assertEquals("2815fff915", payment.INN); Assert.assertEquals("27fff1001", payment.payerKpp); Assert.assertEquals("30302810fffh0000100", payment.payerAccount); Assert.assertEquals("ФКП \"Аэропорты Дальнего Востока\" р/с 40502810409fghfh001 в ХФ ОАО \"МДМ БАНК\" г Хабаровск", payment.payerTitle); Assert.assertEquals("УИНО///Оплата по сч-фак. №10010687719/800 от 28.02.2015 л/счет 1fgh4543. Сумма 1-79 В т.ч. НДС (18%) 0-27", payment.paymentReason); } else if(payment.number.equals("822")) { Assert.assertEquals(new BigDecimal("50"), payment.amount); }else{ // Assert.fail("Not expected document number:" + payment.number + " Check if it is correct and create if branch for this document number"); } } }
private Exchange prepareExchange() { Exchange exchange = new DefaultExchange(new DefaultCamelContext()); PayRoute payRoute = new PayRoute(); exchange.getIn().setBody(payRoute); payRoute.setInScript("src/scripts/1c-java.groovy"); Map resultDirs = new HashMap<>(); resultDirs.put(Directories.ERROR.title, "test/" + Directories.ERROR.title + "/dir/"); resultDirs.put(Directories.GF.title, "test/" + Directories.GF.title + "/dir/"); resultDirs.put(Directories.LG.title, "test/" + Directories.LG.title + "/dir/"); resultDirs.put(Directories.UNDEFINED.title, "test/" + Directories.GF.title + "/dir/"); resultDirs.put(Directories.LOG.title, "test/" + Directories.LOG.title + "/dir/"); payRoute.setResultDirs(resultDirs); exchange.setProperty(CamelProperties.ProcessingFile.title, new File("src/test/resources/sberbank_27_20150320_1.txt").getAbsoluteFile()); return exchange; } }
hexdump для проверки начала файла на bom
[relstand@srv3-amain-a test]$ hexdump -C sberbank_27_20150320_1.txt | head 00000000 31 43 43 6c 69 65 6e 74 42 61 6e 6b 45 78 63 68 |1CClientBankExch| 00000010 61 6e 67 65 0d 0a c2 e5 f0 f1 e8 ff d4 ee f0 ec |ange............|


Ответ

вы применили лишнюю перекодировку «из cp1251 в utf8», в чём несложно убедиться, выполнив обратную перекодировку:
$ echo '1CClientBankExchange ВерсияФормата=1.02 РљРѕРґРёСЂРѕРІРєР°' | iconv -f utf8 -t cp1251 1CClientBankExchange ВерсияФормата=1.02 Кодировка
читайте этот файл «как есть», без каких-либо перекодировок.
Слышал, что могут присутствовать какие-то доп символы в начале файла?
да, это называется bom. убедиться в их наличии/остутствии можно, например, так:
$ hexdump -C путь.к.исследуемому.файлу | head 00000000 70 61 63 6b 61 67 65 20 63 6f 6d 2e 70 65 74 65 |package com.pete| 00000010 72 73 65 72 76 69 63 65 2e 70 61 79 73 2e 66 69 |rservice.pays.fi| 00000020 6c 65 70 61 79 2e 63 61 6d 65 6c 2e 70 72 6f 63 |lepay.camel.proc| 00000030 65 73 73 6f 72 73 2e 69 6e 73 63 72 69 70 74 70 |essors.inscriptp| 00000040 72 6f 63 3b 0a 0a 69 6d 70 6f 72 74 20 63 6f 6d |roc;..import com| 00000050 2e 70 65 74 65 72 73 65 72 76 69 63 65 2e 70 61 |.peterservice.pa| 00000060 79 73 2e 66 69 6c 65 70 61 79 2e 63 61 6d 65 6c |ys.filepay.camel| 00000070 2e 70 72 6f 63 65 73 73 6f 72 73 2e 49 6e 53 63 |.processors.InSc| 00000080 72 69 70 74 50 72 6f 63 3b 0a 69 6d 70 6f 72 74 |riptProc;.import| 00000090 20 63 6f 6d 2e 70 65 74 65 72 73 65 72 76 69 63 | com.peterservic|

обновление
а ещё парсер, теоретически, может «сбиваться» из-за разных окончаний строк
распространённых вариантов как минимум три:
cr lf cr + lf
для изменения этих символов в операционной системе gnu/linux можно воспользоваться программами (из пакета dos2unix, присутствующего в репозиториях всех популярных дистрибутивов):
dos2unix unix2dos unix2mac mac2unix
вызов (для замены пары cr + lf на lf):
$ dos2unix путь.к.файлу

python загрузка файлов vk

Подключил VK API. Необходимо сделать отправку файлов на сервер как о этом рассказано на этой странице - http://vk.com/dev/upload_files P.S. Загрузка файлов на стену пользователя
import vk from time import sleep import sys import urllib.request import urllib.parse import base64 import requests
vkapi = vk.API(access_token='token', app_id='id') sleep(0.5)
data = vkapi.photos.getWallUploadServer(user_id="72374405") DATA_USER_ID = data['user_id'] DATA_ALBUM_ID = data['album_id'] DATA_UPLOAD_URL = data['upload_url']
#with open("1.jpg", "rb") as image_file: #fileD = base64.b64encode(image_file.read())
#files = {'1.jpg': open('1.jpg', 'rb')} #r = requests.post(DATA_UPLOAD_URL, files=files) #r.status_code == requests.codes.ok #print(r) #html = r.read().decode("utf-8")
#dataP = '1.jpg' dataP = "photo=" + dataP#.encode("ASCII") response = urllib.request.urlopen(DATA_UPLOAD_URL,dataP) html = response.read().decode("utf-8") print (html)
решеткой помечено то, что пробовал но не сработало, либо не подошло.
Вроде как корректно отработался вариант с
files = {'1.jpg': open('1.jpg', 'rb')} r = requests.post(DATA_UPLOAD_URL, files=files) r.status_code == requests.codes.ok print(r) #html = r.read().decode("utf-8")
Однако в таком случае не работает вывод и тем самым я не могу понять, отработался ли должным образом запрос.
В случае успешного завершения кода выхлоп таков:
{"server":622624,"photo":"[]","hash":"8112ae8847b27fb1cdf678d3d168e6ae"}
То есть загрузка изображения провальная.
Может кто-либо смог или и так знает как загрузить файл на сервер ВК через POST на Python3. Поделитесь опытом, советом, замечанием. Если что-то в коде непонятно - пишите; отвечу.


Ответ

Вот мой вариант размещения фотографии на стене сообщества от имени сообщества. Реализован алгоритм, описанный в официальной документации
# Импортируем необходимые модули import vk import requests
# Задаём идентификатор группы, токен доступа, картинку и её описание group_id = 'my_group_id' access_token = 'my_access_token' filename = 'image.jpg' caption = 'Some text'
# Авторизуемся в VK session = vk.Session(access_token=access_token) vk_api = vk.API(session)
# Получаем адрес сервера для загрузки картинки upload_url = vk_api.photos.getWallUploadServer(group_id=group_id)['upload_url']
# Формируем данные параметров для сохранения картинки на сервере request = requests.post(upload_url, files={'photo': open(filename, "rb")}) params = {'server': request.json()['server'], 'photo': request.json()['photo'], 'hash': request.json()['hash'], 'group_id': group_id}
# Сохраняем картинку на сервере и получаем её идентификатор photo_id = vk_api.photos.saveWallPhoto(**params)[0]['id']
# Формируем параметры для размещения картинки в группе и публикуем её params = {'attachments': photo_id, 'message': caption, 'owner_id': '-' + group_id, 'from_group': '1'} vk_api.wall.post(**params)

Ошибка “Приложение не установлено”

Тестировал приложение на устройстве, все было гуд. Для тестирования покупок загрузил подписанный апк в Google Developer Console в альфа канал. Добавил покупки. Добавил аккаунты для тестирования. В телефоне под ним залогинен. Для тестирования удалил предыдущую установку приложения, закинул подписанный апк на флешку и запустил установку. Выдает ошибку "Приложение не установлено" в чем может проблема?. Телефон перезагружал, память чистил, пытаюсь сбросить до заводских настроек, телефон просто перезагружается. Прошивка кастомная.
UPD
В списках приложений после удаления приложение все равно есть, только указано что оно удалено


Ответ

В новых версиях Android при включённом аккаунте "гостя", приложения обычным методом не удаляются ("удаляясь" только для активного пользователя). Поэтому, при попытке установки приложения(ранее "удалённого") она заканчивается неудачей (ведь на самом деле оно на аппарате уже стоит).
По крайней мере у меня на 5.1. Оставляйте одного пользователя, если используете аппарат для отладки приложений.

Как разобрать XML в Oracle SQL?

В таблице есть столбец clob, в котором хранится текст XML такого вида:

БРЕСТСКАЯ Город КОБРИН Улица СУВОРОВА 33 6 225306

Хочется разобрать это силами SQL, получив в результате склейку значений. В данном случае хочу получить на выходе
БРЕСТСКАЯ КОБРИН УлицаСУВОРОВА 33 6
Подскажите, как можно добиться такого результата?


Ответ

with t as (select '

БРЕСТСКАЯ Город КОБРИН Улица СУВОРОВА 33 6 225306
' as xml_ from dual) SELECT extractvalue(s.column_value, '/*/Element[@type=''district'']')||' '|| extractvalue(s.column_value, '/*/Element[@type=''city'']')||' '|| 'Улица '||extractvalue(s.column_value, '/*/Element[@type=''street'']')||' '|| extractvalue(s.column_value, '/*/Element[@type=''house'']')||' '|| extractvalue(s.column_value, '/*/Element[@type=''flat'']') as VAL FROM t, table(xmlsequence(EXTRACT(XMLTYPE(t.xml_), '/Address'))) s

Подключение библиотеки Python без установки

Появилась необходимость подключить библиотеку, ну возможности ее поставить нет. На сервере я не root, и при попытке поставить библиотеку дает ошибку типа не хватает прав на запись. Для полного моего счастья мне нужна библиотека requests, можно ли ее как-нибудь подключить не устанавливая?


Ответ

Для установки Питон пакетов можно обойтись без root. Например, можно создать virtualenv в доступной для записи директории или устанавливать в пользовательскую директорию:
$ python3 -m pip install --user requests
Если в данный момент нет интернета или другого способа получить дистрибутив requests, то можно попробовать использовать копию requests, которая включена в установку pip, которая поставляется с недавними версиями Питона:
$ python3 -c "from pip._vendor import requests"
В моем случае python 2.7.3, проверял на 3 все работает, а вот на втором не очень..
Если вы не можете до 2.7.9+ обновится, где pip поставляется с python, то pip и virtualenv могут быть и так доступны отдельно в системе (попробуйте pip, virtualenv команды напрямую). Если они не доступны, то достаточно скачать virtualenv.py и запустить его: python virtualenv.py имя. В активированном virtualenv, уже можно pip install requests запустить.

Spinner не устанавливать значение пока не нажму(android)

У меня есть spinner:
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { @Override public void onItemSelected(AdapterView parent, View view, int childposition, long id) { textView.setText(spinner.getSelectedItem().toString()); }
@Override public void onNothingSelected(AdapterView parent) { textView.setText(""); } });
У меня есть textView При запуске программы, по стандарту туда устанавливается первое значение списка, т.е:
list.add("one"); list.add("two");
Когда я запущу свой пример то у меня в textView будет one.
Вопрос: как сделать так что б при запуске программы у меня был textView.setText("") и только тогда когда я нажму на спиннер и выберу item то устанавливалось textView.setText(spinner.getSelectedItem().toString()); ?


Ответ

То что вы описали - нормальное поведение дефолтного Spinner. Это многим не нравится, поэтому появилось альтернативное решение https://github.com/justjohn/transitwidget/blob/master/src/com/transitwidget/NoDefaultSpinner.java. Добавьте этот класс в свой проект и используйте вместо стандартного Spinner - NoDefaultSpinner. У вас не будет выбираться первое значение по умолчанию, а в самом Spinner будет устанавливаться текст из атрибута prompt.

Добавить иконку в EditText

Как можно добавить иконку в поле вводе EditText, Пример:

Исходник:


Ответ

Самый простой вариант - это добавить к EditText такую строчку:

Ошибка: Parse error: syntax error, unexpected '[', expecting ',' or ';' in

True http://rutube.ru 1 12 Озвучено и пере...
Разбираю на PHP вот так:
echo $xml->results[0]->list-item[0]->description;
Вижу такую ошибку:
Parse error: syntax error, unexpected '[', expecting ',' or ';' in D:\SERVER\domains\home.ru\index.php on line 7
В чем проблема? Я же все верно сделал, по XML тегам. А получаю ошибку.


Ответ

echo $xml->results[0]->{'list-item'}[0]->description;

Передача данных между python и node.js

Здравствуй, есть скрипт на Python, который получает данные от датчиков и управляет моторами (это не важно) и node.js ,который работает с клиентом через socket.io.
Как можно передать данные из python скрипта в js скрипт и наоборот?
Пробовал запускать python из под node.js, через библиотеку python-shell Но данные от python скрипта доходят только после его завершения, а мне нужно передавать данные во время работы скрипта.


Ответ

Это типичная проблема сопряжения разнородных систем (не только python + node.js).
В зависимости от специфики задачи, для передачи данных между подсистемами могут использоваться потоки ввода-вывода, socket-соединения, разделяемая память, различные IPC решения и множество других методов.
В общем случае, когда подсистемы находятся на разных машинах (физических или виртуальных), задача может быть решена через использование посредника для передачи сообщений из одной подсистемы в другую. Хорошим (хотя и несколько избыточным) решением может быть очередь сообщений: ActiveMQ, RabbitMQ и т.д. Можно попробовать использовать Redis, с его реализацией Pub/Sub
Если говорить о вашем конкретном случае, то можно попробовать реализовать клиент socket.io в python приложении, и отправлять данные по этому каналу. Мне кажется, это будет одним из самых простых и нетребовательных к ресурсам решений.

Как сделать круг в IE8, если очень надо?

Собственно, речь о стилизации радиобаттонов и чекбоксов. Радиобаттон должен быть круглым, но в IE8 border-radius не работает.
Вариант включать обводку в фоновую картинку не подходит, поскольку нужны обводки разных цветов в зависимости от условий.
Какие есть альтернативы?
input[type="radio"], input[type="checkbox"] { display: none; } input[type="radio"] + label, input[type="checkbox"] + label { border: 1px solid green; display: inline-block; cursor: pointer; width: 1em; height: 1em; } input[type="radio"] + label { border-radius: 50%; } input[type="checkbox"] + label { border-radius: .25em; } input:checked + label { background: silver; /* На самом деле тут фоновая картинка, разная */ }

PS: Вместо :checked скрипт вешает соответствующий класс.


Ответ

Дикая, конечно, идея: в IE8 прекрасно работает vml. Можно внутрь label поместить vml:shape и стилизовать уже его.

Как сделать Material Design Календарь на Android (см. скриншот)?


Как сделать такой Material Design Календарь под Android? Есть ли какие-нибудь библиотеки? Интересует именно дизайнерское решение.


Ответ

Всё, что на скриншоте сделано с помощью библиотеки Android Design Support Library от гугла.
В данном случае эта разметка содержит:
CoordinatorLayout, а в нём AppBar, а в нём CollapsingToolbarLayout, а в нём Toolbar и (наверное) GridView (для календаря) В CoordinatorLayout также еще RecyclerView (или ScrollView) и FloatingActionButton

Как в Linux клонировать диск в диск другого размера

Имеем Linux - Fedora 22, HDD - на котором установлена система, требуется переехать на SDD который в два раза меньшего размера, но данных на HDD мало, поэтому влезут. Оба диска подключены к компьютеру. Вопрос: как клонировать диск? Желательно средствами GNU Linux.
Уточнения: 1. CD/DVD - нет. 2. gparted - не работает с активным системным разделом. 3. Куда tar архив размещать? в /dev/null ? два диска всего. 4. Диски разного размера!


Ответ

Все можно сделать, главное аккуратно. Нужны следующие вещи:
livecd диск или лучше флешка. Можно другого совместимого дистрибутива, к примеру ubuntu. оба диска должны быть подключены к компу.
Процедура переноса.
загрузится с live открыть gparted или любую другую любимую утилиту для разбивки диска. разбить ssd как нужно (home, root, swap и дальше по предпочтениям), отформатировать монтируем новые диски и старые. Рекомендую сделать в /mount папку old (для старого диска) и new (для нового). копируем данные. Так как это линукс, то можно с помощью cp, главное сохранить права. К примеру home cp -a /mount/old/home/ /mount/new/home аналогично копируется корень. Но тут есть особеность - не все нужно копировать. к примеру, папку tmp не нужно (хотя ничего плохого не будет). Если в папка /mount/old/proc и /mount/old/sys что то будет внутри - это копировать не нужно (содержимое этих папок система создает сама). не забываем о boot разделе. если имена устройств поменялись (к примеру, home это был /dev/sda*1*, а стал /dev/sdb*4* - тут важна цифра, а не буква), то открываем файл /mount/new/etc/fstab и правим по феншую. осталось последнее - перенести загрузочную запись. Вначале копируем старый dd if=/dev/sdX of=/path/to/mbr_file.img bs=512 count=1, а потом переносим на новый. Так как мы не хотим потереть таблицу разделов, то нужно не все скопировать. dd if=/path/to/mbr_file.img of=/dev/sdX bs=446 count=1
Все, можно выключать, поставить диски по местам, поправить в биосе загрузочное устройство и пробовать.
Что делать, если ничего не завелось?
Старый диск скорее всего не поврежден. Так что им можно будет загрузиться. Плюс есть флешка. Можно восстановить.
Но если честно, то я переносил немного по другому. Все как выше, разбил диск, скопировал home раздел, потом вытянул старый диск, и загрузился с флешки. И начал установку как обычно. В процессе установки главное не отформатировать home раздел (хотя потом все равно можно скопировать). Так как home раздел есть, то сохранятся все настройки программ. Потом только возможно нужно будет доустановить недостающие программы.

Узнать высоту элемента через Javascript, если она прописана в стилевом файле

Как я могу получить атрибут height элемента через Javascript, если он прописан в стилевом файле style.css?
style.css:
.menu_bottom { height: 100px; }
index.php:

Как послать данные на ком-порт?

надо послать 0x55 на 3 ком-порт с одним стоп битом.
using System; using System.IO.Ports;
namespace Com { class Program { static void Main(string[] args) { try { SerialPort _serialPort = new SerialPort("COM3", 2400, Parity.None, 8, StopBits.One); _serialPort.Handshake = Handshake.None;
_serialPort.Open(); _serialPort.DataReceived += new SerialDataReceivedEventHandler(sp_DataReceived);
byte sent = 0x55; Console.WriteLine("sent: {0}", sent); _serialPort.Write(new byte[1] { sent }, 0, 1);
} catch (Exception e) { Console.WriteLine("Exception:, {0}", e); } } private static void sp_DataReceived(object sender, SerialDataReceivedEventArgs e) { SerialPort sp = (SerialPort)sender; string indata = sp.ReadExisting(); Console.WriteLine("Data Received:, {0}", indata); Console.ReadLine(); //Pause } } }
Вроде все верно. Но программа ничего не показывает. Где может закрасться ошибка?


Ответ

Причин может быть много:
возможно у вас в системе несколько СОМ-портов и вы отправляете не на тот; устройство которому вы отправляете посылку ничего не отвечает; скорость не подходит, попробуйте поставить, например, 1200; попробуйте поменять таймауты.
_serialPort.ReadTimeout = 500; _serialPort.WriteTimeout = 500;
Или же ваша программа закрывается еще до получения ответа. Попробуйте так:
static void Main(string[] args) { try { SerialPort _serialPort = new SerialPort("COM3", 2400, Parity.None, 8, StopBits.One); _serialPort.Handshake = Handshake.None;
_serialPort.Open(); _serialPort.DataReceived += new SerialDataReceivedEventHandler(sp_DataReceived);
byte sent = 0x55; Console.WriteLine("sent: {0}", sent); _serialPort.Write(new byte[1] { sent }, 0, 1);
} catch (Exception e) { Console.WriteLine("Exception:, {0}", e); } Console.ReadKey(); }

Функция с бесконечным количеством параметров

В JavaScript'e есть функция console.log(), в которую можно передать много параметров. В моём проекте есть нечто подобное:
var MyObj = { log: function() { if (ENV != 'dev') { return; } //TODO more actions with console.log } }
Есть функция, которая будет принимать параметры и передавать их в console.log() Но как достичь её универсальности, если вызовы будут, например, такими:
MyObj.log("var1=%s,var2=%s,var3=%s", var1, var2, var3); MyObj.log("var1=%s,var2=%s,var3=%s,var4=%s,var5=%s", var1, var2, var3, var4, var5);
Как правильно передать в console.log() N аргументов, чтобы при этом не возникало undefined?


Ответ

Если достаточно просто вывести все аргументы на консоль, то:
ENV = "dev"; var MyObj = { log: function() { if (ENV != 'dev') { return; } console.log.apply(console, arguments); } } MyObj.log(1, 2, 3, 4, 5);
Если нужно именно хитрое форматирование - то вам придется его написать вручную.

MySQL, переделать запрос для выборки

Есть массив, вида
[ {date: '2015-05-01', number: 1}, {date: '2015-05-01', number: 2}, {date: '2015-05-03', number: 1}, ]
Как можно составить запрос для MySQL, что бы вернуть данные по совпадению date AND number в этом массиве.
То есть для таких данных будет запрос:
SELECT * FROM TABLE WHERE (date='2015-05-01' AND number=1) OR (date='2015-05-01' AND number=2) OR (date='2015-05-03' AND number=1)
Но, может есть более простой/компактный/красивей вариант?


Ответ

Вы можете использовать конструкцию in вот так:
SELECT * FROM TABLE WHERE (date, number) in (('2015-05-01', 1), ('2015-05-01', 2), ('2015-05-03', 1))
Sql Fiddle пример

swift ios как запустить анимацию во время вычислений

Со свифтом знакома меньше недели, так что извиняюсь, если вопрос слишком глупый, но дело вот какое:
У меня есть контроллер, в котором я ввожу данные, клацаю на кнопку и перехожу к другому контроллеру, в котором производятся вычисления и выводятся на экран. Все вычисления прописаны во viewDidLoad второго контроллера, и если введенное значение слишком большое, то они занимают много времени. И все это время экран зависает на первом контроллере
Я хочу сделать так, чтобы пока производятся вычисления на экране была гифка, но вышло так, что сначала все считается, потом включается гифка и тут же переход. (subView я пробовала добавлять и в функцию кнопки и в функцию ShouldPerformSegue)


Ответ

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

Алгоритм поиска пары ближайших точек

Подскажите, пожалуйста, алгоритм со сложностью O(n ln(n)) для поиска пары ближайших точек (плоскость) в массиве. Было бы очень хорошо, если есть реализация на C# (но подойдет хотя бы псевдокод). p.s. На входе массив с точками (точки имеют координаты Х, У). На выходе - две точки, которые находятся на самом коротком расстоянии среди всех возможных вариантов. p.s.s. Фишка именно в сложности алгоритма: O(n ln(n)).


Ответ

Приведу выписку из своих конспектов по АиСД:
Отсортируем наш массив по координате x и y (На выходе получим два отсортированных массива; Время — O(nlogn)). Теперь мы запустим рекурсивную функцию, которая вернет нам две ближайшие точки.
В рекурсивной функции мы разделим массив точек на две части относительно медианы (за O(n)) и рекурсивно найдем в каждой из частей две ближайшие точки. Назовем кратчайшее расстояние, известное на данный момент, δ.

Осталось проверить, нету ли таких точек, которые лежат в разных половинах, и расстояние между ними короче, чем δ. Для этого рассмотрим любую точку и заметим вот что: если есть точка, расстояние до которой меньше, чем δ, она непременно должна лежать в прямоугольнике со сторонами δ на 2δ:

Но в таком прямоугольнике может уместиться не более шести точек, иначе расстояние между ними станет меньше δ и возникнет противоречие.
Тогда достаточно для каждой точки рассмотреть 6 следующих ее соседей в отсортированном по y массиве.
Время работы T[n]=2T[n/2]+O(n)=O(nlogn) по основной теореме о рекуррентных соотношениях.
Реализация на python

Теория. Применение IEnumerator и yield в Unity3D

Часто вижу в разных статьях и справочниках по программированию в Unity3D использование интервфейса IEnumerator. Но не могу найти точную информацию о его практической необходимости. Расскажите, пожалуйста, подробно. Чем обусловлена необходимость использования этого интерфейса. Теоретические статьи и примеры желательно на русском языке.
С наилучшими пожеланиями, Любитель. P.S Спасибо Алексею за ссылку на этот урок. Он подробный. Пару дней практики по вашим ответам и тема освоена.


Ответ

IEnumerator прямого отношения к Unity не имеет. Это интерфейс из C# "вообще". Он (а точнее, класс, его реализующий) определяет правила перебора некой коллекции. Наверняка вам известен цикл foreach - он позволяет пройтись по всем элементам некой коллекции, причем, в отличие от цикла for программист может позволить себе не забивать голову контролем выхода за границы коллекции. Однако чтобы ваш класс (коллекцию) можно было скормить этому циклу, необходимо, чтобы у него был метод GetEnumerator (тут стоит упомянуть распространенное заблуждение, что для foreach нужен класс, реализующий IEnumerable. Это не так. Ему подойдет любой класс, имеющий метод GetEnumerator с соответствующей сигнатурой и возвращаемым значением). А GetEnumerator как раз должен возвращать экземпляр класса, реализующий IEnumerator, в котором описывается вся логика перебора коллекции.
Необходимость самостоятельно реализовывать IEnumerator возникает нечасто, возможностей встроенных коллекций обычно бывает вполне достаточно для выполнения большинства задач. Возможной причиной для самостоятельной реализации этого интерфейса является необходимость определить какие-то нестандартные правила перебора некой коллекции. Например, если вы хотите, чтобы в коллекции перебирался каждый второй ее элемент.
Стоит также отметить, что этот интерфейс часто используется в связке с IEnumerable, который имеет единственный метод
IEnumerator GetEnumerator()
или для обобщенного варианта
IEnumerator GetEnumerator()
Теперь пару слов про yield. Это удобный синтаксический сахар, который позволяет вместо довольно утомительной реализации IEnumerator определить правила перебора какой-либо коллекции. Вы пишете довольно простой метод, а компилятор за кулисами выполняет всю черновую работу по реализации итератора. Более подробно можно почитать например тут или здесь

Как убрать из html блок при определённом размере экрана?

Есть блок с большими картинками, которые на мобильном вообще не нужны. Если скрывать через @media .nomob{display:none}, то картинки всё равно жрут трафик.
Я так понимаю, что тут поможет JS-скрипт со сравнением размера экрана:
function screen_check(){ if ($(window).width() <= 992) { $('.nomob').?????????; } ; } screen_check(); $(window).on('resize', function(){ screen_check(); });
Пожалуйста, без jQuery.


Ответ

Лучше определять устройство на сервере по User-Agent: в Headers. И в зависимости от устройства посылать мобильную или десктопную версию. Тогда не потребуется грузить front-end лишними скриптами.

Параметр функции, содержащий одно из нескольких значений

Каким образом можно описать параметр функции?
Допустим есть функция: void stick(int a, inb &b, /* ? */ direct)
Собственно вместе с этим direct я передаю один из двух параметров - right и left. И в теле функции должна происходить проверка, на указанный параметр.


Ответ

Попробуйте так:
enum Direction { Left, Right };
void stick(int a, inb &b, Direction d); { switch (d) { case Left: break; case Right: break; } // ... }

Заметьте, что enum в версиях C++ до C++11 даёт достаточно слабую типизацию. Например, такой код компилируется:
enum Direction { Left, Right };
enum Direction2 { North = 5, South = 7 };
void f(Direction d) { switch (d) { case North: break; case South: break; } // ... }
Для компилятора все enum'ы — просто числовые константы.
Но начиная с C++11, лучше использовать строго типизированный enum
enum class Direction { //^^^^^ Left, Right };
enum WrongDirection { Left = 1, Right = 0 };
void f(Direction d) { switch (d) { case Direction::Left: // а не WrongDirection::Left break; case Direction::Right: break; } // ... }
Здесь компилятор не даст вам случайно использовать неправильный тип.

Как с помощью стилей добиться треугольных скосов в блоках?

Приветствую! Подскажите плиз, как с помощью стилей добиться таких скосов в блоках как на картинках 1 и 2, причем, чтобы текст мог быть разной высоты - это вообще возможно или с помощью скриптов только?
.tech, .new { background: yellow; width: 200px; margin: 10px 0; }

техника
новинки


Ответ

Вот еще один вариант реализации этой задачи с использованием transform: skew (у тестовых примеров, фигуры подсвечены красным для ясности):
.item { position: relative; display: inline-block; background: #000; color: #fff; padding: 5px 25px; margin: 0 10px 10px 0; } .has_right_arr:after { position: absolute; display: block; content: ''; top: 0; right: -7px; width: 20px; height: 50%; background: #000; -ms-transform: skew(45deg); -webkit-transform: skew(45deg); transform: skew(45deg); } .has_right_arr:before { position: absolute; display: block; content: ''; bottom: 0; right: -7px; width: 20px; height: 50%; background: #000; -ms-transform: skew(-45deg); -webkit-transform: skew(-45deg); transform: skew(-45deg); } .has_right_skew:after { position: absolute; display: block; content: ''; bottom: 0; right: -7px; width: 20px; height: 100%; background: #000; -ms-transform: skew(-25deg); -webkit-transform: skew(-25deg); transform: skew(-25deg); } .debug:after { background: rgba(255, 0, 0, 0.5); } .debug:before { background: rgba(255, 0, 0, 0.5); } Hello world! Debug
Hello everyone! Debug
Hello world!
Hello everyone!
Фиддл: http://jsfiddle.net/IonDen/ey4zek1e/

Как в objective-c передать массив NSString в метод?

В objective-c мне необходимо передать в метод двумерный массив NSString. Я его объявляю NSString *products[10][10];, потом присваиваю какие-то значения, и не могу написать метод, чтобы он принимал его. Компилятор не пропускает такие объявления:
-(void) Array : (NSString *) array[][]; -(void) Array : (NSSting[][] *) array;
А так же охота, чтобы метод возвращал двумерный массив NSString. Т.е. такое тоже не проходит:
-(NSString[][] *) ArrayCount : (int) count;
Помогите, пожалуйста! Как правильно писать такие методы, которые бы принимали и возвращали двумерный массив NSString? Или такое вообще не возможно?


Ответ

Традиционно в ObjC нет двумерных массивов — вместо них используется такое понятие как "массив массивов". То есть массив, каждым элементом которого является другой массив.
Объявить его можно либо:
NSArray *row1 = @[@"string1", @"string2"]; NSArray *row2 = @[@"string3", @"string4"]; NSArray *container = @[row1, row2];
либо:
NSArray *container = @[@[@"string1", @"string2"], @[@"string3", @"string4"]];
и далее вы передаёте в метод массив container
Чтобы получить элемент из массива:
container[0][0];
Так же надо добавить, что поскольку ObjC основан на C, любой C-код будет работать, включая 2D массивы, но тогда и те методы, куда эти массивы передаются надо писать на C.

Привязка к значению false

Таким способом привязываю доступность одного чекбокса к состоянию IsChecked другого: Но мне нужно сделать наоборот, чтобы первый чекбокс становился доступным, когда у второго состояние IsChecked = False. Каким образом это делается в WPF?


Ответ

Вы можете использовать преобразователь значений (класс, реализующий IValueConverter.) Небольшой пример:
public class NegateConverter : IValueConverter {
public object Convert( object value, Type targetType, object parameter, CultureInfo culture ) { if ( value is bool ) { return !(bool)value; } return value; }
public object ConvertBack( object value, Type targetType, object parameter, CultureInfo culture ) { if ( value is bool ) { return !(bool)value; } return value; }
}
Затем добавить его в свой XAML например так:

...

Вопрос переведен отсюда

Получить только число из переменной, содержащей текст + число + текст

Пишу javascript, и есть переменная, в которой хранится нужное мне число. Я бы его вытащил через parseFloat, но проблема в том что оно хранится в таком виде (50%). Т.е перед числом идет символ ( из-за этого parseFloat возвращает NaN. Как мне вытащить в таком случае число?


Ответ

Если строка всегда будет во формате ({число}%), то можно просто удалить первый символ и последные два символа, вот так:
var str = "(50.5%)"; var x = parseFloat(str.slice(1, -2));

Как правильно понять задание с memoization

Как разработать функцию ( аналог Math ) , которая выполняла простые математические операции (сложение, вычитание , умножение , деление) , а предыдущий рассчитанный результат кешировала ( меморизация , мемойз , memoization ) * Хорошо сделать мемойз каждого типа операции ( дилення, умножения ...) ? Я сделал так(мемойз в моем понимании для сложения):
var sumRes, minusRes, multiRes, divRes; var math = function(operation, op1, op2){ var result; switch(operation){ case "+": sumRes = sumRes ? sumRes + op1 + op2: op1 + op2; result = sumRes; break; case "-": minusRes = op1 - op2; result = minusRes; break; case "*": multiRes = op1 * op2; result = multiRes; break; case "/": divRes = op1 / op2; result = divRes; break; default: console.log("The operation must to be only: \"+\", \"-\", \"*\", \"/\""); } return result; }; console.log(math("+", 1, 2)); console.log(math("+", 1, 2)); console.log(math("+", 1, 2)); console.log(math("+", 1, 2));
Но боюсь нужно иначе реализовать((


Ответ

Мемоизация - это сохранение уже вычисленных значений. Когда функция повторно вызывается с теми же аргументами, она должна вернуть готовое значение, не выполняя повторных вычислений.
var calc = (function () { var results = {};
var fs = { '+': function (x, y) { console.log('calculation'); return x+y }, '-': function (x, y) { console.log('calculation'); return x-y }, '/': function (x, y) { console.log('calculation'); return x/y }, '*': function (x, y) { console.log('calculation'); return x*y } };
return function calc(op, x, y) { return results[x+op+y] = results[x+op+y] || fs[op](x,y); } })();
Естественно, console.log('calculation'); надо убрать - он здесь для демонстрации того, что вычисление происходит только единожды.
Самовызывающаяся функция нужна для того, чтобы сделать переменные results и fs приватными для функции calc

Настройка шаблонов в Eclipse/Netbeans, как в IDEA

Добрый день, комьюнити! Вчера меня взяли на работу Java программистом (мой первый опыт). До этого я всегда разрабатывал в IDEA, но работодатель сказал выбираться между eclipse и netbeans. Открыв эти среды я ужаснулся, там нет нормального автодополнения. Те например в IDEA я пишу psvm - и она мне генерирует public static void main метод, или sout и это будет System.out.println и т.д.
Я уверен, что не один с такой проблемой, может подскажите какие-то плагины, которые могли бы из Eclipse/Netbean сделать мою любимую IDEA? Заранее ОЧЕНЬ благодарен.


Ответ

Preferences -> Java -> Editor -> Templates -> New:

После этого в коде пишите psvm и нажмите Ctrl-Space

Именованные функциональные выражения (Named Function Expression)

Что выведется в консоль при выполнении этого кода? Почему?
(function test() { test = 123; console.log( test ); }())
В консоль выведется эта функция:
function test() { test = 123; console.log( test ) ;}
Почему так происходит?


Ответ

Согласно этой статье, перезаписать имя NPE, доступное внутри самого NPE и используемое для рекурсивного вызова (вместо устаревшего arguments.callee), нельзя. В MDN, к сожалению, про запрет переписывания ничего не сказано, однако практика (ваш пример) говорит о том, что это всё же верное утверждение.
Поэтому test = 123; не даёт никакого эффекта, и console.log выводит первоначальное значение test - само NPE.

Чем чревато отсутствие обработки OperationCanceledException у Task?

Чем может быть чреват такой вот Task с необработанным исключением отмены действия, если далее я к нему нигде не обращаюсь?
public static void Main() { var cts = new CancellationTokenSource(TimeSpan.FromSeconds(10)); Task.Run(() => SomeMethod(cts.Token), cts.Token); }
public static void SomeMethod(CancellationToken token) { while (true) { token.ThrowIfCancellationRequested(); // Некая трудоемкая операция Thread.Sleep(TimeSpan.FromMilliseconds(100)); } }
UPDATE1: После ответа andreycha я решил проверить, как работает ловля ошибок у Task. И я заметил, что исключение отмены не доходит до глобального обработчика и никак не вешает систему. В кофиг файле прописал:

Код:
public static void Main() { TaskScheduler.UnobservedTaskException += (object sender, UnobservedTaskExceptionEventArgs eventArgs) => { Console.WriteLine("Task error"); eventArgs.SetObserved(); (eventArgs.Exception).Handle(ex => { Console.WriteLine("Exception type: " + ex.GetType()); return true; }); };
CancellationTokenSource cts = new CancellationTokenSource(1000); Task.Factory.StartNew(() => { Console.WriteLine("Enter"); while (true) { cts.Token.ThrowIfCancellationRequested(); Thread.Sleep(100); } }, cts.Token); Task.Factory.StartNew(() => { throw new Exception("Some exception"); });
Thread.Sleep(4000); Console.WriteLine("Collecting"); GC.Collect(); GC.WaitForPendingFinalizers();
Console.ReadLine(); }
Пример вывода:
Task error Exception type: System.Exception
Выходит, что если тебе никак не надо обработать отмену операции, то можно в обще ничего не делать и ничего не будет все таки?


Ответ

Если приложение работает под .NET Framework 4 (или под .NET Framework 4.5+ с включенной опцией ThrowUnobservedTaskExceptions), то когда сборщик мусора доберется до этого таска, финализатор выбросит исключение и приложение упадет.
В .NET Framework 4.5+ поведение изменили и приложение продолжит работать (а само исключение по-прежнему можно отловить в обработчике UnobservedTaskException). Необработанное исключение ничему не помешает.

Однако я бы рекомендовал всегда обзервить таски, иначе вы не узнаете, завершился ли таск успешно или нет и завершился ли вообще. В 99% случаев unobserved task -- это ошибка. Отследить завершение можно разными способами (зависит от вашей текущей архитектуры по большей степени):
1) Если вы уже используете async/await, тогда ожидайте так:
var task = Task.Run(() => SomeMethod(cts.Token), cts.Token); try { await task; } catch (OperationCanceledException) { // задача была отменена } catch (Exception) { // другая ошибка }
2) Если ваш код полностью синхронный, то можно использовать либо продолжения, либо синхронное ожидание.
Вариант с продолжением. Помните о том, что продолжение выполняется в том же контексте, что и оригинальный таск (т.е. в потоке из пула потоков). А значит обращаться напрямую к компонентам UI, например, нельзя.
Task.Run(() => SomeMethod(cts.Token), cts.Token) .ContinueWith(SomeMethodHandler, TaskContinuationOption.OnlyOnFaulted); ... private void SomeMethodHandler(Task task) { if (task.Exception is OperationCanceledException) { // задача была отменена } else { // другая ошибка } }
Вариант с синхронным ожиданием. Тут надо быть аккуратным с тем, в каком конкретно месте вы ожидаете. Поскольку внутри SomeMethod у вас бесконечный цикл, то на строке task.Wait() приложение будет висеть до тех пор, пока задача не будет отменена
var task = Task.Run(() => SomeMethod(cts.Token), cts.Token); try { task.Wait(); } catch (AggregateException e) { // синхронное ожидание, в отличие от await, не "разворачивает" исключения // проверяем e.InnerExceptions на предмет наличия OperationCanceledException }

P.S. Если же говорить о коде, который вы привели, то он завершит свое выполнение почти моментально, не успев произвести нужную работу. Потому что таск никто не ожидает.

Каким образом Iterable может хранить объекты?

Есть сигнатура метода: Iterable incoming(Iterable tasks, Date start, Date end).
Метод предназначен для хранения Taskов которые выполняются в промежутке между start и end
Вопрос: Каким образом работает Iterable. Что хранит?


Ответ

Iterable - это интерфейс. Он в себе ничего не хранит, он предоставляет собой поведение. В данном случае, поведение - это перебор элементов. Это если совсем кратко. Рекомендую почитать статью с хабры на эту тему.
Сигнатура метода Iterable incoming(Iterable tasks, Date start, Date end) говорит о том, что в качестве первого аргумента будет поставляться коллекция, параметризованная типом Task и которая имплементирует интерфейс Iterable. Далее у этой коллекции можно будет взять iterator, т.к. этот метод объявлен в интерфейсе Iterable, с помощью которого можно будет обойти пришедшую коллекцию

Как выбрать нужную кнопку

Существую цикл из определенного количества аннотаций, при каждой аннотации добавляется кнопка на вью, как после добавления всех кнопок в коде выбрать нужную?
Пример
for (int i = 0; i < 5; i++) {
UIButton * testView2 = [[UIButton alloc] initWithFrame:CGRectMake(20, hightArray1 + 90 + 37 * i, 280, 35)]; testView2.backgroundColor = [UIColor whiteColor]; testView2.layer.cornerRadius = 5.f; testView2 addTarget:self action:@selector(actionTestView1) forControlEvents:UIControlEventTouchUpInside]; [self.mainScrollView addSubview:testView2]; }


Ответ

Я бы сказал, что использовать viewWithTag в этом случае не очень хорошо. В этом случае вы фактически используете view для хранения model, что неправильно в рамках MVC паттерна. Лучше было бы создать массив и в него сложить все UIButtons, и потом их получать по индексу:
UIButton *myButton = (UIButton*)buttonArray[index];

Конструктор

Хочу написать конструктор класса, который в качестве параметра принимает статический массив (указатель на 1 элемент) и инициализирует вектор внутри класса этим массивом:
class A { public: explicit A(int x[]):v(x,x+sizeof(x)/sizeof(*x)) {} // или (int* x) private: vector v; };
Не работает... В чём проблема?


Ответ

Параметр вашего конструктора имеет тип int *. Поэтому выражение
sizeof(x)/sizeof(*x)
эквивалентно выражению
sizeof( int * )/sizeof( int )
И может равняться либо 2, если размер указателя равен, например, 8 байтам, а размер объекта типа int равен 4 байтам, либо 1, если данные размеры совпадают.
Лучше объявить два перегруженных конструктора.
Первый конструктор может быть определен как
A( const int *first, const int *last ) : v( first, last ) {}
а второй конструктор может быть определен либо как
A( const int *first, size_t n ) : v( first, first + n ) {}
либо использовать делегирующий конструктор
A( const int *first, size_t n ) : A( first, first + n ) {}
Также вы можете объявить шаблонный конструктор, как, например,
template A( const int ( &a )[N] ) : v( a, a + N ) {}
Вот демонстрационная программа, в которой показаны все три способа вызова конструкторов класса
#include #include
struct A { A( const int *first, const int *last ) : v( first, last ) {} A( const int *first, size_t n ) : v( first, first + n ) {} template explicit A( const int ( &a )[N] ) : v( a, a + N ) {}
std::vector v; };
int main() { int a[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
A a1( a, a + sizeof( a ) / sizeof( *a ) );
for ( int x : a1.v ) std::cout << x << ' '; std::cout << std::endl;
A a2( a, sizeof( a ) / sizeof( *a ) );
for ( int x : a1.v ) std::cout << x << ' '; std::cout << std::endl;
A a3( a );
for ( int x : a1.v ) std::cout << x << ' '; std::cout << std::endl; }
Ее вывод на консоль
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9

Возможно ли в переменную записать что угодно? C++

Допустим, пользователь должен ввести 2 аргумента, которые передадутся шаблону-функции, которая принимает любой тип данных, там их меняет местами и выводит на экран... Изи. Но... Как сделать так, чтобы пользователь через консоль мог вводить что угодно. Скажем 1, 2. Или 5.2, 7.3 Или a, b. Ведь то что он ввел, записывается в переменную. А переменная имеет свой тип. И если она int, то пользователь не сможет ввести символ.


Ответ

Входные данные вы получаете в виде строки. Тут без вариантов. Т.к. динамической типизации в C++ нет и вы не знаете заранее (по условию нужно чтобы мог вводить что угодно), что вам ввёл пользователь - этапа определения типов введённых данных не избежать. Вам для каждого аргумента надо определить, а не int ли это, или double. И в зависимости от результатов такой проверки уже решаете какую операцию применить к аргументам.
Если они приводимы к числу. т.е. оба int или double, или один int а второй double то вы их складываете. Если хотя бы один из них не приводим к числу-работаете как со строками.
Детали реализации это уже вкусовщина. Можно определять сразу после получения аргументов и, в зависимости от результатов проверки вызывать нужную функцию которая проведёт операцию и вернёт результат (можно и без функци обойтись) Можно после ввода вызывать функцию принимающую 2-а string'а и осуществляющую проверку и операции в теле функции. А можете создать класс наследуемый от string'a (сответственно чтоб его экземпляр можно было инициализировать строкой) и перегрузить в нём операцию "+". Тогда проверки и нужные операции будут выполняться в теле перегруженного метода.

Зачем нужны классы для PDO

Я вот думаю стоит ли подключать в свою cms класс для работы с базой, например этот https://github.com/indieteq/PHP-MySQL-PDO-Database-Class или не стоит. Посмотрев на использование этого класса я понял, что в PDO уже есть всё тоже самое, так зачем переписывать его?
Например:
// 1. Read friendly method $db->bind("id","1"); $db->bind("firstname","John"); $person = $db->query("SELECT * FROM Persons WHERE firstname = :firstname AND id = :id");
тоже самое что и:
$stmt->bindParam(1, $name);
Можете разжевать мне пожалуйста?


Ответ

99% классов для PDO не нужны.
Потому что PDO - уже класс, и чтобы его улучшить, нужно быть очень хорошим программистом. Обычно же писать обертки для PDO берутся криворукие нубы, которые не умеют работать с PDO, не знают азов программирования, и в итоге получают кривого монстра, который приносит больше вреда чем пользы.
Этот класс - как раз пример такого подхода.
он логирует ошибки (чего делать не должен). Ошибками должен заниматься централизованный обработчик. он пишет в браузер какую-то ересь про лог файл, чего делать не должен вообще никогда. С какой радости посетитель сайта должен что-то там смотреть в лог файле?! Такие надписи - индикатор того, что перед нами нуб, не сделавший ни одного проекта. Иначе бы он понимал, что в браузер пишется информация для посетителя, а не для программиста. он НЕ "держит соединение", в том смысле что он не гарантирует, что на протяжении скрипта будет использоваться единственное соединение с БД. Как раз наоборот - из примеров видно, что автор предлагает создавать класс каждый раз заново, создавая и новое соединение с БД. В итоге в скрипте будет столько соединений, сколько будет потомков класса CRUD (обычно это десятки). он дублирует функционал PDO, который автор не осилил изучить, к примеру функция column(). он ломает функционал PDO, добавляя какой-то ад в виде utf8_encode($value); - то есть тупо портит входящие данные. вместо того, чтобы упростить синтаксис PDO, автор его усложняет. К примеру, PDO поддерживает позиционные плейсхолдеры, которые в большинстве случаев позволяют значительно сократить писанину и не повторять, как второгодник, одно и то же слово по пять раз. Здесь же их использовать невозможно. не понимая азов программирования, автор совершает классическую ошибку всех нубов: он смешивает в одном классе функционал, работающий как с соединением в целом, так и с отдельным запросом. Чего делать категорически нельзя, а делать надо беря пример с PDO: отдельный объект для соединения и отдельные объекты для каждого запроса. Это единственно правильный подход. Первый же запрос внутри цикла обработки другого запроса поставит этот класс в очень неприятную позу.
Что характерно, предыдущие ораторы, похоже, считают всё это достоинствами.
Вам я порекомендую сначала освоить PDO, и научиться им пользоваться, понять его сильные и слабые стороны. К примеру, как правильно "держать соединение": либо передавать везде переменную с единственным инстансом класса, либо использовать некий сервис, который будет хранить этот инстанс и выдавать его по запросу; как получать данные сразу в нужном формате не прибегая к криворуким поделиям; как правильно работать с ошибками (в общем случае - никак не надо, PHP прекрасно справляется сам).
После этого можно будет либо писать свой класс, либо поискать чужой, но уже такой, который не несет больше вреда, чем пользы.
Либо, как говорилось выше, вместо библиотеки для одной только работы с БД, взять "библиотеку", которая упрощает еще сотню вещей - от разбора входных параметров до отправки писем - фреймфорк. Для этого обязательно прочесть вот эту статью, но учить после неё не Symfony, а Laravel, который на ней базируется.

Объявление объекта класса

В классе A есть конструктор по умолчанию и конструктор с 1 параметром.
При таком A x(); и таком A x; объявлениях объекта класса A выполняются разные действия. Почему?


Ответ

A x(); - это объявление функции x которая возвращает результат с типом A
В Си и С++ функции можно объявлять в т.ч. и внутри функций, например
int main() { int f(); // объявили функцию, которая будет определена ниже. return f(); }
int f() { return 0; }
Чтобы объявить переменную, используйте фигурные скобки:
A x{};
Или просто используйте A x;

Java. Задание занчения (final) переменной в try-блоке и ее дальнейшее использование и видимость

Проблема заключается в необходимости задания значения final переменной (connectionSocket2) в try-блоке. В дальнейшей части кода (в части run()) этого не видно и возникает как бы ошибка, что та переменная не определена:
final Socket connectionSocket; try { connectionSocket = welcomeSocket.accept(); }
The local variable connectionSocket2 may not have been initialized
убрать final не могу, так как (в части run()) дает ошибку
Cannot refer to the non-final local variable connectionSocket defined in an enclosing scope
Socket connectionSocket2=null; try { connectionSocket2 = welcomeSocket.accept(); } catch (IOException e2) { e2.printStackTrace(); } final Socket connectionSocket=connectionSocket2; try{connectionSocket2.close();}catch(IOException e1){e1.printStackTrace();}
service.submit(new Runnable() { public void run() { while (true) { BufferedReader inFromClient=null; DataOutputStream outToClient=null; try{ inFromClient = new BufferedReader(new InputStreamReader(connectionSocket.getInputStream())); outToClient = new DataOutputStream(connectionSocket.getOutputStream()); outToClient.writeBytes(inFromClient.readLine()); } catch(IOException ioe) {} }}});
Статической делать не могу - для каждого потока создается свое соединение, как бы свой экземпляр этой переменной.
Приведенный код работает, использовал вторую переменную для передачи ей значения и дальнейшего использования именной второй переменной. Но это выглядит плохо.
Как правильно, профессионально быть в этой ситуации? Модно ли как-то сказать компилятору, что переменная на самом деле уже определена в try блоке и ему нечего "волноваться"? (типа динамическая переменная, как в .Net)


Ответ

Ответ-вопросник и очередной наброс на медальку.
Итак, у вас было что-то вот такое:
public class ICanIntoSockets {
public static void main( String[] args ) throws IOException { ServerSocket welcomeSocket = new ServerSocket(10000); ExecutorService service = Executors.newCachedThreadPool();
doWork( welcomeSocket, service ); }
public static void doWork( ServerSocket welcomeSocket, ExecutorService service ) { try { while (true) { final Socket connectionSocket = welcomeSocket.accept();
service.execute( () -> { try ( Socket socket = connectionSocket; BufferedReader inFromClient = new BufferedReader( new InputStreamReader(socket.getInputStream())); DataOutputStream outToClient = new DataOutputStream( socket.getOutputStream())) {
outToClient.writeBytes(inFromClient.readLine()); } catch (IOException ioe) { ioe.printStackTrace(); } }); } } catch ( IOException ex ) { ex.printStackTrace(); } } }
но try - плохо, и торморзит на тысячах подключений (тесты где?), поэтому вы решили от него избавиться. Ява - убогий язык, в ней зачем-то придумали Checked Exceptions и напихали во все места в стандартной библиотеке, поэтому совсем без try - никак:
public static void doWork( ServerSocket welcomeSocket, ExecutorService service ) { while (true) { final Socket connectionSocket; try { connectionSocket = welcomeSocket.accept(); } catch (IOException ex) { ex.printStackTrace(); }
service.execute(() -> { try ( Socket socket = connectionSocket; // The local variable connectionSocket may not have been initialized BufferedReader inFromClient = new BufferedReader( new InputStreamReader(socket.getInputStream())); DataOutputStream outToClient = new DataOutputStream(socket.getOutputStream())) {
outToClient.writeBytes(inFromClient.readLine()); } catch (IOException ioe) { ioe.printStackTrace(); } }); } }
Зло загнано в угол в одной строчке кода! Но компилятор почему-то считает, что переменная connectionSocket может быть не инициализирована. Почему? Потому что есть путь выполнения программы, при которой она действительно не инициализируется: когда welcomeSocket.accept() выбрасывает исключение. Метод не возвращает значение - значение переменной не присваивается. Что же делать?
Не надо продолжать выполнение итерации, ваш код все равно не сможет работать дальше без клиентского сокета. Сделайте внутри catch-блока return, break, continue (в надежде, что следующий accept не выбросит исключение, что вряд ли). Если код непременно должен продолжаться дальше - присвойте connectionSocket null и где-то сделайте проверку.
Предложенный вариант с массивом - это либо то самое создание объектов и выделение памяти, с которым вы сражаетесь, либо потеря подключений и обработка одного подключения несколько раз, смотря где вы этот массив объявите.

Значения по умолчанию для полей в БД

Есть поле типа int которое может иметь а может не иметь значение.
Какое значение по умолчанию будет правильнее использовать в данной ситуации?
NULL нельзя,а если 0 то это может быть primary key в другой таблице.


Ответ

Раз у вас таблица (T1) хранит некое значение, которое в другой таблице (T2) является primary key, то установка некого специального значения отличного от NULL и не находящегося в T2 это странное решение. Оно конечно имеет право на жизнь, но используется в очень экзотических случаях.
В базах данных, при связи двух таблиц, значение NULL как раз используется для отражения факта отсутствия какого либо значения и, следовательно, необходимости такой связи у записи.
В реляционных базах данных рекомендуется делать внешние ключи (foreign key) для отражения связи двух таблиц. Наличие такого foreign призвано для обеспечения ссылочной целостности БД. Он не позволяет существовать в подчиненной таблице значениям, не существующим в основной таблице. При этом внешний ключ позволяет существовать NULL значению - как раз для отражения факта отсутствия связи.
Рекомендуемая структура таблиц (Отделы и сотрудники):
create table DEPT ( DEPT_ID INT not null auto_increment, DEPT_NAME VARCHAR(100), primary key (DEPT_ID) ) engine = InnoDB;
create table PERSON ( PERSON_ID INT not null auto_increment, NAME VARCHAR(100) not null, DEPT_ID INT, primary key (ID), FOREIGN KEY (DEPT_ID) REFERENCES DEPT(DEPT_ID) ) engine = InnoDB;
При отсутствии у сотрудника отдела к которому он относится DEPT_ID должен быть NULL

Rust. Проблема с многопоточностью

Пытаюсь освоить многопоточность в Rust. Прошу ответить на несколько вопросов. Читаю перевод Rustbook.
Мы оборачиваем данные в sync::Mutex, когда хотим использовать эти данные (эту переменную) в других потоках, чтобы не было "гонки данных"? То есть оборачиваем в Mutex, а там уже когда используем, то lock() и все остальные "становятся в очередь"? Я сейчас о примере с Rustbook:
use std::sync::{Arc, Mutex}; use std::thread; fn main() { let data = Arc::new(Mutex::new(vec![1u32, 2, 3])); for i in 0..3 { let data = data.clone(); thread::spawn(move || { let mut data = data.lock().unwrap(); data[i] += 1; }); } thread::sleep_ms(50); }
Какие-то странные и непонятные действия. Ну, хорошо, связали data с вектором, который обернут в Mutex, но зачем ещё в Arc? Внутри цикла зачем-то делаем копию и связываем с data, потом уже в замыкании опять новая переменная data. Объясните пожалуйста.
Моя попытка сделать десять потоков и в каждом из них прибавлять по единице к data. Неработающая попытка:
use std::thread; use std::sync::{Arc, Mutex};
fn main() { let mut data = Arc::new(Mutex::new(0));
let handles: Vec<_> = (0..10).map(|_| { thread::spawn(move|| { data.lock(); data += 1; //binary assignment operation `+=` cannot be applied to type `alloc::arc::Arc> }) }).collect();
for h in handles { h.join(); }
}
Почему опять ему (компилятору) не нравится?


Ответ

В книге очень подробно разобран этот пример с вариантами что будет без мьютексов и что будет без Arc:
Arc - является атомарным указателем со счетчиком ссылок. «Атомарный» означает, что им безопасно обмениваться между потоками. Чтобы гарантировать, что его можно безопасно использовать из нескольких потоков, Arc предполагает наличие еще одного свойства у вложенного типа. Он предполагает, что T реализует типаж Sync. В нашем случае мы также хотим, чтобы была возможность изменять вложенное значение. Нам нужен тип, который может обеспечить изменение своего содержимого лишь одним пользователем одновременно. Для этого мы можем использовать тип Mutex
Единственное что там вводит в заблуждение - используется затенение переменных, так что там три разных переменных с одинаковым именем data
Вот рабочий код вашего примера:
use std::thread; use std::sync::{Arc, Mutex};
fn main() { let data = Arc::new(Mutex::new(0));
let handles: Vec<_> = (0..10).map(|_| { let xd = data.clone();// (1) thread::spawn(move|| { let mut x = xd.lock().unwrap();// (2) *x+=1;// (3) }) }).collect();
for h in handles { h.join(); }
println!("{:?}",data) }
По пунктам что было не так:
Вы пытаетесь непосредственно обратиться к переменной data. Так как для типа Arc не реализован типаж неявного копирования Copy, то первый же поток захватит право владения переменной и она будет недоступна для остальных потоков (и для основного тоже). Поэтому используется явное клонирование указателя data.clone() Функция lock() возвращает специальный объект MutexGuard дополнительно завернутый в LockResult. Когда этот объект будет освобожден защелка будет отпущена. Поэтому результат возвращаемый lock() нужно сохранить в переменную. unwrap() вытаскивает MutexGuard из LockResult. К тому же этот объект нужен для доступа к самим данным. Для доступа к данным внутри MutexGuard нужно разыменовать то что мы получили в п.2.

Как устроен и работает предикат?

Не могу разобраться как устроен и работает предикат. Вот простенький пример использования предиката в сортировке:
#include #include #include
using namespace std;
bool mySort(int x, int y){ // функция будет использоваться в качестве предиката return x < y; }
int main (){ vector va;
va.push_back(10); va.push_back(100); va.push_back(2);
// for (vector::iterator it = va.begin(); it != va.end(); it++) // cout << *it << endl;
sort(va.begin(), va.end(), mySort); //третий параметр является предикатом
// cout << endl;
// for (vector::iterator it = va.begin(); it != va.end(); it++) // cout << *it << endl;
return 0; }
мне непонятно почему обычная функция рассматривается как предикат и почему в фунции-предиката два параметра, а не три к примеру и имеют целый тип параметров


Ответ

std::sort третьим параметром принимает что-то, что можно вызвать как функцию имеющую 2 параметра(полный список требований можно посмотреть тут). Не 3, не 1 — именно 2. Почему 2? Потому что для сортировки, за одну операцию, нужно сравнить именно 2 элемента.
Теперь касательно типа параметров: чтобы корректно сравнить 2 элемента массива, тип параметров функции должен быть совместим с типом элементов массива. Поэтому у Вас в коде и используется int. Но можете использовать и long и любой другой тип, который даст корректный результат сравнения. Но вот если Вы сделаете параметры функции, к примеру, типа std::string, то получите ошибку компиляции.

Для лучшего пониманию, предлагаю рассмотреть следующий пример:
#include
void myFunc(int x, int y) { std::cout << "x: " << x << ", y:" << y << "
"; }
template void superFunction(Fun fun) { fun(156, 11); }
int main(int argc, char* argv[]) { superFunction(myFunc); }
Здесь, superFunction чем-то похожа на std::sort, она принимает своим аргументом что-то, что можно вызвать с двумя параметрами, причём каждый параметр является int. Внутри это «что-то» вызывается. Передав в функции main нашу myFunc мы получаем вызов оной, косвенно, через superFunc. Точно так же всё происходит в std::sort, только там переданная функция используется для сравнения двух элементов и в эту функцию передаются два члена массива, вместо констант, как в моём коде.