Страницы

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

воскресенье, 22 декабря 2019 г.

Книги по архитектуре Linux

#linux #книги


Здравствуйте , вот хочу изучить как построены linux системы. То есть пользоваться
умею , но хочу изучить поглубже , как что и с чем взаимодействует , как память работает
, как устроены уровни защиты и так далее. Хорошо бы если было сравнение с Windows (то
есть в чем принципиальная разница) . И вот хотел бы еще понять в чем разница между
различными дистрибутивами linux , к примеру opensuse и debian , из чего состоит ядро
системы и другое. Подскажите пожалуйста хорошие книги . 
Можно на английском , даже желательно на английском . 
Спасибо заранее.    


Ответы

Ответ 1



Могу порекомендовать парочку на русском (от одного из разработчиков ядра): Роберт Лав. Ядро Linux. описание процесса разработки и его же Linux. Системное программирование Думаю, при желании несложно найти оригиналы. Правда, никакого сравнения с виндоуз (а так же описания дистрибутивов) в них нет (сплошной кодинг + концепции).

USB флешка с FAT32 + EXTfs под Linux-ом

#linux #ext4 #fat32 #flash_память


Хотелось-бы сделать странную флешку: чтобы на ней был ext[234] и FAT32 одновременно.

Но не с двумя разделами, а с одним разделом, то есть, сделать что-то типа (/dev/sdf
— это флешка):


Создаем файл badblocks, в нем указываем блоки, идущие подряд, а суммарный объем этих
bad-блоков совпадает с разделом FAT32.
Форматируем флешку целиком в ext[234] с указанием файла badblocks (mkfs.ext4 -b badblocks
/dev/sdf).
Через fdisk (fdisk /dev/sdf) создаем единственный primary-раздел, который находится
в области, отмеченной в badblocks.
Форматируем /dev/sdf1 в FAT32


Понятно, что в linux-е мне такой флешку придется монтировать руками, зато под виндою
она подхватится автоматически.

Возможно, существует какой-нибудь HOWTO на эту тему, просто с первой попытки не нашел.
    


Ответы

Ответ 1



для того, чтобы операционная система ms/windows могла примонтировать раздел со своей «родной» файловой системой fat, вовсе не требуется тех ухищрений, что изложены в вопросе. необходимо и достаточно, чтобы этот раздел был первым на usb-storage (aka «флэшка»), у которой установлен removable bit. все остальные разделы, какая бы там ни была файловая система, для ms/windows (без каких-нибудь специализированных средств) остаются «вне поля зрения» — воспринимается только первый раздел.

Ответ 2



Полагаю, что речь об этом приёме. Способ заключается в переключении между двумя таблицами разделов, в каждой из которых по одному разделу. В одной из них раздел при создании файловой системы получил на вход крупную последовательность "битых блоков", обходящую местонахождение раздела из второй таблицы. На флэшке виден в каждый момент только один из этих двух, переключение происходит посредством... перезаписи таблицы разделов. Предполагается, что в обычном состоянии флэшка содержит таблицу разделов, с которой видна только файловая система с "зелёным" пространством. Когда "тихо и спокойно", можно записать на флэшку другую таблицу разделов (pro tip: её можно хранить в последнем секторе диска, только надо его обходить остальными инструментами) и тем самым получить доступ к "секретному разделу", потеряв доступ к основному. "Сделав дело", можно вернуть исходную таблицу разделов обратно, вернув флэшку в обычное состояние. Какие файловые системы будут на внешнем и внутреннем разделах, совершенно неважно (лишь бы файловая система умела обходить стороной "плохие" блоки). Windows вполне может видеть оба раздела при условии перезаписи таблицы разделов (и осознании этого факта операционной системой) и совместимой файловой системы на них (например, FAT32). То есть, если вы забудете вернуть исходную таблицу разделов на место, Windows в этом случае успешно увидит секретный раздел. Такой раздел не стоит делать большим, потому что "плохие блоки" в рамках файловой системы обычно числятся как "всегда занятые" во всяких графических инструментах. Так что если диск пуст (нет файлов и папок, в т. ч. скрытых), а на нём занято существенное количество места (заметно больше, чем на диске всего "сырого места" минус структуры ФС), то это может быть сигналом того, что на диске имеется подобная штука.

Ответ 3



Вот тут есть довольно-таки старая, но весёлая инструкция. Или не то?

Как запустить скрипт Python на другом PC

#python


Здравствуйте, начал изучать Python. 
Задался вопросом, как запустить скрипт на другом компьютере (оба PC на Windows),
не подготавливая машину (не устанавливая Python)? 
Все, что смог найти, - это способ формирования .exe файла при помощи py2exe.
Хотелось бы узнать, есть ли альтернативные пути распространения скрипта (более "правильные")
и какие минусы у этого подхода. 
В книжке нет (возможно, еще не дочитал) способов, описывающих перенос, может, я просто
еще не понимаю назначение этого языка?
Python может сильно помочь, если нужно что-то автоматизировать, работая на "моем"
компьютере. Или web-приложения, которые также не требуют предустановки Python на компьютер
конечного пользователя.
Так же я понял:
Но еще на нем можно написать обычную десктопную программу, оптимизируя критические
места на C++. 
Но зачем писать десктопные программы, если их нельзя отдать конечному пользователю?
Или обычно в таких случая в установщик добавляют еще и установщик Python?
Буду особенно признателен за ответ в виде ссылки на статью (или полноценный ресурс),
которая поможет мне разобраться в том, как используют Python в реальной разработке.     


Ответы

Ответ 1



Это проблема Windows. В Linux этой проблемы нет - на этих операционных системах он обычно уже есть "из коробки" (например, в Fedora много скриптов на нем написано). Правильный способ - это сделать два инсталлятора программы: один - со встроенным Python, второй - без. Тот инсталлятор, который со встроенным Python должен иметь либо полный инсталлятор Python и устанавливать ее нормально (но при этом должен быть готовым, что Python уже будет у пользователя), либо содержать минимально необходимую версию Python и держать у себе в папке. Я бы сделал следующее: инсталлятор без Python с возможностью скачивания его из Интернета, если он не установлен у пользователя.

Emacs: как устанавливать пакеты?

#emacs


Хочу попробовать emacs, но без встроенного файлового браузера, по-моему, вообще невозможно
работать (dired - подходит, когда работаешь с двумя, тремя файлами, но когда работаешь
с десятком, по-моему, это нереально).  
Хочу установить Emacs-nav и не врублюсь, как это сделать. В list-packeges его нет.
Делаю по такому туториалу. Там сказано ввести определенный код в ~/.emacs. У меня вообще
нет такого пути, есть  ~/.emacs.d. Захожу и не знаю, куда надо ввести код, который
в туториале, у меня там только файлы auto-save-list, elpa, eshell. Куда вводить-то? 
Еще надо скачать там архив. Я его скачала и не знаю, куда его девать. Вообще непонятно. 
Всем спасибо за ответы.    


Ответы

Ответ 1



Так создайте этот файл с указанным содержимым. cat >> ~/.emacs paste emacs-lisp code from URL ^D Потом все настройки emacs-а будете добавлять туда. А вообще-то я, например, использую emacs параллельно с Thunar (файл-манагер в xubuntu) или Nautilus в ubuntu или каким-нибудь другим GNOME-файл-манагером в др. Linux-ах. Для открытия файла мне Ctrl-x Ctrl-f + (дополняет имена файлов) вполне хватает. Опять же из командной строки всегда можно любую *nix-команду выполнить (Meta-!). И для начала, запустите emacs, наберите Ctrl-h t и читайте туториал.

Ответ 2



dired прикольная штуковина, если почитать про все ее возможности. Если нужно отрыть файл, то ничего делать грандиозного не надо: C-x C-f Много файлов: C-x C-f ~/foo/*.c RET Если нужно визауальное решение гляньте тут https://github.com/jaypei/emacs-neotree https://www.emacswiki.org/emacs/Sunrise_Commander Не настроенным Emacs пользоватся конечно можно, но есть куча уже подогнанных и отлаженных сборок: http://spacemacs.org/ https://github.com/purcell/emacs.d Если отвечать на вопрос, заданный в названии темы: M-x package-list-packages

Ответ 3



Если только начинаете - используйте менеджер пакетов, например MELPA. Там около 4200 разных пакетов. Описание установки тут: http://melpa.org/#/getting-started По сути, если вы еще в самом-самом начале настройки, достаточно удалить/перенести старый файл .emacs и создать новый со следующим содержимым: (require 'package) (let* ((no-ssl (and (memq system-type '(windows-nt ms-dos)) (not (gnutls-available-p)))) (proto (if no-ssl "http" "https"))) (when no-ssl (warn "\ Your version of Emacs does not support SSL connections, which is unsafe because it allows man-in-the-middle attacks. There are two things you can do about this warning: 1. Install an Emacs version that does support SSL and be safe. 2. Remove this warning from your init file so you won't see it again.")) ;; Comment/uncomment these two lines to enable/disable MELPA and MELPA Stable as desired (add-to-list 'package-archives (cons "melpa" (concat proto "://melpa.org/packages/")) t) ;;(add-to-list 'package-archives (cons "melpa-stable" (concat proto "://stable.melpa.org/packages/")) t) (when (< emacs-major-version 24) ;; For important compatibility libraries like cl-lib (add-to-list 'package-archives (cons "gnu" (concat proto "://elpa.gnu.org/packages/"))))) (package-initialize) После этого перезапустите emacs А перечень пакетов тут: http://melpa.org/#/ Далее всё просто. Нажимаете M-x (Alt+X в emacs терминологии) и вводите команду: package-list-packages После чего получите список все доступных пакетов от встроенных (GNU), до тех что установили (melpa). Подводите курсор к нужному, нажимаете Enter, открывается дополнительное окно где нажав на ссылку Install можно установить любой. Читайте описание к каждому пакету. Какие-то пакеты сразу вписываются и запускаются как влитые, какие-то для запуска нужно прописывать в .emacs, ну или запускать внутренней командой. Думаю, что разберётесь, так как всё, как правило, очень хорошо обписано. Особыне знания lisp в этом плане не особо требуется и устанавливается всё довольно легко и без ошибок. Описание как подключить пакетный менеджер Список пакетов для emacs

Двойное условие сортировки листа ( Comparator )

#java #android


Имеется класс:

public class Man (){

    private int rating1;
    private int rating2;

    Man (int rating1, int rating2){
        this.rating1 = rating1;
        this.rating2 = rating2;
    }

    public int getRating1(){
        return rating1;
    }

    public int getRating2(){
        return rating2;
    }
}


Формируется List по rating2 (по убыванию):

public class MyComporatorByRating implements Comparator {

    @Override
    public int compare(man o1, man o2) {
        return Integer.compare(o2.getRating1(), o1.getRating1());
    }

}


Что необходимо добавить в MyComporatorByRating, чтобы вначале списка были только
те Man, у которых rating2 от 1 до 5 в порядке возрастания.

Т.е. первыми в списке List были отсортированы Man по значению rating2 от 1 до 5 (значения
rating1 у них игнорируются), а потом все остальные Man по rating1 от 100 до 0 (значение
rating2 у них 0)?
    


Ответы

Ответ 1



public class Man { private int rating1; private int rating2; Man(int rating1, int rating2) { this.rating1 = rating1; this.rating2 = rating2; } public int getRating1() { return rating1; } public int getRating2() { return rating2; } public CompareWith getCompareWith() { if(rating2 >= 1 && rating2 <= 5) { return CompareWith.RATING2; } return CompareWith.RATING1; } public enum CompareWith { RATING1, RATING2 } } И компаратор: public class MyComporatorByRating implements Comparator { @Override public int compare(Man o1, Man o2) { if(CompareWith.RATING2.equals(o1.getCompareWith()) && CompareWith.RATING2.equals(o2.getCompareWith())) { return o1.getRating2() - o2.getRating2(); } else if(CompareWith.RATING2.equals(o1.getCompareWith())) { return 1; } else if(CompareWith.RATING2.equals(o2.getCompareWith())) { return -1; } else { return o2.getRating1() - o1.getRating1(); } } }

Ответ 2



@Override public int compare(Coordinates o1, Coordinates o2) { int result = Integer.compare(o1.getX(), o2.getX()); if (result != 0) { return result; } return Integer.compare(o1.getY(), o2.getY()); } примерно так. Этот компаратор сравнивает координаты в моём проекте. Сначала сравнивает ось Х, если Х одинаковы, то сравнивает по оси Y. Действуй по аналогии

Ответ 3



Если вы используете Java 8+, то можете воспользоваться новыми возможностями: потоками и лямбдами. Ваш код будет гораздо проще: Comparator comparator = Comparator.comparing(man -> man.rating2); comparator = comparator.thenComparing(Comparator.comparing(man -> -man.rating1)); Stream manStream = men.stream().sorted(comparator); List sortedMen = manStream.collect(Collectors.toList()); Не нужно никаких отдельных классов и ручного сравнения.

Ответ 4



Из Вашего описания следует, что: rating2 є [0, 5], rating1 є [0, 100]. В этом случае, компаратор можно переписать без всякого добавления enum'ов в класс Man. Он будет таким: public class MyComporatorByRating implements Comparator{ @Override public int compare(Man o1, Man o2) { if(o1.getRating2() == 0 && o2.getRating2() == 0){ return -Integer.compare(o1.getRating1(), o2.getRating1()); } else if(o1.getRating2() == 0){ return 1; } else if(o2.getRating2() == 0){ return -1; } else{ return Integer.compare(o1.getRating2(), o2.getRating2()); } } } Также замечу, что оба поля класса Man можно объявить как final (поскольку у Вас нет методов set(), то эти поля неизменяемы).

Как своему приложению android дать возможность переноситься на SD-карту?

#android #карты #sd


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


Ответы

Ответ 1



Нужно в манифесте указать значение android:installLocation ... доступные варианты : auto- на усмотрение системы internalOnly - только во внутренюю память preferExternal - по возможности на SD-карту подробнее смотрите офф.справку

Что лучше использовать для парсинга XAML?

#c_sharp #net #xaml #синтаксический_анализ


Недавно прочел, что для парсинга html не рекомендуют использовать регулярные выражения,
так как есть специальная библиотека. Ну и вот вопрос: есть ли что-то лучше регулярных
выражений для парсинга XAML?
Дополнительная информация:


Пишу на языке C#
Желательно чтобы инструмент работал со строкой, а не с файлом.
Цель: поиск повторяющейся разметки, сокращение ее объема и перестановка атрибутов. 

    


Ответы

Ответ 1



Если вам нужно детальное управление синтаксисом, то используйте парсеры XML: новый System.Xml.Linq.XDocument, старый System.Xml.XmlDocument. XAML — надмножество XML вместе со всеми пронстранствами и имён и прочим, поэтому любой парсер XML справится с XAML. Учтите, что в этом случае вы получите markup extension в виде простой строчки, а маппингом типов придётся заниматься вручную, если он вам понадобится. Если вам нужно глубокое понимание структуры (вместе с markup extension, маппингом на реальные типы и прочими надстройками XAML над базовым XML), то используйте парсер XAML: System.Xaml.XamlServices. Вы потеряете контроль над синтаксисом (если вы сериализуете не исключительно ваши классы), но у вас будет полностью распарсенное в объекты дерево, которое можно модифицировать и впоследствии сериализовать. Если вам нужна кросс-платформенность, то учтите, что парсер XAML в Mono не поддерживает все возможности (читать: ущербен до невозможности и абсолютно бесполезен), а на разных виндовых платформах свои отдельные парсеры диалектов XAML (читать: парсить можно только XAML родом из родной платформы). При этом в CoreCLR парсер XAML тоже, вроде, не намечается.

Tomcat долго запускается (17 минут)

#ubuntu #веб_программирование #tomcat #vps


Арендовал VPS, Ubuntu 14.04, установил туда Tomcat 8. В первый раз запустился нормально.
Ура. Выключил. Включил. Не отвечает на запросы. Мучился довольно долго, в итоге просто
написал

/opt/tomcat/bin/catalina.sh run


и стал дальше сёрфить инет. Спустя 17 минут он заработал! Я получил вот такой вывод
в консоли: http://pastebin.com/WHZv9ssy

Как видно шаг


  01-May-2015 22:13:02.183 INFO [localhost-startStop-1]
  org.apache.catalina.startup.HostConfig.deployDirectory Deploying web
  application directory /opt/tomcat/webapps/ROOT


длился 17 минут! Что это может быть такое? В какую сторону копать?

Дополнение: Судя по  статистике сервера, в это время не было повышенной нагрузки
на процессор, занятой оперативки было 170 из 1024 мб, никаких дисковых операций не
совершалось.
    


Ответы

Ответ 1



Собственно, нашёл решение. Нужно заменить в файле $JAVA_PATH/jre/lib/security/java.security строку securerandom.source=file:/dev/urandom на строку securerandom.source=file:/dev/./urandom Оригинал ответа тут: https://stackoverflow.com/questions/26431922/tomcat7-starts-too-late-on-ubuntu-14-04-x64-digitalocean

Получить результат из функции в Bash

#linux #bash #shell


Есть функция main, которая обращается за результатом к функции Checker.
 При выполнении скрипта, никаких сообщений из Cheker не выводится и не пишется "Все
ОК", хотя файлы существуют и имеют права на чтение.
Что я делаю не так?

 #!/bin/bash
    file1="$1"
    file2="$2"
    main()
    {   
            if  [ "$(checker)" == "true" ]
            then
                    echo "Все ОК"
            fi
    }
    checker()
    {
            flag=""
            if [ -f "$file1" ] && [ -f "$file2" ]
            then
                    echo "Файлы существуют"
                    if [ -r "$file1" ] && [ -r "$file2" ]
                    then
                            echo "Файлы могут быть прочитаны"
                            flag="true"
                    else
                            echo "Один из файлов не может быть прочитан"
                            flag= "false"
                    fi

            else
                    echo "Один из файлов не существует"
                    flag="false"
            fi

            echo "$flag"

    }
main

    


Ответы

Ответ 1



Из двух функций сделайте одну с проверкой по $flag Откройте для себя return [N] вместо flag

Ответ 2



Что я делаю не так? располагаете функцию до её вызова. перенесите функцию main в конец файла — и, скорее всего, вы получите ожидаемый результат.

Ответ 3



#!/bin/bash file1="$1" file2="$2" checker() { flag="" if [ -f "$file1" ] && [ -f "$file2" ] then echo "Файлы существуют" if [ -r "$file1" ] && [ -r "$file2" ] then echo "Файлы могут быть прочитаны" flag=true else echo "Один из файлов не может быть прочитан" flag=false fi else echo "Один из файлов не существует" flag=false fi echo $flag } checker main() { if [[ $(checker) == *true ]] then echo "Все ОК" fi } main

Ломаются цвета в консоли при работе с git

#git #shell


Почему-то при работе с git в *nix-like консоли ломаются цвета: весь текст выводится
дефолтным цветом, а строки, которые должны быть цветными, оказываются обрамлены кодами
цветов:


  ESC[33mcommit 53f26c1fa4dc4f66df6a0fd01677bb3f7d1da12dESC[m


При этом цветной вывод ls --color, например, работает нормально.

Проблема воспроизводится в некоторых дистрибутивах Linux и во FreeBSD. Как быть?
    


Ответы

Ответ 1



Причина проблемы в том, что вывод git отображается посредством системной утилиты less, которая по умолчанию не умеет работать с ANSI-последовательностями, обозначающими границы цветного выделения текста в консоли (точнее, посредством того, что находится в переменной окружения $PAGER). Чтобы less отображал цветные строки, нужно добавить к его вызову ключ -R: -R or --RAW-CONTROL-CHARS Like -r, but only ANSI "color" escape sequences are output in "raw" form. Unlike -r, the screen appearance is maintained correctly in most cases. ANSI "color" escape sequences are sequences of the form: ESC [ ... m where the "..." is zero or more color specification characters Данный флаг можно добавлять непосредственно к вызову less или в содержимое переменной окружения $LESS. Во втором случае $PAGER останется неизменным, но искомый эффект будет достигнут, так как less считает из окружения "свою" переменную $LESS и добавит к себе флаг -R прозрачно. Итого, проблему можно решить следующими способами: Либо передавать нужный флаг через окружение каждый раз непосредственно перед вызовом git: $ LESS=-R git log Данный метод - наименее "инвазивный" и ничего не меняет в настройках git и системы. Либо объявив флаг для less в общесистемное окружение через глобальный конфиг вашего shell-а: например, в случае bash, внеся следующую строчку в ~/.bash_profile: export LESS=-R Либо отказаться от использования git-ом общесистемного $PAGER, прописав вызов less в явном виде в конфиг git-а: $ git config --global core.pager "less -R" Этот метод позволяет не беспокоиться о том, что при изменении системных настроек изменится поведение git. Впрочем, можно и глобально переопределить $PAGER, снабдив вызов less произвольным набором флагов (см. man less): например, в случае bash, внеся следующую строчку в ~/.bash_profile: export PAGER='env LESS_IS_MORE=1 less -FRX' Этот метод затронет вывод не только git, но и многих других "длинных" команд, например того же man.

Как осуществить вызов userControl при помощи паттерна MVVM

#c_sharp #wpf #mvvm


Привет всем.

Решил измотать себя, при помощи WPF. Ну и конечно, паттерн MVVM :)

Разумеется, сразу же столкнулся с проблемой, как при помощи MVVM паттерна открыть
UserControl?

Конечно, нет проблем это сделать в самом View. Но, как же MVVM . Кто-нибудь может
привести пример в пару строк кода Как мне это реализовать. дело в том что в интернете
есть много описания паттерна MVVM, все ограничиваются написанием калькулятора, то бишь
на одной форме. В принципе я тоже пишу всегда на одной форме но в нужные моменты подставляю
контрол.  эмитируя переход на другую форму. Я не знаю правильно это или нет. но, мне
так удобней.
    


Ответы

Ответ 1



Популярный путь такой. Вы прописываете class MainVM : INotifyPropertyChanged { VM activePageVM; public VM ActivePageVM { get { return activePageVM; } set { activePageVM = value; NotifyPropertyChanged(); } } // обвеска для INotifyPropertyChanged } обычным образом. Теперь, ваше окно выглядит так: (можете ещё вокруг добавить общую обвеску, нужную на всех страницах). Осталось только сделать так, чтобы ваш ContentPresenter выбирал правильный UserControl в зависимости от типа VM. Это делается очевидной диспетчеризацией через DataTemplate: Эту диспетчеризацию поместите в App.xaml или куда-то ещё, где она видна в главном окне. Если вам надо где-то локально перекрыть отображение для какого-то типа, пользуйтесь локальными ресурсами, они всегда имеют приоритет.

Не работают label при динамическом добавлении input?

#javascript #html #input #label


Почему-то не работают элементы label, добавляемые вместе с инпутами динамически (пробовал
для инпутов типа radio и checkbox). При этом итоговая разметка аналогична разметке
в "статическом" варианте (когда элементы сразу прописаны в HTML), но в статическом
варианте всё работает (label кликабельны, и при клике на них выбирается соответствующий
инпут).

Проблема наблюдается в Opera 11, в Firefox 38, Chrome 37.

Пытался не использовать при добавлении элементов innerHTML, работая с методами DOM
- не помогло.

При правке через отладчик, допустим, атрибутов name, ничего не изменяется. При этом
в "статическом" варианте всё работает даже если поменять через отладчик тип элементов
с checkbox на radio, и сменить имена (сделав имя единым, чтобы связать радиопереключатели
в группу). Что я делаю не правильно?

P.S. Атрибут for, разумеется, указан в обоих случаях. В JS использовал свойство htmlFor
во втором варианте.

UPD: исходный код

function selectQuestion(index) {

   // Удаление старого содержимого...

   for (var i = 0; i < questions[index].answers.length; i++) {
      var ans = document.createElement('div')
      ans.className = 'answer'
      var str = questions[i].multiple == '1' ? 'ans' + (i+1) : 'ans'
      ans.innerHTML = ''
      ans.innerHTML += ''
      document.getElementById('question_answers').appendChild(ans)
   }
   var answer = questions[index].selected
   if (answer != '') {
      var a = document.getElementById('question_answers').getElementsByTagName('input')
      for (var i = 0; i < questions[index].answers.length; i++) {
         if (answer.charAt(i) < a.length) a[parseInt(answer.charAt(i))-1].checked = true
      }
   }
}


UPD2: HTML код (при котором label не работают)


    


Ответы

Ответ 1



Согласно W3Schools, атрибуту for в качестве значения нужно передавать идентификатор (id) элемента. Пример того, что даже в статичном варианте это не работает с name (браузер - Opera 30.0): А вариант с id работает: Упрощенный (для теста) JS-код для проверки работоспособности динамически добавленных

Android studio не видит смартфон

#android #android_sdk


Android studio не видит телефон. Подключаю через USB, режим разработчика и отладка
по USB включены. Драйвера вроде бы устанавливались при подключении к ПК телефона.

И может можно просто как-то устанавливать сразу приложение на телефон? Делать установочный
пакет, таким образом тоже можно тестировать, медленней но можно. Только как это сделать?
    


Ответы

Ответ 1



Если на телефоне стоит root то можно отлаживаться по wify установив это приложение: https://play.google.com/store/apps/details?id=com.ttxapps.wifiadb&hl=ru Почему IDE может не видеть телефон? 1) установлены не те драйвера 2) слишком длинный/поврежденый кабель или разъем. При этом зарядка будет идти, и комп будет видить, но подключиться из IDE не получится. 3) кто-то блокирует девайс. Например под Linux см, http://developer.android.com/tools/device.html

RecyclerView Adapter отображение элементов при быстром скролинге

#java #android #adapter #recyclerview


У меня такая проблема: при быстром скролинге данные клонируются с одних элементов
в другие. Извините за большие картинки. На первом фото есть первый элемент с текстом
"Новый ПРАЙС!!". Как видите, в нем нет картинки.

    

На втором фото, есть элемент с картинкой игры нхл15



Но при быстрой прокрутке списке вниз а потом вверх в первом(в текущем случае в первом,
а в общем каждый раз куда попадет) элементе появляется картинка со второго фото



Для отображение данных в RecyclerView я использую RecyclerView.Adapter

Код адаптера

public class PostAdapter extends RecyclerView.Adapter {

    private RecyclerView listView;
    VKList posts;
    Context context;

    PostAdapter(VKList p , Context context){
        this.posts = p;
        this.context = context;
        mInflater = LayoutInflater.from(context);
    }

    private LayoutInflater mInflater;
    public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {

        View v = mInflater.inflate(R.layout.simple_list_item_1, viewGroup, false);
        ViewHolder h = new ViewHolder(v);
        return h;
    }


    public void onBindViewHolder(final ViewHolder h, final int i) {
        final VKApiPost post = this.posts.get(i);

        h.id.setText("#" + Integer.toString(post.id));

        h.date.setText(new SimpleDateFormat("d MMM yyyy 'в' HH:mm", new Locale("ru"))
                .format(new Date(post.date * 1000L)));

        if (post.text != "") {
            h.content.setVisibility(View.VISIBLE);
            h.content.setText(post.text);
        }else{
            h.content.setVisibility(View.GONE);
        }

        h.likeCount.setOnClickListener(new View.OnClickListener() {
            private boolean stateChanged;

            public void onClick(View view) {
                if (stateChanged) {
                    // reset background to default;
                    h.likeCount.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.ic_post_btn_like_up, 0);
                    h.likeCount.setTextColor(Color.DKGRAY);
                } else {
                    h.likeCount.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.ic_post_btn_like_selected, 0);
                    h.likeCount.setTextColor(Color.BLUE);
                }
                stateChanged = !stateChanged;
            }
        });

        h.comment.setOnClickListener(new View.OnClickListener() {

            public void onClick(View view) {
                Intent commentActivity = new Intent(context, CommentsActivity.class);
                commentActivity.putExtra("post", post);
                context.startActivity(commentActivity);
            }
        });

        if(!post.user_likes)
        {
            h.likeCount.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.ic_post_btn_like_up, 0);
            h.likeCount.setTextColor(Color.DKGRAY);
        }
        else {
            h.likeCount.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.ic_post_btn_like_selected, 0);
            h.likeCount.setTextColor(Color.BLUE);
        }


        if(post.likes_count == 0)
            h.likeCount.setText("");
        else {
            h.likeCount.setText(post.likes_count + " ");
        }


        for(int j = 0; j < post.attachments.size(); j++){

            VKAttachments.VKApiAttachment att = post.attachments.get(j);
            String type = att.getType();
            if(type == "audio") {

            }
            else if(type == "doc"){
                try {
                    h.docLayout.setVisibility(View.VISIBLE);

                    VKApiDocument doc = (VKApiDocument) att;

                    h.docName.setText(doc.title);
                    if (doc.size % 1024 != 0) {
                        h.docInfo.setText("Документ " + Long.toString(doc.size /
1024 + 1) + " кб");
                    } else {
                        h.docInfo.setText("Документ " + Long.toString(doc.size /
1024) + " кб");
                    }
                }
                catch (Exception e){

                }
            }
            else if(type == "photo"){
                VKApiPhoto photo = (VKApiPhoto)att;
                h.photo.setVisibility(View.VISIBLE);

                Picasso.with(this.context).load(photo.photo_604).into(h.photo);
            }
        }
    }

    @Override
    public int getItemCount() {
        return this.posts.size();
    }

    @Override
    public void onAttachedToRecyclerView(RecyclerView recyclerView) {
        super.onAttachedToRecyclerView(recyclerView);
    }

    static class ViewHolder extends  RecyclerView.ViewHolder{
        TextView id;
        TextView date;
        TextView content;
        ResizableImageView photo;
        CardView cv;
        RecyclerView audios;

        TextView likeCount;

        TextView docName;
        TextView docInfo;
        LinearLayout docLayout;

        Button comment;

        ViewHolder(View itemView){
            super(itemView);
            cv = (CardView)itemView.findViewById(R.id.cv);
            id = (TextView)itemView.findViewById(R.id.postId);
            content = (TextView)itemView.findViewById(R.id.postContent);
            photo = (ResizableImageView)itemView.findViewById(R.id.postImage);
            date = (TextView)itemView.findViewById(R.id.postDate);
            audios = (RecyclerView) itemView.findViewById(R.id.postAudioList);
            comment = (Button) itemView.findViewById(R.id.btnComment);
            likeCount = (TextView) itemView.findViewById(R.id.likeCount);

            docLayout = (LinearLayout) itemView.findViewById(R.id.HLRelativeLayout1);
            docName = (TextView) itemView.findViewById(R.id.docs_item_title);
            docInfo = (TextView) itemView.findViewById(R.id.docs_item_info);
        }
    }
 }


Может кто то сталкивался с данной проблемой?
    


Ответы

Ответ 1



При прокрутке вниз создаются новые вьюхи, выполняется onCreateViewHolder() и onBindViewHolder(). Ушедшие при скролле за экран вьюхи не уничтожаются, а перемещаются в пул объектов RecycledViewPool. Затем, при скролле вверх, либо при дальнейшем скролле вниз, новые вьюхи уже не создаются, а используются ранее освобожденные. Вьюха берётся из RecycledViewPool и вызывается только onBindViewHolder(). В вашем onBindViewHolder() в некоторых случаях не инициализируется h.photo, поэтому там показывается старое значение. В onBindViewHolder() нужно всегда полностью инициализировать все элементы, которые могут изменяться. Т.е. нужно добавить h.photo.setVisibility(View.GONE) куда-нибудь в начало onBindViewHolder(), либо дальше в условиях.

Оператор case не работает с большими числами?

#delphi


Я определяю типы графических файлов по их заголовкам, например:  

var stream : TFileStream;
buff   : int64;
…
stream := TFileStream.Create(FileName, fmOpenRead or fmShareDenyRead);
  stream.Read(buff, sizeof(buff));
  stream.Free;
  case (buff and $FFFFFFFF) of
    $E0FFD8FF : result := 'JPEG IMAGE';
    $E2FFD8FF : result := 'JPEG CANNON EOS JPEG FILE';
…


Используя http://www.filesignatures.net/index.php?page=all&order=EXT&alpha=P.
Но когда я подставляю сигнатуру для «*.*png» - $0A1A0A0D474E5089 (в 8 байт) в case:

case buff of
    $0A1A0A0D474E5089 : result := 'PNG';
end


у меня ошибка:


  Constant expression violates subrange bounds


Как быть в этом случае?
    


Ответы

Ответ 1



Как сказано в документации, ограничение 32 бита: http://docwiki.embarcadero.com/RADStudio/XE3/en/Declarations_and_Statements#Case_Statements any expression of an ordinal type smaller than 32 bits (string types and ordinals larger than 32 bits are invalid) Выход - делать приведение к 32 битам или писать в блоке else case (buff and $FFFFFFFF) of $E0FFD8FF: Result := 'JPEG IMAGE'; $E2FFD8FF: Result := 'JPEG CANNON EOS JPEG FILE'; $474E5089: if buff shr 32 = $0A1A0A0D then Result := 'PNG'; // <-- вариант номер 1 else if buff = $0A1A0A0D474E5089 then // <-- вариант номер 2 Result := 'PNG'; end;

Как написать программу без libc?

#c #ассемблер #arm


Вот хочу написать программу которая просто запустится и завершится без ошибки сегментации.

Если я просто пишу функцию int _start() { return 0;} то получаю ошибку сегментации,
насколько я понял в гугле то надо правильно завершить программу(пару строчек на ассемблере)
но какие должны быть строчки для arm(я с arm ноутбука)?
    


Ответы

Ответ 1



test.c: void _start() { asm( "mov r0, #0;" /* кладем в r0 0 -- код выхода */ "mov r7, #1;" /* кладем в r7 1 -- номер системного вызова exit */ "swi 0" /* системный вызов Linux */ ); } Компиляция и выполнение: $ gcc -nostdlib test.c -o test $ ./test

Изменение внешнего вида выбранного TreeViewItem

#c_sharp #wpf #xaml #treeview


Здравствуйте, имею в своём приложении собственный обозреватель папок. В целом он
функционирует хорошо, но есть один недочёт: если нажать на тот, или иной TreeViewItem,
то он обводиться стандартным и не красивым синим прямоугольником. Как это можно изменить?
Надо заменить этот прямоугольник чем-то...

  
    


Ответы

Ответ 1



Элементы TreeView неявно (или явно, если ваш код это указывает) кладутся в TreeViewItem. Визуализация выбранных элементов/элементов с фокусом делается в TreeViewItem'е. То есть, вам нужно переопределить, как он выглядит. Насколько я понимаю, для этого вам нужно поменять его стиль (ItemContainerStyle), причём целиком. Кажется, нет возможности подменять лишь часть стиля. Вот здесь дан код, как этот стиль определён по умолчанию. (Ищите Style TargetType="controls:TreeViewItem".) Определение реально большое, но правильное. Его можно переопределить например так, как описано здесь (хотя техника немного устарела: вместо триггеров нужно бы использовать VisualState). Или вы можете базироваться на стиле по умолчанию, и подменить нужные части.

Ответ 2



Вам следует переопределить системный цвет, который хранится в ресурсе SystemColors.HighlightBrushKey на который и ссылается стандартный стиль TreeViewItem. Пример:

Как отфильтровать данные и поставить условие на date

#ruby_on_rails


Есть запрос такого вида 

Сущность.where(calendars: {date: "1.07.2015"}).count


Мне возвращает количество записей с значением "1.07.2015" в поле date. Но мне надо
запрашивать именно 7й месяц (или любой другой). Как отфильтровать и поставить условие
на date?

Вот код самой миграции

create_table :calendar do |t|           
  t.belongs_to :user, index: true
  t.belongs_to :days_info, index: true
  t.datetime :date
  t.timestamps
end

    


Ответы

Ответ 1



Попробуйте так: What.where(calendars: {date: '1.07.2015'.to_date...'1.07.2015'.to_date + 1.month}).count

Ответ 2



date = '1.07.2015' daterange = date.to_datetime.beginning_of_month..date.to_datetime.end_of_month Item.includes(:calendars).where(calendars: {date: daterange}).count

Ответ 3



В общем удалил поле date:datetime и создал два поля month:integer и year:integer. Да избыточности много....

Почему тип дженрика нужно указывать второй раз при использовании {{}}?

#java


Почему так можно:

ArrayList list = new ArrayList();


А так нельзя: 

ArrayList list = new ArrayList(){{
   add(0);
}};


Почему так сделали?
    


Ответы

Ответ 1



Используя так называемый double-brace initialization, вы создаёте новый анонимный класс. Когда в Java-7 разрешили опускать аргументы типа в некоторых случаях, одним из исключений, явно прописанным в стандарте, являются как раз анонимные классы: It is a compile-time error if a class instance creation expression declares an anonymous class using the "<>" form for the class's type arguments. Тут нет каких-то принципиальных ограничений, просто усложняло вывод типов в компиляторе, потому что есть много частных случаев. Поэтому недоделали. В Java-9 планируют исправить этот момент — смотрите баг JDK-8073593. В заключение скажу, что double-brace initialization — исключительно дурацкий способ инициализации объектов. У него могут быть неожиданные проблемы: от случайного захвата контекста внешнего класса до смены serialVersionID. В вашем случае это вообще не нужно. Пишите так: List list = new ArrayList<>(Arrays.asList(0)); А если не собираетесь в будущем добавлять и удалять элементы в список, то лучше так: List list = Arrays.asList(0); Но даже если б у вас была Map, лучше заведите отдельный метод, фабрику или билдер, который создаёт предопределённые Map, но не делайте double-brace initialization. В той же девятке, кстати, планируется упростить этот момент — смотрите JDK-8048330. Будет можно писать List list = List.of(1,2,3,4); Set set = Set.of("aa", "bb", "cc"); Map map = Map.of("aa", 1, "bb", 2, "cc", 3);

Sudo: command not found на некоторых командах

#linux #sudo #root


Подскажите почему может не работать команды с sudo, если sudo -s работает?

$ sudo ll
sudo: ll: command not found

    


Ответы

Ответ 1



Это может происходить, если ll — псевдоним. Например: $ which ll ll: aliased to ls -lh В таком случае sudo не сработает, потому что псевдоним не распознаётся. Выход такой: добавьте в ваш ~/.bashrc (~/.zshrc) строку alias sudo='sudo ' Теперь сработает: $ sudo ll Password: total 1240 ... Дело в том, что для распознавания псевдонима необходимо, чтобы первое слово в выполняемой команде было псевдонимом. Если последний символ значения псевдонима — пробел, то следующее за первым псевдонимом слово также будет проверяться как псевдоним. Из bash manual: Aliases allow a string to be substituted for a word when it is used as the first word of a simple command. The shell maintains a list of aliases that may be set and unset with the alias and unalias builtin commands. The first word of each simple command, if unquoted, is checked to see if it has an alias. If so, that word is replaced by the text of the alias. The characters ‘/’, ‘$’, ‘`’, ‘=’ and any of the shell metacharacters or quoting characters listed above may not appear in an alias name. The replacement text may contain any valid shell input, including shell metacharacters. The first word of the replacement text is tested for aliases, but a word that is identical to an alias being expanded is not expanded a second time. This means that one may alias ls to "ls -F", for instance, and Bash does not try to recursively expand the replacement text. If the last character of the alias value is a space or tab character, then the next command word following the alias is also checked for alias expansion. Решение и цитата взяты из этого ответа на Ask Ubuntu: Aliases not available when using sudo Кстати, не вижу большого смысла применять sudo к команде ls. Это сработает точно так же: $ sudo ls $ ls -A

Проблема компиляции Cosmos C#

#c_sharp


Решил тут написать ОС.
Поставил VS 2013 и Cosmos User Kit. Ошибка, я так понимаю, не моя, а Cosmos'а
Мой код

using System;
using System.Collections.Generic;
using System.Text;
using Sys = Cosmos.System;

namespace Meduze
{
    public class Kernel : Sys.Kernel
    {
        protected override void BeforeRun()
        {
            Console.WriteLine("Meduze starting...");
        }

        protected override void Run()
        {
            while(true);
        }
    }
}


Ошибка:

1>------ Build started: Project: Meduze, Configuration: Debug Any CPU ------  
1>C:\Program Files (x86)\MSBuild\12.0\bin\Microsoft.Common.CurrentVersion.targets(1697,5):
warning MSB3270: There was a mismatch between the processor architecture of the project
being built "MSIL" and the processor architecture of the reference "Cosmos.Core, Version=1.0.0.0,
Culture=neutral, PublicKeyToken=5ae71220097cb983, processorArchitecture=MSIL", "x86".
This mismatch may cause runtime failures. Please consider changing the targeted processor
architecture of your project through the Configuration Manager so as to align the processor
architectures between your project and references, or take a dependency on references
with a processor architecture that matches the targeted processor architecture of your
project.  
1>C:\Program Files (x86)\MSBuild\12.0\bin\Microsoft.Common.CurrentVersion.targets(1697,5):
warning MSB3270: There was a mismatch between the processor architecture of the project
being built "MSIL" and the processor architecture of the reference "Cosmos.Debug.Kernel,
Version=1.0.0.0, Culture=neutral, PublicKeyToken=5ae71220097cb983, processorArchitecture=MSIL",
"x86". This mismatch may cause runtime failures. Please consider changing the targeted
processor architecture of your project through the Configuration Manager so as to align
the processor architectures between your project and references, or take a dependency
on references with a processor architecture that matches the targeted processor architecture
of your project.  
1>C:\Program Files (x86)\MSBuild\12.0\bin\Microsoft.Common.CurrentVersion.targets(1697,5):
warning MSB3270: There was a mismatch between the processor architecture of the project
being built "MSIL" and the processor architecture of the reference "Cosmos.Hardware,
Version=1.0.0.0, Culture=neutral, PublicKeyToken=5ae71220097cb983, processorArchitecture=MSIL",
"x86". This mismatch may cause runtime failures. Please consider changing the targeted
processor architecture of your project through the Configuration Manager so as to align
the processor architectures between your project and references, or take a dependency
on references with a processor architecture that matches the targeted processor architecture
of your project.  
1>C:\Program Files (x86)\MSBuild\12.0\bin\Microsoft.Common.CurrentVersion.targets(1697,5):
warning MSB3270: There was a mismatch between the processor architecture of the project
being built "MSIL" and the processor architecture of the reference "Cosmos.System,
Version=1.0.0.0, Culture=neutral, PublicKeyToken=5ae71220097cb983, processorArchitecture=MSIL",
"x86". This mismatch may cause runtime failures. Please consider changing the targeted
processor architecture of your project through the Configuration Manager so as to align
the processor architectures between your project and references, or take a dependency
on references with a processor architecture that matches the targeted processor architecture
of your project.  
1>  Meduze -> c:\users\катя\documents\visual studio 2013\Projects\Meduze\Meduze\bin\Debug\Meduze.dll  
2>------ Build started: Project: MeduzeBoot, Configuration: Debug x86 ------  
2>  IL2CPU invoked with DebugMode='Source', DebugEnabled='True', TraceAssemblies='{NULL}',
IgnoreDebugStub='False'  
2>  IL2CPU task took 00:00:18.0546475  
2>C:\Program Files (x86)\MSBuild\Cosmos\Cosmos.targets(55,5): error : Error occurred
while invoking objdump.  
2>C:\Program Files (x86)\MSBuild\Cosmos\Cosmos.targets(55,5): error : An error occurred:
System.ArgumentNullException: Parameter "message" cannot be null.  
2>   at Microsoft.Build.Shared.ErrorUtilities.VerifyThrowArgumentNull(Object parameter,
String parameterName, String resourceName)  
2>   at Microsoft.Build.Utilities.TaskLoggingHelper.LogError(String subcategory,
String errorCode, String helpKeyword, String file, Int32 lineNumber, Int32 columnNumber,
Int32 endLineNumber, Int32 endColumnNumber, String message, Object[] messageArgs)  
2>   at Cosmos.Build.MSBuild.BaseToolTask.Logs(LogInfo logInfo) in g:\IL2CPU\source2\Build\Cosmos.Build.MSBuild\BaseToolTask.cs:line
175  
2>   at Cosmos.Build.MSBuild.BaseToolTask.ExecuteTool(String workingDir, String filename,
String arguments, String name) in g:\IL2CPU\source2\Build\Cosmos.Build.MSBuild\BaseToolTask.cs:line
127  
2>   at Cosmos.Build.MSBuild.ExtractMapFromElfFile.RunObjDump() in g:\IL2CPU\source2\Build\Cosmos.Build.MSBuild\ExtractMapFromElfFile.cs:line
174  
2>   at Cosmos.Build.MSBuild.ExtractMapFromElfFile.Execute() in g:\IL2CPU\source2\Build\Cosmos.Build.MSBuild\ExtractMapFromElfFile.cs:line 68  
2>Done building project "MeduzeBoot.Cosmos" -- FAILED.  
2>  
Build has been canceled.  


Почему возникает ошибка и как её исправить?
    


Ответы

Ответ 1



Ваш проект лежит в: c:\users\катя\documents\visual studio 2013\Projects\Meduze\ Попробуйте разместить его в другой директории, так, чтобы путь не содержал кириллицы. Cosmos не поддерживает не ASCII символы в путях.

Как правильно собрать пакет с nginx-ом и сторонним модулем?

#ubuntu #nginx #debian #dpkg


В отличие от apache, модули nginx-а компилируются непосредственно в саму программу.

Как правильно пересобрать пакет с nginx-ом в debian-основных дистрибутивах, включив
в код программы какой-нибудь сторонний модуль?
    


Ответы

Ответ 1



пример для модуля nginx-rtmp, но подойдёт и для любого другого. только исходники модуля надо будет брать по другой ссылке и распаковывать в каталог с другим именем (не nginx-rtmp-module). установим необходимые для сборки пакеты: $ sudo apt-get update $ sudo apt-get install build-essential $ sudo apt-get build-dep nginx создадим где-нибудь в домашнем каталоге «сборочный» каталог и «перейдём» в него: $ mkdir -p ~/sborka/nginx $ cd ~/sborka/nginx скачаем и распакуем исходники дистрибутивного пакета nginx: $ apt-get source nginx помимо нескольких необходимых файлов появился и каталог с исходниками пакета — nginx-номер.версии. «перейдём» в него: $ cd nginx-номер.версии в каталоге debian/modules хранятся каталоги с исходниками модулей, которые собираются в одно целое с программой nginx. туда и скачаем исходники дополнительного модуля, в каталог (к примеру) debian/modules/nginx-rtmp-module (т.к. нам не нужна вся история из репозитория, добавим опцию --depth 1): $ git clone --depth 1 https://github.com/arut/nginx-rtmp-module.git debian/modules/nginx-rtmp-module теперь самое «сложное» — надо добавить опцию --add-module=путь/к/модулю в «правильном» месте, чтобы она была передана скрипту configure при сборке пакета. делается это в файле debian/rules. это «обыкновенный» makefile, но «особого, debian-овского назначения». тут два варианта: в более старых версиях пакета надо использовать переменную CONFIGURE_OPTS. если есть её упоминания, то добавьте где-нибудь в начале файла строку: CONFIGURE_OPTS = --add-module=$(MODULESDIR)/nginx-rtmp-module в более новых есть переменная common_configure_flags. найдите строки вида: common_configure_flags := \ --with-cc-opt="$(debian_cflags)" \ ... --with-http_realip_module \ и после последней добавьте нужную строку, чтобы выглядело примерно так (не забудьте про обратный слэш в конце строки и не удаляйте следующую пустую строку): common_configure_flags := \ --with-cc-opt="$(debian_cflags)" \ ... --with-http_realip_module \ --add-module=$(MODULESDIR)/nginx-rtmp-module \ теперь можно собирать пакет (точнее, их соберётся несколько разных): $ dpkg-buildpackage -b -us -uc если последняя команда завершилась успешно (строкой типа dpkg-buildpackage: binary only upload (no source included)), то пакеты — собрались. файлы с ними лежат на каталог выше текущего, т.е. непосредственно в нашем «сборочном» каталоге ~/sborka/nginx. там присутствуют файлы, включающие в названии буквы dbg — это пакеты с отладочной информацией, они обычно не нужны. нужен как минимум пакет из файла nginx-common_версия.и.другие.буквы.deb и один из пакетов, начинающихся с: nginx-core (базовая функциональность, «умолчальная» версия) или nginx-light («облегчённая» версия) или nginx-full («навороченная» версия). для начала удалите установленную версию nginx (если есть): $ sudo apt-get remove 'nginx-*' и поставьте собранные пакеты из файлов: $ sudo dpkg -i ~/sborka/nginx/nginx-common_*.deb ~/sborka/nginx/nginx-core.*.deb если в выводе команды появятся упоминания про неудовлетворённые зависимости, установите их, выполнив: $ sudo apt-get -f install теперь можно проверить, присутствует ли упоминание про тот модуль, который вы добавляли (пример был про rtmp, эту строку и ищем): $ /usr/sbin/nginx -V |& sed 's/ /\n/g' | grep rtmp --add-module=/home/.../sborka/nginx/nginx-версия/debian/modules/nginx-rtmp-module есть такая буква в этом слове!™

Многозадачность компьютеров

#многопоточность #таймер #ос


Насколько я понимаю, процессы в компьютере выполняются не совсем параллельно, а на
самом деле быстро переключаются между собой. Но в таком случае время на завершение
всех процессов все равно остается таким же, как если бы процессы работали последовательно.
Правильно ли я понимаю, что главная фишка этой как-бы "параллельности" в том что мы
можем не дожидаться пока некий процесс закончится а перейти на другой остановив предыдущие?
Какие еще преимущества у такого принципа "параллельности"?

В таком случае, если принцип как-бы "параллельности" верен, то разве в часах на компьютере
не должно накапливаться отставание?
    


Ответы

Ответ 1



Ответ зависит от того, что делают ваши процессы или потоки (давайте для простоты дальше будем говорить о потоках, которые в оригинале зовутся thread). Потоки будут выполняться действительно одновременно, если у вас есть больше одного ядра. Но в вопросе, как я понимаю, интересует ситуация, когда ядро одно. В этом случае некоторые потоки все равно могут выполняться параллельно. Например, пока жесткий диск читает данные или сетевая карта получает пакеты, то операционная система может переключиться на другой поток, и в таких задачах будет заметен выигрыш. Если вы отправили некоторые данные на звуковую карту, то можете пока заняться другими делами, пока она не проиграет полученный участок звука. Если же у вас несколько потоков, которые заняты в основном расчетами, которые занимают ядро процессора, то в этом случае выигрыша от распараллеливания не будет, и даже будет замедление, т.к. переключение между потоками - это не очень дешевая операция.

Ответ 2



Насколько я понимаю, процессы в компьютере выполняются не совсем параллельно, а на самом деле быстро переключаются между собой. В современных многозадачных операционных системах это действительно так, но в общем случае это зависит от операционной системы. Но в таком случае время на завершение всех процессов все равно остается таким же, как если бы процессы работали последовательно. Да, если вся полезная нагрузка процессов выполняется именно на процессоре. А это далеко не всегда так. Различный ввод-вывод приводит к простою процессора. Если во время этого простоя выполнять код другого процесса, можно сэкономить время. Правда, это не учитывает расходы времени на т. н. context switch ("переключение контекста", переход управления из процесса в процесс), так что чисто ЦПУшные задачи при "распараллеливании" окажутся даже медленнее. Правильно ли я понимаю, что главная фишка этой как-бы "параллельности" в том что мы можем не дожидаться пока некий процесс закончится а перейти на другой остановив предыдущие? Да, я выше примерно это и описал :) Другие процессы могут быть и не "силой" остановлены. Они могут остановиться сами в ожидании результата от ядра ОС. Какие еще преимущества у такого принципа "параллельности"? Вообще это не "параллельность" как таковая, но хорошего перевода правильного термина, concurrency, я пока не слышал. "Конкурентность" разве что. Concurrency имеет место, когда код структурирован не для последовательного выполнения, а содержит определённые "разветвления" и "соединения", разные ветки которых могут (потенциально) исполняться параллельно. Однако не обязаны. И описанный вами механизм как раз позволяет "конкурентному" коду ужиться на одном процессоре. Достаточно часто конкурентный код используется в рамках одного процесса (в разных потоках [thread]), в котором поддерживается какой-то интерфейс пользователя (UI), а из него запускается какая-то рабочая нагрузка. Они оформляются конкурентно, чтобы интерфейсом можно было пользоваться даже когда программа занята какой-то работой. Однако это "преимущество" строится скорее на способе определения понятия "процесс". Скажем, в Linux различий между "процессом" и "потоком" минимум: у них всех есть собственные "process ID", хотя снаружи их не всегда видно, т. к. перечислители процессов стараются отдельные потоки не показывать, за ненадобностью. Но этот же принцип встречается и в несколько неожиданной форме: интерпретаторы некоторых языков, в частности Ruby (MRI), JS (V8) и Python (CPython), реализованы с применением Global Interpreter Lock, и из-за этого интерпретатор в каждый момент времени может заниматься выполнением только одного потока кода. Это существенно упрощает реализацию интерпретатора и взаимодействующего с ним кода (расширений на С, например), хотя и ставит дополнительные ограничения. В таком случае, если принцип как-бы "параллельности" верен, то разве в часах на компьютере не должно накапливаться отставание? Да нет, там всё в порядке, поддержкой часов обычно занимается отдельное устройство (RTC с батарейкой), а не процесс. Иначе как бы часы шли, когда компьютер выключен? Впрочем, это легко выяснить. К примеру, на всех моделях Raspberry Pi часы при каждом включении приходится выставлять заново. Там реализована поддержка часов при включенном устройстве, но отдельного источника питания для них нет. Похожим образом будет себя вести и обычный настольный компьютер, если извлечь из материнской платы батарейку.

Как узнать время сервера из присланного ответа POST запроса?

#java #android #http #post #время


Как вытащить время сервера из ответа, который пришел на POST запрос? 
Для отправки POST запроса с Android используется библиотека OKHTTP.

String post(String...url) throws IOException {
        FormEncodingBuilder form = new FormEncodingBuilder();
        RequestBody formBody =form.build();
        Request request = new Request.Builder()
                .header("Cookie", x)
                .url(url[0])
                .post(formBody)
                .build();
        Response response = client.newCall(request).execute();
        return response.body().string();
    }

    


Ответы

Ответ 1



В Response есть параметр Date, в котором передается текущее время сервера. Пример Response Headers: Date: Fri, 13 Nov 2015 23:24:28 GMT Content-Type: application/json Transfer-Encoding: chunked Connection: keep-alive Но в вашем методе post() возвращается только body, тогда как Date хранится в headers. Соответственно пример кода для получения даты: Date post(String...url) throws IOException { FormEncodingBuilder form = new FormEncodingBuilder(); RequestBody formBody =form.build(); Request request = new Request.Builder() .header("Cookie", x) .url(url[0]) .post(formBody) .build(); Response response = client.newCall(request).execute(); //return response.body().string(); //Возвращается только Body. return response.headers().getDate("Date"); //Возвращаем объект Date. }

Почему SmtpClient не отправляет письмо и не выдает исключение?

#c_sharp #wpf #email #mailru


При запуске данного кода:

MailMessage mail = new MailMessage();
mail.From = new MailAddress(senderBox.Text);
mail.To.Add(recipientBox.Text);
mail.Subject = subjectBox.Text;
mail.Body = bodyBox.Text;

SmtpClient SmtpServer = new SmtpClient("smtp.mail.ru");
SmtpServer.Port = 465;
SmtpServer.Credentials = new NetworkCredential(senderBox.Text, passwordBox.Password);
SmtpServer.EnableSsl = true;

try
{
    SmtpServer.Send(mail);
}
catch (Exception exc)
{
    MessageBox.Show(exc.Message);
}


Код покидает функцию после строки SmtpServer.Send(mail);, но письмо не отправляется
и код не входит в catch-блок. Чем можно объяснить такое поведение?
UPD:
проблема была в порте.Попробовал 587-все нормально работает
    


Ответы

Ответ 1



Для диагностики, чтобы понять что происходит, можно включить следующий блок в раздел в файл app.config Тогда можно будет увидеть и понять отправилось Ваше сообщение на smtp сервер или нет и что именно происходит.

Ответ 2



SMTP сервер mail.ru не смотря на то что работает через SSL но при этом использует 25 порт, вот такой вот парадокс, потратил пол-дня пока разобрался

Ответ 3



Метод Send не гарантирует 100% отправки сообщения. Этот метод только добавляет ваше письмо в очередь на отправку на SMTP сервере, а дальше уже сервер сам решает отправлять его или нет. Проверьте сервер. На том же mail.ru стоят фильтры антиспама - проверьте, что письмо не попало в них. Если ничего не выйдет - напишите в саппорт или смените SMTP сервер.

Ответ 4



Вот мой работающий код (ранее тоже мучался с этим вопросом) private Task SendEmailAsync(IdentityMessage message) { string email_address = "blala@blala.ru"; SmtpClient smtp = new SmtpClient("smtp.mail.ru", 25); smtp.Credentials = new NetworkCredential(email_address, "blala"); smtp.EnableSsl = true; smtp.Timeout = 20000; //20s MailMessage mailMessage = new MailMessage(email_address, message.Destination, message.Subject, message.Body); try { //smtp.SendAsync(mailMessage, 1); smtp.Send(mailMessage); } catch (Exception ex) { Debug.WriteLine($"Произошла ошибка при отправке email: {ex.Message}"); Task.FromException(ex); } return Task.FromResult(0); }

реализация ЕСИА на сайте

#c_sharp #авторизация #oauth #аутентификация


Добрый день! Встал вопрос прикрутить авторизацию на сайте через есиа (Госуслуги). 
Наверняка кто-то уже проделывал это! Помогите пожалуйста, я от этого очень далека,
а сделать надо...

В общем, имеется сайт на ASP.NET (c#, Windows Forms).

Выбранный тип аутентификации - OAuth 2.0 и OpenID Connect 1.0.

Уже, как указано, на сайте минкомсвязи сформировали заявку на подключение к тестовой
среде ЕСИА. Заявку одобрили, прислали документ с инструкцией и 3 файла. В инструкии
как таковых шагов нет, только логины и пароли для входа на госуслуги тестовые и описание
того, что должно прийти в ответ. 

Файлы типа .rar - по инструкции это якобы контейнеры с ключами для ЭЦП.
например, архив EsiaTest.006.rar содержит такие файлы:


header.key 
masks.key
masks2.key
name.key
primary.key
primary2.key


Все параметры для авторизации в принципе понятны, кроме как раз подписи.
Вот как раз с формированием ЭЦП у меня проблемы.

В документе сказано формировать ее так:


  Подпись запроса в формате PKCS#7 detached signature в кодировке UTF-8 от значений
четырех параметров HTTP–запроса: scope, timestamp, clientId, state (они у меня есть).
Подпись должна быть закодирована в формате base64 url safe. Используемый для проверки
подписи сертификат должен быть предварительно зарегистрирован в ЕСИА и привязан к учетной
записи системы-клиента в ЕСИА. ЕСИА поддерживает сертификаты в формате X.509. ЕСИА
поддерживает алгоритмы формирования электронной подписи RSA с длиной ключа 2048 и алгоритмом
криптографического хэширования SHA-256, а также алгоритм электронной подписи ГОСТ Р
34.10-2001 и алгоритм криптографического хэширования ГОСТ Р 34.11-94.


Помогите сформировать эту подпись! Как все это реализовать на c# ?
Заранее благодарю
    


Ответы

Ответ 1



Шаги по интеграции вы вряд ли где-то найдете. Есть только методические рекомендации и регламент работы с ЕСИА, но адекватного описания процедуры "как это сделать на C#" там нет :) То, что вам прислали вместе с ответом на заявку — это просто примеры разных тестовых аккаунтов для отладки работы, т.е. это НИКАК НЕ СВЯЗАНО с подписью ваших запросов к ЕСИА. Вот команды которыми мы генерирует правильный сертификат: openssl req -nodes -sha256 -newkey rsa:2048 -keyout secret.key -out request.csr -subj /C=RU/ST=Rostov-na-Donu/L=city/O=COMPANY\/emailAddress=EMAIL@site.ru/ openssl x509 -req -sha256 -days 3650 -in request.csr -signkey secret.key -out cert.crt -extfile /etc/ssl/openssl.cnf -extensions v3_ca openssl x509 -in cert.crt -text Соответственно в нужные места нужно подставить правильные данные о компании почту и т.п. это команда работает под линуксом при этом в файле /etc/ssl/openssl.cnf надо добавить(изменить) следующую секцию: [ v3_ca ] # Extensions for a typical CA # PKIX recommendation. keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment, dataEncipherment extendedKeyUsage = emailProtection, clientAuth subjectKeyIdentifier=hash authorityKeyIdentifier=keyid:always,issuer в результате вы получите работающий сертификат cert.crt и ключ secret.key Но это будет только начало. Там еще вагон и маленькая тележка нюансов по части обмена данными с ЕСИА. Вот тут есть готовое решение, в т.ч. и на C#: esia.pro Оно платное, но помимо готовой реализации там еще проконсультируют по процессу интеграции и оргвопросам.

Ответ 2



У нас подпись заработала как-то так: public static byte[] Sign(X509Certificate2 certificate, byte[] data) { if (data == null) throw new ArgumentNullException("data"); if (certificate == null) throw new ArgumentNullException("certificate"); // setup the data to sign ContentInfo content = new ContentInfo(data); SignedCms signedCms = new SignedCms(content, true); CmsSigner signer = new CmsSigner(certificate); var sha256 = new Oid("2.16.840.1.101.3.4.2.1", "sha256"); signer.DigestAlgorithm = sha256; // create the signature signedCms.ComputeSignature(signer); var signature = signedCms.Encode(); return signature; } С base64 там всё не очевидно: Convert.ToBase64String не подходит, не достаточно точно реализует стандарт. Использовал вот такой метод: public static string Base64UrlEncode(byte[] arg) { string s = Convert.ToBase64String(arg); // Regular base64 encoder s = s.Split('=')[0]; // Remove any trailing '='s s = s.Replace('+', '-'); // 62nd char of encoding s = s.Replace('/', '_'); // 63rd char of encoding return s; } Проверка их подписи - это очередной ребус. Можно предположить, что это процесс обратный процессу подписания, т.е. как-то так: public static bool ValidateCmsSignature(byte[] data, byte[] signature, X509Certificate2 certificate) { bool result = false; if (data == null) throw new ArgumentNullException("data"); if (signature == null) throw new ArgumentNullException("signature"); if (certificate == null) throw new ArgumentNullException("certificate"); // setup the data to sign ContentInfo content = new ContentInfo(data); SignedCms signedCms = new SignedCms(content, true); try { signedCms.Decode(signature); signedCms.CheckSignature(new X509Certificate2Collection(certificate), true); result = true; } catch (Exception ex) { var msg = ex.Message; } return result; } И этот метод работает для проверки нашей подписи, но не подходит для их подписи. А почему? Если мы сначала формируем текстовую строку, потом создаем отсоединенную подпись по ней, и потом всё это кодируем в base64, то они формируют два JSON'а: HEADER и PAYLOAD, потом кодируют их по отдельности в base64, и вот потом формируют подпись по строке HEADERbase64.PAYLOADbase64. А потом уже и подпись кодируют в base64. Итого, метод для проверки их подписи выглядит как-то так: public static bool ValidateSignature(byte[] data, byte[] signature, X509Certificate2 certificate) { bool result = false; using (var csp = (RSACryptoServiceProvider) certificate.PublicKey.Key) { using (var hasher = new SHA256Managed()) { var hash = hasher.ComputeHash(data); string id = CryptoConfig.MapNameToOID("SHA256"); bool isDataok = csp.VerifyData(data, id, signature); bool isHashOk = csp.VerifyHash(hash, id, signature); // можно ещё так //RSAPKCS1SignatureDeformatter rsaDeformatter = new RSAPKCS1SignatureDeformatter(csp); //rsaDeformatter.SetHashAlgorithm("SHA256"); //bool isHashOk2 = rsaDeformatter.VerifySignature(hash, signature); result = isDataok && isHashOk; } } return result; }

Ответ 3



А вообще уже есть в NuGet полезнейшая библиотечка, с которой всё становится легче: https://www.nuget.org/packages?q=esia.net В наши времена первопроходимцев так не баловали :))

setw задаёт разную ширину поля вывода строк

#cpp #строки #потоки_данных


Привет!
Есть таблица некоторых строковых переменных (string). Необходимо эту таблицу вывести
в адекватном форматированном виде. Проблема заключается в том, что при использовании
манипулятора setw () строки, разные по длине, занимают разную ширину поля, а не фиксированную.

#include 
#include 
#include 

using namespace std;

int main ()
{
  string one = "Один", two = "Два", eight = "Восемь";
  cout << setw (10) << one <


Ответы

Ответ 1



Эх. Судя по всему, это проблемы интернационализации и utf-8. Дело в том, что C++ не знает об utf-8, и считает ширину поля в байтах, а не в реальных символах. А для utf-8 количество байт не равно количеству символов. Обратите внимание, что у вас ширина поля получилась не 10, а меньше — текст "Один" в utf-8 занимает больше четырёх байт, поэтому количество недостающих до 10 байт меньше. Попробуйте перейти на широкие строки: wstring one = L"Один", two = L"Два", eight = L"Восемь"; wcout << setw (10) << one << endl; wcout << setw (10) << two << endl; wcout << setw (10) << eight << endl; Если вы работаете под Windows, вам придётся прибегнуть к небольшой акробатике, чтобы заставить консоль правильно понимать широкие строки. Под линуксом, кажется, достаточно в начале программы применить заклинание setlocale(LC_ALL, ""); Заметьте, что консольный ввод/вывод приложения должен быть либо полностью «узкий», либо полностью «широкий»: переключиться после первого выведенного символа уже нельзя.

Источники по безопасному (Secure) программированию

#javascript #java #cpp #python #c


Какие есть ресурсы (книги, форумы, статьи) по безопасному программированию (Secure
Programs). 




  Данный перечень входит в поддерживаемый сообществом Сборник учебных ресурсов по
программированию.

    


Ответы

Ответ 1



Безопасность в вебе: статьи и рекомендации от Open Web Application Security Project The Web Application Hacker's Handbook: Finding and Exploiting Security Flaws, Dafydd Stuttard, Marcus Pinto The Tangled Web: A Guide to Securing Modern Web Applications, Michal Zalewski Secure Code от Microsoft: Ссылки на best practices и "how-to"-статьи по написанию secure code Writing Secure Code (2nd Edition) (Developer Best Practices), David LeBlanc, Michael Howard

При помощи jQuery UI Datepicker сделать несколько календарей на странице таким образом, чтобы к каждому можно было применить свой стиль

#javascript #html #jquery_ui #календарь #datepicker


Как на одной Html-странице сделать несколько независимых календарей jQuery UI Datepicker,
чтобы у каждого был свой класс (чтобы к каждому применить свои стили)?
    


Ответы

Ответ 1



Достаточно просто применить к инпутам класс и повесить datepicker на него $(function() { $( ".datepicker" ).datepicker({ dateFormat: "yyyy-mm-dd" }); });

Ответ 2



Чтобы изменить оформление для каждого календаря отдельно, потребуется задавать класс внутри функции beforeShow. При этом сначала придется удалять все возможные "свои" классы, иначе после открытия всех календарей будут добавлены все классы. $(function() { $(".datepicker").datepicker({ beforeShow: function(input, inst) { inst.dpDiv .removeClass('custom1 custom2') .addClass($(input).data('dp-class')); } }); }); #ui-datepicker-div.custom1 { background: #ff8; } #ui-datepicker-div.custom2 { background: #f8f; }

JavaScript Application и авторизация через OAuth 2

#php #javascript #angularjs #oauth2


Дано:


Основной сайт (PHP+HTML) с поднятым OAuth 2 сервером
Доверенное приложение на этом же домене на Angular-е (100% javascript)


Задача:


Авторизация пользователей в приложении через собственный OAuth сервер (точнее нужен
токен для доступа к апи)
"Запомнить меня" (каждый раз тыкать кнопку и делать кучку редиректов не вариант)


Размышления:

Сама спецификация предусматривает для таких случаев Implicit Grant, но как реализовать
"запомнить" я так и не придумал ибо срок жизни токена ограничен, а получить новый можно
только через редиректы => оно неюзабельно.

Кроме того, например, вон там рассказывается что оно не безопасно и дана гениальная
идея использовать proxy и шифрованные кукисы для скрытия токенов (refresh_token получается
недоступен в js, но сохраняется в кукисах и может потом использоваться повторно) -
однако, я так и не понял что помешает использовать этот proxy напрямую? (имхо, бессмысленное
усложнение, возможно, ошибаюсь?) 

Следующей после после proxy была идея забить на спецификацию и использовать Authorisation
Code Grant с открытым client_secret - благодаря наличию refresh_token-а можно будет
получать новые токены и оставаться авторизованным. НО этот вариант по сути мало чем
отличается от Implicit Grant с "вечным" токеном + из-за большего количества действий
реализация получается немного сложнее.

Решение?

В итоге после прочтения тонны всяких статей на тему js + oauth и размышлений о том
как же оно всё криво изложенных выше остановился на следующем варианте: используя Client
Credentials Grant выполняем ajax POST на основной сайт и если пользователь там авторизован
("там" оно определяется по cookies) и ранее уже авторизовал приложение, то сразу возвращаем
токен (это и будет "запомнить меня"), если нет, то получаем первый токен через Implicit
Grant. Естественно это всё только при https, POST, X-Frame-Options: DENY и всё на одном
домене. Вроде бы оно не сильно дыряво получается? 



В общем то, хотелось бы услышать критику или предложите какой-нибудь другой вариант,
себе уже всю голову сломал :(
    


Ответы

Ответ 1



Вы, ровно как и Алекс Билби сильно преувеличиваете опасность авторизации клиентских приложений в OAuth2. Естественно, в фронтенде публичного веб-приложения не стоит организовывать получение прав через Resource Owner Password Credentials(когда OAuth-серверу для получения токена передаётся id приложения + логин/пароль пользователя). Не стоит использовать и Client Credentials(OAuth-серверу передаётся только id приложения, а авторизация происходит с использованием внешних систем - например через NTLM-хеш, либо через HTTP-basic-авторизацию). Впрочем, оба этих способа очень специфичны, и абсолютное большинство OAuth-серверов их просто-напросто не поддерживают... Для авторизации остаются только Explicit(Authorization Code) и Implicit. Explicit требует наличия веб-сервера. При этом access token клиенту не передаётся - клиентской стороне возвращается "статус" и "код авторизации", тот передаёт серверу приложения, а он используя код авторизации получает от OAuth-сервера токен доступа. Дополнительно(но не всегда обязательно) при получении токена доступа серверу приложения требуется отправить "client secret" - специальный код/пароль, по которому определяется подлинность вашего приложения, и без указания которого нельзя получить токен доступа. Implict не требует наличия веб-сервера, при этом токен доступа возвращается в url. И естественно "client secret" в этом случае не используется - OAuth-серверу отправляется только id приложение, которое собственно по определению не является секретной информацией(любой может просто скопировать его из url авторизации, даже при explicit-авторизации). Злоумышленник потенциально может украсть как токен доступа при Implicit авторизации, так и авторизационные cookies вашего сайта. Основным каналом утечки при этом являются XSS-уязвимости на вашем сайте, либо вредоносное ПО на компьютере пользователя. Что злоумышленник получит в случае кражи токена доступа/cookies? Для практически всё! И не важно, что применялась Explicit-авторизация и вы проксировали запросы - всю необходимую информацию он получит через ваш сайт. Основное преимущество "проксирования" состоит в том, что иногда поставщики OAuth-ресурсов создают чересчур широкие scope, включающие заведомо больший функционал, нежели необходимо вашему приложению(несмотря на спецификацию, требующую минимальность) - в этом случае вы можете отрезать доступ к нежелательным ресурсам на уровне вашего бекенда. Но и минус тоже есть - при Explicit-авторизации, в случае взлома вашего сервера, злоумышленник получит из хранилища токены доступа сразу всех пользователей приложения. В случае же Implict-авторизации, взломав ваш сервер, злоумышленник токены доступа пользователей сразу не получит(ему придется предваритально модифицировать код фронтенда, да выдирать сохраненные на клиентской стороне токены).

Структура файла .class

#java #классы #компилятор


Какую информацию можно получить от уже скомпилированного java файла .class? Какие
данные там хранятся в явном виде?
    


Ответы

Ответ 1



Если я ничего не забыл и правильно понимаю официальную документацию (https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html), хранятся там в явном виде все строки, информация о предке, методах, интерфейсах и полях. Может и еще что.

Ответ 2



Свойства файла: определяющее тип файла «волшебное слово» 0xCAFEBABE и версия формата; Пул констант – содержит все используемые имена методов и классов в специальном формате, и прочую символьную информацию. В других местах используются только ссылки на элементы пула; Основные свойства класса: флаги доступа, имя этого класса, его предка, интерфейсов; Внутреннее содержимое: список полей класса и байткод методов Атрибуты класса; Взято отсюда

Как запустить рекламу адмоба(видео) при старте приложения?

#java #android #admob #activity_life_cycle


Ссылка на офф. документацию : https://developers.google.com/admob/android/interstitial

Сделал как там все описано - работает, но только при нажатии кнопки. А как сделать,
что бы при каждом запуске приложения отображалась реклама 1 раз? 
    


Ответы

Ответ 1



Надо отследить что пользователь открыл приложение, а не (например) повернул. Это можно сделать проверив if(savedInstanceState==null) это аргумент в onCreate методе активити. После её поворота (пересоздания) этот аргумент уже не null и условие выполнено не будет. В этом условии сформировать запрос к AdMob Запустить его и ждать пока реклама не отобразится. public class MainActivity extends ActionBarActivity { boolean adsAlredyShown = false; InterstitialAd mInterstitialAd; @Override protected void onCreate(Bundle savedInstanceState) { Log.i("LOG", "onCreate"); super.onCreate(savedInstanceState); mInterstitialAd = new InterstitialAd(this); mInterstitialAd.setAdUnitId("ca-app-pub-3940256099942544/1033173712"); //идентификатор из доков надо заменить на свой mInterstitialAd.setAdListener(new AdListener() { @Override public void onAdClosed() { Log.i("LOG", "onAdClosed"); } public void onAdLeftApplication() { Log.i("LOG", "onAdLeftApplication"); } @Override public void onAdLoaded() { Log.i("LOG", "onAdLoaded"); mInterstitialAd.show(); } public void onAdFailedToLoad(int errorCode) { Log.e("LOG", "onAdFailedToLoad with errorCode " + errorCode); } @Override public void onAdOpened() { Log.i("LOG", "onAdOpened"); //вызывается в момент отображения рекламы. //и раз она отобразилась ставим флаг в true //чтобы больше её не показывать adsAlredyShown = true; } }); if(savedInstanceState==null) { AdRequest adRequest = new AdRequest.Builder().build(); mInterstitialAd.loadAd(adRequest); } else { adsAlreadyShown = savedInstanceState.getBoolean("AdsAlreadyShown", false); //реклама ещё не показывалась if(!adsAlreadyShown) { AdRequest adRequest = new AdRequest.Builder().build(); mInterstitialAd.loadAd(adRequest); } } } protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); outState.putBoolean("AdsAlreadyShown", adsAlreadyShown); } } Также, в тот же savedInstanceState можно поместить флаг после показа рекламы и не показывать её пока он true. Этот флаг исчезнет только если активити будет убита системой или вручную методом finish()

Ответ 2



Дык, по правилам Гугла, рекламу Запрещено отображать при старте приложения ? Недопустимые способы размещения межстраничных объявлений

Растянуть слово по ширине div

#html #css


Есть определенное слово, нужно его растянуть по ширине div Можно изменить letter-spacing
но блок резиновый, как подобрать непонятно. Возможно ли решить на CSS без скриптов
и не разбивая слово на элементы?
    


Ответы

Ответ 1



каждой букве одеваешь span и родителю text-align: justify; например:
Слово


Ответ 2



Помещаем нужное слово в тэг списка, добавляем флексбокс и растягиваем по экрану, например, вот так: ul{ display:flex; text-align: center; padding: 0; margin: 0; list-style: none; } ul li { flex: 1 10%; background: #333; color: #fff; margin: 0 10px; }
  • О
  • ф
  • и
  • г
  • е
  • т
  • ь


Ответ 3



В итоге вставил между буквами пробелы и выровнял через text-align: justify; Если у кого есть более цивилизованное предложение, буду очень рад.

array_slice не срабатывает внутри foreach

#php #массивы


Проблемный участок кода:

public function create($file)
{
    $file = file($file);

    $country = preg_grep('/\((\w+)\)(\s?(\w+)\s?(\w+))/', $file);

    foreach ($country as $key => $value)
    {
        $this->collection[$value] = array_slice($file, $key, next($country));
    }
}


Входной файл:

(UK) Great Britan
Zelma Belyavskaya
Danielle Hughes
(PH) Philippines
Marione Bayunggan
Maria Hadap


Нужный результат:

array [
    (UK) Great Britan => [Zelma Belyavskaya, Danielle Hughes],
    (PH) Philippines => [Marione Bayunggan, Maria Hadap]
]


Текущий результат:

array [
    (UK) Great Britan => [],
    (PH) Philippines => []
]

    


Ответы

Ответ 1



Вы там намудрили. next вернет первый раз 3, а второй раз ему нечего возвращать - массив кончился. Я бы так делал $file = [ '(UK) Great Britan', 'Zelma Belyavskaya', 'Danielle Hughes', '(PH) Philippines', 'Marione Bayunggan', 'Maria Hadap' ]; $collection = []; $key = ''; foreach ($file as $value) { if (preg_match('/\((\w+)\)(\s?(\w+)\s?(\w+))/', $value)) { $key = $value; continue; } $collection[$key][] = $value; } print_r($collection); получим Array ( [(UK) Great Britan] => Array ( [0] => Zelma Belyavskaya [1] => Danielle Hughes ) [(PH) Philippines] => Array ( [0] => Marione Bayunggan [1] => Maria Hadap ) )

Бинарное дерево

#бинарное_дерево


Требуется реализовать бинарное дерево, НО:
Обязательное ли условие, чтобы правая крайняя сторона с корня увеличивалась до максимума,
а левая крайняя сторона уменьшалась до минимума?(см. на приложенное изображение) Интернет
перерыл, но прямым текстом это нигде не написано, но на одних визуализациях это условие
выполняется, а на других нет.  

Обновлено:
Можно ли данную реализацию считать бинарным деревом?

    


Ответы

Ответ 1



Определения Определение бинарного дерева:(1) Дерево, в котором каждая вершина имеет не более двух потомков, называется бинарным, в противном случае будем дерево называть произвольным. Определение бинарного дерева поиска:(2) Будем называть бинарное дерево деревом поиска, если для любой вершины ключ этой вершины не меньше ключа любой вершины левого поддерева и строго меньше ключа любой вершины правого поддерева Ссылки: (1) В.Д.Валединский, Ю.Н.Пронкин Вычислительные системы и программирование, Схемы хранения данных (Москва, 2006 г.) стр 67 (2) В.Д.Валединский, Ю.Н.Пронкин Вычислительные системы и программирование, Схемы хранения данных (Москва, 2006 г.) стр 74 Изображение на рисунке терминала является бинарным деревом, но не бинарном деревом поиска, так как нет алфавитного или какого-нибудь другого, заранее обговорённого, порядка

Создание файла в java

#java


Как создавать файл в java, чтобы он стал частью package?
Тоесть, находился в одной папке с java файлами?
Путь к папке через C:// не подходит, т.к. файл должен создаваться на разных устройствах.
И как его прописать впоследствии для открытия?
    


Ответы

Ответ 1



Если я правильно понял ваш вопрос, то вы можете получить путь к папке проекта как String path = new File("").getAbsolutePath(); и затем просто создавать файлы в папке проекта как File newFile = new File(path + "\file1.txt");

Проблема с буквой “Й” в UTF-8

#linux #mac #hex #diff


Пытаюсь сравнить два файла, оба содержат список файлов/папок, один сделан на маке,
другой на linux.
diff показывает разницу где ее на первый взгляд нет.
Перевод в hex режим показал что одна и та же буква (визуально это й)
в одной системе сформировалась след. символом d0b9 а в другой d0b8.
Может кто знает почему ? и как сравнивать в таком случае ?
    


Ответы

Ответ 1



Буква "й" может быть кодирована в unicode двумя способами: как один символ - собственно, "й" (Cyrillic Small Letter Short I), и как два символа - "и" (Cyrillic Small Letter I) и Combining Breve ("шляпка"). Это может создавать определённые проблемы при сравнении и поиске текста. Подробнее можно почитать в этой статье: Хабрахабр: «Й» вам не «и» краткое! О важности нормализации Unicode В вашем случае можно файл с "разложенной" буквой "й" перед сравнением прогнать через sed с помощью следующей команды: cat файл | sed "s/\xD0\xB8\xCC\x86/\xD0\xB9/g" (предложено участником Mike)

Поиск по listView android

#java #android #listview


Есть задача реализовать поиск по listViev, но данный код  адекватно ищет только по
первым символам, если ввести символы которые в словах находятся в средине или конце
- то он вообще не дает результатов. Если нужно привести дополнительный код - говорите
я добавлю.    

 mInputSearch.addTextChangedListener(new TextWatcher() {

        @Override
        public void onTextChanged(CharSequence cs, int arg1, int arg2, int arg3) {
            // When user changed the Text
            ListFragment.this.mAdapter.getFilter().filter(cs);
        }

        @Override
        public void beforeTextChanged(CharSequence arg0, int arg1, int arg2,
                                      int arg3) {
            // TODO Auto-generated method stub
        }

        @Override
        public void afterTextChanged(Editable arg0) {
            // TODO Auto-generated method stub
        }
    });


ListFragment.java

public class ListFragment extends Fragment {

private ListView mListView;
private EditText mInputSearch;

private ArrayList mList;
private ArrayAdapter mAdapter;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    mList = new ArrayList();
    fillArray();

    mAdapter = new ArrayAdapter(getActivity().getApplicationContext(),R.layout.item_list,
mList);

}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View v = inflater.inflate(R.layout.activity_list, container, false);

    mInputSearch = (EditText) v.findViewById(R.id.inputSearch);

    mListView = (ListView) v.findViewById(R.id.listView);
    mListView.setAdapter(mAdapter);

    return v; }

@Override
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);

    mInputSearch.addTextChangedListener(new TextWatcher() {

        @Override
        public void onTextChanged(CharSequence cs, int arg1, int arg2, int arg3) {
            // When user changed the Text
            ListFragment.this.mAdapter.getFilter().filter(cs);


        }

        @Override
        public void beforeTextChanged(CharSequence arg0, int arg1, int arg2,
                                      int arg3) {
            // TODO Auto-generated method stub
        }

        @Override
        public void afterTextChanged(Editable arg0) {
            // TODO Auto-generated method stub
        }
    });
}

private void fillArray() {

    mList.add("Lorem");
    mList.add("Ipsum");
    mList.add("Dolor");
    mList.add("Sit");
    mList.add("Amet");
    mList.add("Consectetur");
    mList.add("Adipiscing");
    mList.add("Elit");
    mList.add("Fusce");
    mList.add("Pharetra");
    mList.add("Luctus");
    mList.add("Sodales");

    Collections.sort(mList);
}
}

    


Ответы

Ответ 1



Для того, чтоб настроить свой фильтр, нужно решить некую последовательность: Создать свой custom адаптер. Привязать к нему интерфейс Filterable Настроить метод getFilter() под себя. Я сделал рабочий пример, для того чтоб вы могли потестить: Кастомный адаптер: public class myAdapter extends ArrayAdapter implements Filterable { private List allModelItemsArray; private List filteredModelItemsArray; private Activity context; private ModelFilter filter; private LayoutInflater inflater; public myAdapter(Activity context, ArrayList list) { super(context, R.layout.list_item, list); this.context = context; this.allModelItemsArray = new ArrayList(); allModelItemsArray.addAll(list); this.filteredModelItemsArray = new ArrayList(); filteredModelItemsArray.addAll(allModelItemsArray); inflater = context.getLayoutInflater(); getFilter(); } @Override public Filter getFilter() { if (filter == null){ filter = new ModelFilter(); } return filter; } static class ViewHolder { protected TextView text; } @Override public View getView(int position, View convertView, ViewGroup parent) { View view = null; String m = filteredModelItemsArray.get(position); ViewHolder viewHolder = null; if (convertView == null) { view = inflater.inflate(R.layout.list_item, null); viewHolder = new ViewHolder(); viewHolder.text = (TextView) view.findViewById(R.id.tvItem); view.setTag(viewHolder); } else { view = convertView; viewHolder = ((ViewHolder) view.getTag()); } viewHolder.text.setText(m); return view; } private class ModelFilter extends Filter { @Override protected FilterResults performFiltering(CharSequence constraint) { constraint = constraint.toString().toLowerCase(); FilterResults result = new FilterResults(); if(constraint.toString().length() > 0) { ArrayList filteredItems = new ArrayList(); for(int i = 0, l = allModelItemsArray.size(); i < l; i++) { String m = allModelItemsArray.get(i); if(m.toLowerCase().contains(constraint)) filteredItems.add(m); } result.count = filteredItems.size(); result.values = filteredItems; } else { synchronized(this) { result.values = allModelItemsArray; result.count = allModelItemsArray.size(); } } return result; } @SuppressWarnings("unchecked") @Override protected void publishResults(CharSequence constraint, FilterResults results) { filteredModelItemsArray = (ArrayList)results.values; notifyDataSetChanged(); clear(); for(int i = 0, l = filteredModelItemsArray.size(); i < l; i++) add(filteredModelItemsArray.get(i)); notifyDataSetInvalidated(); } } } MainActivity.class public class MainActivity extends AppCompatActivity { ListView lv; EditText editText; myAdapter adapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); lv = (ListView) findViewById(R.id.lv); editText = (EditText) findViewById(R.id.editText); ArrayList values = new ArrayList<>(); for (int i = 0; i < 25; i++) { values.add("Item:" + i); } adapter = new myAdapter(this, values); lv.setAdapter(adapter); editText.addTextChangedListener(new TextWatcher() { @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { } @Override public void onTextChanged(CharSequence s, int start, int before, int count) { } @Override public void afterTextChanged(Editable s) { adapter.getFilter().filter(s.toString()); } }); } } activity_main.xml list_item.xml