Страницы

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

пятница, 14 декабря 2018 г.

Каким способом лучше указывать путь к файлу в программе на языке Java? Где лучше хранить используемые программой файлы?

Можно прописать абсолютный путь к файлу, скажем вот так:
Image img = new ImageIcon("G:\\img.png").getImage();
Насколько я понимаю, так делать совсем плохо, ибо мы не знаем, куда пользователь сохранит нашу программу.
Можно прописать относительный путь к файлу, скажем вот так:
Image img = new ImageIcon("img.png").getImage();
Но тогда (если только я правильно понял из проделанных экспериментов) чтобы получить полный путь к файлу JVM делает "конкатенацию" текущей директории с прописанным относительным путём. Т.е. если я запускаю программу такой командой:
G:\program\bin>java -jar Program.jar
То JVM будет искать файл по такому расположению:
G:\program\bin\img.png
Насколько я понимаю, так делать совсем плохо, ибо мы не знаем, с какой директории будет запускать пользователь нашу программу.
Можно делать что-то вообще интересное и непростое, типа такого:
Image img = new ImageIcon( this.getClass().getResource("img.png") ).getImage();
Здесь поиск файла будет происходить из пакета, где находится класс this.getClass(). (т.е. та самая "конкатенация" происходит с путём к пакету класса)
Но ведь наверное плохо мешать файлы классов с файлами ресурсов?
Или даже так:
Image img = new ImageIcon( this.getClass().getResource("/img.png") ).getImage();
Здесь поиск файла происходит в директориях classpath. Но по идее, тогда может оказаться несколько подходящих файлов? И что же это будет?!
В общем вопросы: Правильно ли то, что я написал? Какие ещё способы существуют? Когда какой способ использовать? Какой способ наилучший (если он существует)?


Ответ

Общим ответом на это будет просто слово "зависит" - главный вопрос в том, с чем вы работаете. Как правило, java-приложения распространяются в виде jar-архивов, и если у вас есть распространяемые с приложением ресурсы (например, иконки), то они должны либо оказаться именно там, среди классов, либо, если вы распространяете приложение в виде архива и отдельных ресурсов снаружи архива, то вам нужно самому находить расположение jar-файла и вручную восстанавливать путь к ресурсом по аналогии с working directory. В случае, если вы пишете некоторую утилиту, которая обрабатывает аргументы, то вам, скорее всего, придется иметь дело из абсолютными, и с относительными путями - если вы пишете, скажем, ресайзер изображений, то вызов java -jar path/resizer.jar image.png 300x400 потребует простого проброса аргумента внутрь ImageIcon напрямую, без вообще какого-либо анализа.
Другими словами, все описанные методы имеют свое применение, и являются более или менее предпочтительными в зависимости от ситуации; каждый из них не чем-то плох, а неприменим в текущей ситуации. Если вопрос заключается в поиске ресурсов приложения, то лучше всего либо закидывать в jar, либо искать место установки приложения и отсчитывать от него (т.к. working dir может оказатсья любым).

Поиск наиболее часто встречающегося вложенного списка с одинаковыми элементами

Есть список с вложенными списками. Нужно найти наиболее часто встречающийся список.
Пример:
Input:
[[1,2,3],[2,5,6],[8,2,1],[2,3,1]]
Output:
[1,2,3] -> 2 шт
Списки [1,2,3] и [2,3,1] cчитаются равными.


Ответ

Одной строкой (не считая импорта, инициализации s и вывода):
from collections import Counter s = [[1,2,3],[2,5,6],[8,2,1],[2,3,1]] sublist, count = max(Counter(tuple(sorted(x)) for x in s).items(), key=lambda x: x[1]) print('%s -> %d' % (list(sublist), count))
Разбор:
Превращаем s в набор сортированных кортежей (неизменяемых списков, по сути). Сортируем потому, что по условию списки различающиеся только порядком одинаковы, а после сортировки они становятся полностью совпадающими. Преобразование в кортеж нужно потому, что Counter из следующего пункта может считать только хешируемые объекты (списки к таким объектам не относятся, а вот кортежи - да): (tuple(sorted(x)) for x in input) Отправляем это в Conter, получаем объект, в котором подсчитано, сколько каждый объект, в переданном ему "списке" (вообще, итерируемом объекте) встретился: Counter(...). Если на этом этапе вывести полученное значение, будет что-то вроде Counter({(1, 2, 3): 2, (1, 2, 8): 1, (2, 5, 6): 1}) Извлекаем из Counter пары (ключ, значение) (ключ - объект, значение - количество), находим элемент с максимальным значением количества: max(Counter(...).items(), key=lambda x: x[1]). Метод .items() как раз превращает Counter в набор пар (ключ, значение). Параметр key=lambda x: x[1] функции max говорит, что нужно отбирать максимальное по второму элементу каждой пары. "Распаковываем" полученный элемент (пару подсписок-количество) в переменные sublist и count: sublist, count = max(...) Выводим в виде "[список] -> количество", подсписок показываем в виде списка (а не кортежа): print('%s -> %d' % (list(sublist), count))
Вывод:
[1, 2, 3] -> 2
Ограничения:
Изначальный список должен иметь хотя бы один подсписок. При выводе подсписок список всегда будет отсортированным, независимо от того, каким он был в исходном списке. Если в исходном списке несколько подсписков, встречающихся наиболее часто, в результате будет показан только один из них.

ASP.NET Identity VS Самописная система авторизации

Может показаться что это очень "холиварный" вопрос, но я всё же задам его.
Начинал писать свою систему ещё тогда, когда был в моде ASP.NET Membership. Ну естественно, гибкости мне далеко не хватало и я решил писать свою систему авторизации, не опираясь на какие-то устоявшиеся в те времена принципы разработки авторизационных/аутентификационных систем. Что примерно из себя напоминает система сейчас:
Отдельный контекст (мало ли что в жизни бывает); CodeFirst - реализация; Хранение токена сессии в кукисах и сравнение его с токеном в отдельной таблице в БД. Авторизационные фильтры типа ([IdentityFilter("admin", "user", "manager")]) и типа ([IdentityFilter(RolesEnum.Manager)]). На выбор ;) Репозиторий. Авторизационная информация получается в фильтре и далее гуляет в HttpContext`e. Ну и много других мелочей.
Так вот, как бы работает быстро, но что то подсказывает мне, что можно ещё быстрее.
Собственно хотелось узнать, какие преимущества может нести для меня Identity и целесообразно ли его использование в "реальном продакшне", или же это интерфейс для новичков, и для тех, кто не хочет парится.
Ведь в моём коде для меня нет никаких ограничений, а вот в Identity ограничения всё таки есть, хотя бы то же самое именование таблиц и полей по умолчанию.
P.S. Прошу очень развёрнутый, и тем более аргументированный ответ. Заранее спасибо!


Ответ

Membership забыл как страшный сон, перешел на Identity
Нужна простая авторизация без лишней возни? - пожалуйста. Добавил подсистему и забыл. Нужно использовать Claims? - пожалуйста. Не нужно? - можно добавить в любой момент, а до тех пор хранить все основной таблице. А Claims так и будет ждать своего часа. Нужно добавить авторизацию через соцсети? - пожалуйста. Не нравятся именование полей или самой таблицы? - можно все переименовать. Нужно добавить новое поле? - пожалуйста. Автоматическая миграция, ничего не нужно удалять или бэкапить. Необходима двухфакторная аутентификация с подтверждением по смс или электронной почте? - Всё есть, просто добавить необходимые службы. Дополнительные требования к логинам и паролям? - орудия пыток на выбор:
AllowOnlyAlphanumericUserNames, RequireUniqueEmail // ------------------- RequiredLength = 6, RequireNonLetterOrDigit = false, RequireDigit = false, RequireLowercase = false, RequireUppercase = false
и т.д. и т.п.
Проще в студии загрузить готовый шаблон и поковырять его пару вечерков, чтобы точно убедиться подходит ли Identity для своих нужд. Для загрузки рабочего примера с комментариями в консоли пишем «Install-Package Microsoft.AspNet.Identity.Samples -Pre»
Update
Если нужно простое, гибкое, функциональное и готовое решение - Asp.net Identity подойдет. Все в коробке. Если необходимо реализовывать сложные сценарии: глубокие политики безопасности, одновременная аутентификация по Active Directory, сертификатам, токенам, онлайн формам (как на всех сайтах), то советую обратить внимание на Windows Identity Foundation. Придется несколько попотеть.

Квадратные ячейки Grid

Как сделать чтобы ячейки Grid были всегда квадратные?


Ответ

Немного другое идеологически решение — декоратор, размер которого не ограничен, но который заставляет свой дочерний элемент сохранять нужную пропорцию сторон.
Код украден отсюда
public class AspectRatioDecorator : Decorator { #region dp double AspectRatio with validator ValidateAspectRatio public static readonly DependencyProperty AspectRatioProperty = DependencyProperty.Register( "AspectRatio", typeof(double), typeof(AspectRatioDecorator), new FrameworkPropertyMetadata( 1.0, FrameworkPropertyMetadataOptions.AffectsMeasure), ValidateAspectRatio);
public double AspectRatio { get { return (double)GetValue(AspectRatioProperty); } set { SetValue(AspectRatioProperty, value); } }
static bool ValidateAspectRatio(object value) { if (!(value is double)) return false;
var aspectRatio = (double)value; return aspectRatio > 0 && !double.IsInfinity(aspectRatio) && !double.IsNaN(aspectRatio); } #endregion
#region dp HorizontalAlignment HorizontalChildAlignment public HorizontalAlignment HorizontalChildAlignment { get { return (HorizontalAlignment)GetValue(HorizontalChildAlignmentProperty); } set { SetValue(HorizontalChildAlignmentProperty, value); } }
public static readonly DependencyProperty HorizontalChildAlignmentProperty = DependencyProperty.Register( "HorizontalChildAlignment", typeof(HorizontalAlignment), typeof(AspectRatioDecorator), new FrameworkPropertyMetadata( HorizontalAlignment.Center, FrameworkPropertyMetadataOptions.AffectsArrange), ValidateHorizontalChildAlignment);
static bool ValidateHorizontalChildAlignment(object value) { if (!(value is HorizontalAlignment)) return false;
var horizontalAlignment = (HorizontalAlignment)value; return horizontalAlignment != HorizontalAlignment.Stretch; } #endregion
#region dp VerticalAlignment VerticalChildAlignment public VerticalAlignment VerticalChildAlignment { get { return (VerticalAlignment)GetValue(VerticalChildAlignmentProperty); } set { SetValue(VerticalChildAlignmentProperty, value); } }
public static readonly DependencyProperty VerticalChildAlignmentProperty = DependencyProperty.Register( "VerticalChildAlignment", typeof(VerticalAlignment), typeof(AspectRatioDecorator), new FrameworkPropertyMetadata( VerticalAlignment.Top, FrameworkPropertyMetadataOptions.AffectsArrange), ValidateVerticalChildAlignment);
static bool ValidateVerticalChildAlignment(object value) { if (!(value is VerticalAlignment)) return false;
var verticalAlignment = (VerticalAlignment)value; return verticalAlignment != VerticalAlignment.Stretch; } #endregion
protected override Size MeasureOverride(Size constraint) { if (Child == null) // we have no child, so we need no space return new Size(0, 0);
constraint = SizeToRatio(constraint, false); Child.Measure(constraint);
if (double.IsInfinity(constraint.Width) || double.IsInfinity(constraint.Height)) return SizeToRatio(Child.DesiredSize, true);
return constraint; }
public Size SizeToRatio(Size size, bool expand) { double ratio = AspectRatio;
double height = size.Width / ratio; double width = size.Height * ratio;
if (expand) { width = Math.Max(width, size.Width); height = Math.Max(height, size.Height); } else { width = Math.Min(width, size.Width); height = Math.Min(height, size.Height); }
return new Size(width, height); }
protected override Size ArrangeOverride(Size arrangeSize) { if (Child == null) return arrangeSize;
var constrainedSize = arrangeSize;
var fwChild = Child as FrameworkElement; if (fwChild != null) { constrainedSize.Height = Math.Min(constrainedSize.Height, fwChild.MaxHeight); constrainedSize.Width = Math.Min(constrainedSize.Width, fwChild.MaxWidth); }
var newSize = SizeToRatio(constrainedSize, false);
double widthDelta = arrangeSize.Width - newSize.Width; double heightDelta = arrangeSize.Height - newSize.Height;
double top = 0; double left = 0;
if (!double.IsNaN(widthDelta) && !double.IsInfinity(widthDelta)) switch (HorizontalChildAlignment) { case HorizontalAlignment.Left: break; case HorizontalAlignment.Center: left = widthDelta / 2; break; case HorizontalAlignment.Right: left = widthDelta; break; };
if (!double.IsNaN(heightDelta) && !double.IsInfinity(heightDelta)) switch (VerticalChildAlignment) { case VerticalAlignment.Top: break; case VerticalAlignment.Center: top = heightDelta / 2; break; case VerticalAlignment.Bottom: top = heightDelta; break; };
var finalRect = new Rect(new Point(left, top), newSize); Child.Arrange(finalRect);
return arrangeSize; } }
Имея это, можно писать что-то такое

И получать результат:

Необходимо вычислить, какое максимальное количество фигур вместится на прямоугольнике. Чем можно реализовать?

Необходимо написать мини-программку, которая рассчитывала бы наиболее экономичную раскладку материала. Дано: фигура произвольной формы и прямоугольный лист материала. Необходимо разложить максимально возможное количество данной фигуры на этом листе так, чтобы между ними оставалось расстояние 2-3мм (можно регулировать). В какую сторону копать? На чем можно реализовать? Хотелось бы на Python, так как более-менее знаю только его.


Ответ

В общем виде эта задача является труднорешаемой, и не имеет эффективного алгоритма решения в принципе (его не существует в природе). Если материал Ваш имеет какую-то особую форму, то ещё можно что-то сделать, а если форма произвольная, то можно попробовать эвристики. Копайте по таким ключевым словам: "задача о плоскостном раскрое" или "Cutting stock problem". На русском, сразу говорю, - мало что полезного найдёте. На английском ищите задачу Cutting stock problem на прямоугольных полосках с бесконечной длиной (или высотой). Там суть почти всех эвристик в том, что делается попытка разместить N фигур на прямоугольной полоске минимальной длиной (высотой) и с фиксированной высотой (длиной). Соответственно, если у вас ширина (высота) уже заданы заранее, то задача о максимальном числе N решается бинарным поиском. Сами же эвристики настолько объёмы по изложению, что расписывать их здесь не смогу.
Отвечаю на второй вопрос: реализовать можно на чём угодно, когда знаешь алгоритм. Готовые библиотеки мне лично не известны. Вообще, это серьёзная научная проблема, коей занимались разные институты (особенно в советское время), нужно довольно хорошо владеть программированием, чтобы всё здесь правильно закодировать.

Освобождение памяти

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


Ответ

Начнем с того, что free категорически противопоказан. Это C-шная функция, работающая только в паре с malloc
erase - это функция, которая удаляет элементы из вектора. Но поскольку у вас вектор указателей, то автоматически память, на которую они указывают, освобождаться не будет (ведь вас это интересует?)
Так что надо перед erase пробежаться и освободить объекты самому. Если хотите, чтобы все делалось надежно и просто - используйте unique_ptr (если вектор единолично :) владеет объектами; если нет - shared_ptr<>).

Добавить несколько элементов в Layout

Почему когда я пытаюсь добавить несколько View в LinearLayout, компилятор выдает ошибку следующего содержания:
The specified child already has a parent. You must call removeView() on the child's parent first.
Вроде раньше делал подобным образом, все было ок.
LinearLayout layout = (LinearLayout) findViewById(R.id.chart_container); PieChart mPieChart = new PieChart(getApplicationContext());
mPieChart.addPieSlice(new PieModel("Freetime", 15, Color.parseColor("#FE6DA8"))); mPieChart.addPieSlice(new PieModel("Freetime", 15, Color.parseColor("#FE6DA8"))); layout.addView(mPieChart); layout.addView(mPieChart);


Ответ

А если попробовать так
PieChart mPieChart = new PieChart(getApplicationContext()); mPieChart.addPieSlice(new PieModel("Freetime", 15, Color.parseColor("#FE6DA8"))); layout.addView(mPieChart); mPieChart = new PieChart(getApplicationContext()); mPieChart.addPieSlice(new PieModel("Freetime", 15, Color.parseColor("#FE6DA8"))); layout.addView(mPieChart);