Страницы

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

пятница, 13 декабря 2019 г.

Чем отличается Comparable от Comparator?

#java


Когда использовать Comparable, а когда Comparator?
    


Ответы

Ответ 1



Классы реализуют Comparable, чтоб можно было потом сортировать за счёт реализации compareTo(Object) метода. Если класс реализует этот интерфейс, то можно использовать потом Collection.sort() или Arrays.sort(). Объекты будут сортироваться основываясь на реализации compareTo(Object) метода. Например: public class Country implements Comparable{ @Override public int compareTo(Country country) { return (this.countryId < country.countryId ) ? -1: (this.countryId > country.countryId ) ? 1:0 ; } } При вызове Collection.sort() на коллекции объектов этого класса, они будут сравниваться основываясь на compareTo(Country country). А Comparator используется, чтоб реализовать сортировку по кастомному полю, типо: List listOfCountries = new ArrayList(); [...] Collections.sort(listOfCountries,new Comparator() { @Override public int compare(Country o1, Country o2) { return o1.getCountryName().compareTo(o2.getCountryName()); } }); Будут отсортированы объекты основываясь на сравнении имён стран. Если резюмировать, то: Comparable - реализуется внутри класса. По сути, определяет обычный/естественный порядок сравнения объектов. Comparator - реализуется вне класса. Можно реализовать различные варианты сортировки, основанные на сравнении различных полей.

Эффективные способы работы с Excel

#c_sharp #excel


Работаю в консольных приложениях. у меня стоит Windows 10 и VS последняя актуальная
версия. Кое как,  методом тыка и вдумчивого поиска, разобрался с элементарными задачами:
прочитать данные в такой-то ячейке, записать данные в такую-то ячейку, и создать новую
книгу.
Использовал при этом:

using Excel = Microsoft.Office.Interop.Excel;


Для меня большая проблема состоит в том, что я не вижу документации для работы с
этой библиотекой. Если вы считаете, что есть более эффективные способы работы с Excel
через C#, то просветите меня. Буду рад, если вы понятно для меня изложите. 
    


Ответы

Ответ 1



Во-первых вам следует определиться, какой вам формат нужен: .xls или .xlsx. Они совершенно разные: xls — бинарный, а xlsx — это zip-архив XML файлов. Также, возможно, вам может подойти ods файл, который тоже представляет собой zip-архив XML файлов, но об этом ниже. Office COM Interop То о чём вы ведёте речь называется Office Interop. Иногда ещё к этому названию добавляют COM. Я сильно рекомендую его не использовать. Разве что только вы генерируете небольшие файлы на компьютере для себя. Почему? Очень медленный. Много утечек памяти. Ни в коем случае не используйте эту библиотеку для веб-сайтов или приложений, где на сервере генерируются файлы Office-форматов. У вас кончится оперативная память довольно быстро и сайт или приложение упадёт. Чтобы не быть голословным, могу сказать, что Microsoft сама не рекомедует использовать свою же Office COM Interop для автоматизации: Microsoft does not currently recommend, and does not support, Automation of Microsoft Office applications from any unattended, non-interactive client application or component (including ASP, ASP.NET, DCOM, and NT Services), because Office may exhibit unstable behavior and/or deadlock when Office is run in this environment. Что в вольном переводе значит: Корпорация Майкрософт не рекомендует и не поддерживает, автоматизации приложений Microsoft Office с помощью автоматических, не-интерактивных клиентских приложений или компонентов (включая ASP, ASP.NET, DCOM и службы NT), потому что офис может показывать нестабильное поведение и/или взаимоблокировку (deadlock), когда офис работает в этой среде. Требует наличия офиса определённой версии. На каждую машину, где будет работать ваше приложение. Рассмотрю xlsx файлы. Вроде уже прошло время, когда ещё надо поддерживать Office 2003 и ниже. Путаница с названием форматов Некорректно называть этот формат Excel. Excel — это одна из программ пакета Microsoft Office. (Также некорректно называть docx-файл Word). Называть формат xlsx Excel — приблизительно то же самое, что называть формат HTML — Internet Explorer. Office Open XML Что следует из того, что это zip-архив XML файлов? Что это значит? Это значит, что вы можете взять любой Open XML формат (все которые оканчиваются на x: docx, xlsx, pptx и т.д.), переименовать расширение на zip, открыть его. Затем можно посмотреть все нужные XML-файлы и можно даже попробовать их редактировать. (То же самое справедливо и для ods, но это OpenDocument-формат, а не Open XML!). Стандарт Open XML xlsx-файлы безусловно связаны с реализацией Microsoft. OpenXML форматы (все которые оканчиваются на x: docx, xlsx, pptx и т.д.) стали выходить после пакета офиса 2007 года. Microsoft опубликовало спецификацию в 2006 году, затем выпустило офис. А зачем Microsoft выпустило спецификацию? Для того, чтобы её реализовать мог кто угодно. Трудности в работе с Open XML Важное обновление. Все нижеописанные трудности крайне успешно решаются с помощью бесплатного инструмента от Microsoft под названием OpenXML SDK Productivity Tool. Он позволяет генерировать код для создания документа, генерировать код превращения одного документа в другой, валидировать документы с ошибками и показывать какие именно ошибки он содержит. Дело в том, что стандарт Open XML мягко говоря, громоздкий (занимает 6546 страниц), поэтому его просто не осилишь просто чтением стандарта. И с ним работать довольно тяжело. У вас есть объектная обёртка над различными тэгами XML. НО: При разработке ничто не подсказывает что и куда должно быть вложено. Вам приходится находить рабочие примеры и делать из них "винигрет" того, что работает. Основная трудность помимо того, что нет никакой подсказки до компиляции что с ним делать, что нет и никаких исключений и ошибок, если вы сгенерировали невалидную XML-структуру. Всё сильно усугляется тем, что офис просто не откроет ваш документ. Точнее откроет и выдаст "The file is corrupt and cannot be opened". То есть одна ошибка (вложили не тот элемент или чего-то не вложили) и даже гигантский документ не открывается. Вам приходится вникать в низкоуровневые детали того, как устроено хранение данных. То есть сама разработка сильно усложняется тем, что вам приходится писать код для казалось бы простых вещей. К примеру: Здесь вы узнаете, что строковые значения ради производительности хранятся в специальной таблице (SharedStringTable) и при добавлении и новой строки добавляется всего лишь порядкой номер в этой таблице (к примеру в ячейке будет хранится 1). То есть если вам надо добавить строковое значение в ячейку вам надо будет посмотреть в таблицу SharedStringTable есть ли там такая строка, и если нет — то создать запись в этой таблице, и вернуть новое число, если да — то взять порядковый номер. Для того, чтобы даты просто добавить ячейку как дату, надо помнить что они хранятся как числа (OLE Date), но весь курьёз заключается в том, что есть тип CellValues.Date, который не работает. Далее надо будет добавить несколько секций стилей и тогда всё заработает. Пример. Если вам ещё важен формат дат, то это тоже потребует времени разобраться, как именно хранятся форматы данных. Если вам надо будет просто удалить строку (row) или столбец (column), то придётся все значения (ниже или правее) переносить вручную. Библиотеки, основанные на Open XML В общем, если обернуть всё методами и потратить где-то 1-3 рабочих дня, то в целом можно и так работать. Чтобы избежать этих сложный вещей используйте уже готовые библиотеки, основанные на Open XML: ClosedXML EPPlus Open Document Format Помимо xls и xlsx существует также формат ods, который первоначально поддерживался в OpenOffice и затем LibreOffice. Cейчас форматы Open Document уже поддерживаются и Microsoft Office. Для этого работы с форматами Open Document существует библиотека AODL, для которой есть Nuget-пакет и примеры.

Ответ 2



Для этих целей лучше использовать OpenXML так как interop штука тормозная+ требует наличия office (Правда, можно поставить халявный office SDK). Голый OpenXML не очень приятный в использовании, поэтому для него существует удобная обертка EPPlus Примеры и документация тут. Правда, есть ограничение: Либа не поддерживает EXCEL формата 2003 года. Вроде, формат 2003 года сохранялся в бинарном виде, а не в структуре XML.

Ответ 3



Если работа с ексель файлами требует всего лишь работу с данными и в частности с данными на одной таблице/странице, я советовал бы не заморачиватся и просто вот этот скриптик использовать: Как просто работать с / открыть / изменить / сохранить Excel / CSV файлы В нем ты сразу работаешь с ексель файлом как с 2хмерным массивом ячеек. Минимум функционала. Если хочется больше -- советую ClosedXML как обертка к OpenXML. Так же по ссылке найдешь ответ на свой вопрос. В принципе, там написано то же, что написал Vadim Ovchinnikov. Просто другими словами + пример использования.

Можно ли предсказать максимальный размер png изображения?

#png #сжатие #clipboard


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


Ответы

Ответ 1



Вы задали сложный и интересный вопрос. Точного ответа на который скорее всего ни у кого нет. Хотя Вы можете поискать какие-нибудь оценки алгоритма сжатия DEFLATE, который используется в PNG. К слову, о PNG. Это формат хранения картинок со сжатием данных без потерь, в котором используется алгоритм DEFLATE. Метод не из самых простых. Его достаточно хорошее описание мной найдено было найдено здесь, здесь, частично тут и вот тут. Но в силу того, что мои интересы лежат немного в стороне от сжатия данных, вспоминать коды Хаффмана в различных вариациях я не стал, а избрал иной, более дешёвый подход к решению задачи. Он даёт худший результат и не точный результат. Но, при должном развитии идеи, которую я опишу, можно получить достаточно качественные нижнюю и верхнюю оценки. Нужно также понимать, что используюя данный подход, всегда можно будет подобрать такое изображению, которое будет выбиваться из общей динамики картинок. В силу того, что я не знаю, что и как Вы хотите оптимизировать, приведу лишь основные положения того, что можно делать. Всё ниже перечисленное снабжу кодом на python 2.7. Готового решения, к сожалению, я не дам, посколько не знаю целей. Но на основе моих наработок можно получить очень хороший результат. Насчёт точной оценки. Её скорее всего можно получить, изучив то, как ведут себя коды Хаффмана. Но это будет трудоёмкий процесс. Вопрос в том, насколько это Вам нужно. Общая идея подхода состоит в том, чтобы выявить зависимость , где -- параметры, которые будем задавать. Указанную зависимость мы будем получать, рассматривая некоторое множество изображений (у меня на компьютере есть база со стоковыми фотографиями профессиональных фотографов). Эти изображения мы будем рассматривать как объекты. Выше указанную зависимость мы будем строить, основываясь на выборке картинок. Если у Вас нет python и IDE для него, то я советую Вам pyCharm. Все вопросы по установке, либо возникающим проблемам Вы можете задавать в комментариях. Начиная работать, обязательно обратите внимание на pip -- установщик пакетов, который, кстати, очень хорошо интегрирован в pyCharm. Теперь насчёт изображений. В сети полно всяких дампов фоток, картинок и другого хлама. Вы легко их можете найти в гугле. Но проблема в том, что они могут быть в разных форматах. Эта проблема легко решает приведенеием их к *.png. Сделать это можно так: import Image import glob listOfImages = glob.glob("/home/hedgehogues/project/testPNG/*.jpg") # Получаем список имён файлов index = 0 for itemFile in listOfImages: img = Image.open(itemFile) img.save("/home/hedgehogues/project/testPNG/" + str(index) + ".png") index += 1 print index Код комментить не буду. Он вроде бы понятен. Итак, начал я с того, что решил поглядеть, что представляет собой размер картинки (далее картинка -- это некоторый экземпл базы картинок) в зависимости от её площади. К сожалению, здесь меня ждал грустный ответ. Это не очень хорошое распределение. Вы можете на него взглянуть: Но вообще говоря, даже глядя на такую картинку можно дать кое-какие оценки. Например, мы можем дать жёсткую оценку вёрхней границы. Она, как видно, из рисунка выражается следующим уравнением: Нижняя граница соответственно: Таким образом, размерах файлов при фиксированной площади может сильно варьироваться (практически в 3 раза) ~ 2.922. Для того, чтобы понять, что это много, можно сравнить 3 Мб и 9 Мб. 300 кБ и 1Мб. Разница ощутима. Апогея она достигнет, если рассматривать изображения очень больших размеров: 50 Мб и 150 Мб. Каково? Я приведу код, с помощью которого можно произвести рассчёты: import Image import os import matplotlib.pyplot as plt import numpy as np listOfSize = [] # Размер файла total = [] # Площадь картинки index = 0 for itemFile in range(0, 260): tmpSize = os.path.getsize("/home/hedgehogues/project/testPNG/" + str(index) + ".png") # Получаем размеры файла с картинкой img = Image.open("/home/hedgehogues/project/testPNG/" + str(index) + ".png") hLocal, wLocal = img.size # Размеры сторон картинки img = np.array(img.convert('L')) listOfSize.append(tmpSize) total.append(wLocal * hLocal) index += 1 print index plt.plot(total, listOfSize, linestyle = '', marker = 'x') plt.show() Следующим логичным шагом стало предположение о том, что, информация о длинах сторон картинок -- это совсем неинформативный признак, поскольку внутри каждой картинки кроется различная информация, а следовательно, самые информативные параметры будут связаны с интенсивностями пикселей. Здесь я оговорюсь, что далее, для простоты, все изображения я буду приводить к градациям серого. Разумеется, если этого не делать, а работать со всей информацией, то мы получим более качественные результаты. Но и сложность задачи возрастает в разы. Для учёта этой информации будем строить гистограммы изображений: Но, вот незадача, мои изображения оказываются очень большими (5000х5000) и их обработка занимает порядочное время. Поэтому я их жму. Получаю: Как видим, характер гистограммы сохраняется. Приведу код, который позволяет построить такого класса гистограммы: import Image import matplotlib.pyplot as plt import numpy as np index = 0 for itemFile in range(0, 250): img = Image.open("/home/hedgehogues/project/testPNG/" + str(index) + ".png") img.thumbnail((300, 300), Image.ANTIALIAS) # сжатие изображения img = np.array(img.convert('L')) y = np.histogram(img, bins = range(0, 256)) # bins задачёт количество градаций гистограммы x = np.arange(0, 1, 1./255) plt.plot(x, y[0]) plt.show() index += 1 print index Что со всем этим делать? Легко. Можно построить аппроксимацию этих гистограмм. Это можно делать по-разному. Например, при помощи нелинейного МНК. Я подобрал такую функцию, которая более или менее отвечает гистограммам. Все гистограммы для МНК нормируются по отрезку [0; 1]. Вот, что мы получаем. Несколько гистограмм и построенных для них МНК: Данная функция подбиралась методом научного тыка и выглядит следующим образом: Средствами python легко найдём неизвестные параметры, если минимизировать будем функцию, которая соответствует МНК: Для минимизации перебёрем все данные для каждой гистограммы. Все эти действия можно проделать самостоятельно: import Image import scipy.optimize as opt import matplotlib.pyplot as plt import numpy as np # Целевая функция def Model(a, x): sum = a[0] for coeff in range(1, len(a)): sum += a[coeff] * ((x * np.sin(x)) ** coeff + np.exp(x)) return sum index = 0 for itemFile in range(0, 250): img = Image.open("/home/hedgehogues/project/testPNG/" + str(index) + ".png") img.thumbnail((300, 300), Image.ANTIALIAS) img = np.array(img.convert('L')) weight = np.array(range(0, 10)) ErrorFunc = lambda tpl, x, y: 0.5 * (Model(tpl, x) - y) ** 2 # Функционал минимизации y = np.histogram(img, bins = range(0, 256)) x = np.arange(0, 1, 1./255) # Нормировка y = y[0] / float(np.max(y[0])) # Нормировка spl = opt.leastsq(ErrorFunc, weight, args = (x, y)) # Вычисление коэффициентов yy = Model(spl[0], x) plt.plot(x, yy) plt.plot(x, y) plt.show() index += 1 print index Получим веса w_i, а также имея площадь, можем построить ещё одно регрессионную модель, которая будет предсказывать размер конкртеного изображения. Сделать это можно по аналогии с тем, как построена регриссионная модель выше. Введём некоторую целевую функцию и функционал минимизации. Запишем исходные данные в виде: u_i = [w_i, area]. Теперь имея в качестве исходных данных пары (u_i, total_size), аналогичным образом обучим модель и получим некоторую зависимость. По указанной зависимости можно будет предсказывать предполагаемый размер файла. С другой стороны, можно воспользоваться более простой идеей и также, как и ранее, получить верхнюю и нижнюю оценку. Для этого посчитаем среднее значение элементов гистограммы. Построим график зависимости размера файла от среднего значения: Предвосхищая вопросы. Замечу, что на графике присутствуют два вида точек. Синие -- это множество, на котором производилось "обучение". Красные -- это точки, взятые из интернетов (картинки скачал). Как видим, они примерно укладываются в общую тенденцию. Разумеется, в данной ситуации у нас есть выбросы, которые нужно отдельно обработать и понять их причину. Кроме того, наша оценка средним значением гистограммы очень груба. А значит не следует претендовать на слишком качествеенный результат. Также отмечу, что построение гистограммы для отдельного изображения -- это затратная операция. Поэтому имеет смысл брать некотору аппроксимацию этой операции (например, брать на изображении случайные пиксели и строить гистограмму по ним). Приведу код: import Image import os import matplotlib.pyplot as plt import numpy as np def Model(a, x): sum = a[0] for coeff in range(1, len(a)): sum += a[coeff] * ((x * np.sin(x)) ** coeff + np.exp(x)) return sum listOfSize = [] listOfSizeTest = [] h = [] w = [] total = [] totalTest = [] data = [] # Перебираем все элементы из train set index = 0 for itemFile in range(0, 250): img = Image.open("/home/hedgehogues/project/testPNG/" + str(index) + ".png") img.thumbnail((300, 300), Image.ANTIALIAS) img.save("/home/hedgehogues/project/testPNG/_-1.png") tmpSize = os.path.getsize("/home/hedgehogues/project/testPNG/_-1.png") img = np.array(img.convert('L')) y = np.histogram(img, bins = range(0, 256)) total.append(np.mean(y[0] / float(np.max(y[0])))) index += 1 print index # Перебираем все элементы из test set (картинки из интернетов) for itemFile in range(0, 6): img = Image.open("/home/hedgehogues/project/testPNG/_" + str(itemFile) + ".png") img.thumbnail((300, 300), Image.ANTIALIAS) img.save("/home/hedgehogues/project/testPNG/_-1.png") tmpSize = os.path.getsize("/home/hedgehogues/project/testPNG/_-1.png") img = np.array(img.convert('L')) listOfSizeTest.append(tmpSize) y = np.histogram(img, bins = range(0, 256)) totalTest.append(np.mean(y[0] / float(np.max(y[0])))) plt.plot(total, listOfSize, linestyle = '', marker = 'x') plt.plot(totalTest, listOfSizeTest, linestyle = '', marker = 'x', color = 'red') plt.show()

Cтроки подключения в App.config и Web.config

#c_sharp #git #непрерывная_интеграция


Представим ситуацию:
В Visual Studio есть решение, которое состоит из 3 проектов. В каждом из проектов
в файле app.config лежит в открытом виде строка подключения базе данных, развернутой
в production среде.

Возникла необходимость работать с этим проектом в команде используя VSTS.

Хочу реализовать такой сценарий:
Разработчик синхронизирует себе репозиторий с этим решением, и в файлах app.config
строки подключения нет, он должен добавить туда строки подключения к своей локальной
тестовой базе данных.
После отправки кода обратно в репозиторий, в процессе CI и CD в файлы app.config
подставляются нужные строки подключения к рабочей базе данных.

Как можно реализовать это? 
    


Ответы

Ответ 1



В каждом из проектов в файле app.config лежит в открытом виде строка подключения базе данных, развернутой в production среде. Звучит опасно. Получается, предоставляя разработчику доступ на чтение репозитория, вы сразу доверяете ему доступ к боевой базе данных. Думаю, что доступ к боевой инфраструктуре нужно максимально ограничивать. Значит, из репозитория это нужно убрать. Предлагаю перенести ключевые параметры подключения (например, логин и пароль, или токен, или что там ещё может быть) из конфига в переменные окружения. Очень подробно о пользе такого подхода рассказывается в манифесте «12-факторное приложение» Многие CI-серверы умеют хранить такие переменные и инициализировать ими окружение перед запуском вашего приложения. Точно умеют GitLab CI, Jenkins и Travis (ссылки ведут на документацию по фичам). Доступ к просмотру и редактированию секретных переменных при этом будет у пользователей с максимальным уровнем доступа. Если не засветить переменные в логе сборки, то они не будут доступны случайному прохожему. Просто не дублируйте в лог команду для подключения к базе. Нужно будет также настроить, чтобы секретные переменные использовались только при деплое кода из вашей релизной ветки. Программист будет инициализировать окружение сам, можно написать какой-то скрипт ему в помощь.

Ответ 2



Бонусом ко всему сказанному. Есть возможность трансформировать app.config (равно как и любой другой файл) при сборке. Такая функциональность есть по умолчанию в проектах WCF сервисов для web.config, но её же можно добавить в другие типы проектов. Схема следующая: есть некий дефолтный пустой app.config, рядом с ним лежат дополнительные файлы с названиями app.Debug.config, app.Release.config, app.Test.config и так далее, которые содержат инструкции для трансформации исходного app.config. Если предположить, что в CI и CD используются только определённые конфигурации сборки (например, только Release), то можно в app.Release.config держать нужный набор настроек для работы с продуктивом. Разработчики же свободно могут править app.config локально и работать с Debug конфигурацией (если разработчикам необходимо работать и с Release, можно добавить новую конфигурацию CIRelease, которая будет использоваться только на билдсервере). Для использования данного подхода не в WCF проекте, нужно совершить несколько махинаций. Создаём файл ConfigurationTransform.targets следующего содержания: $(AllowedReferenceRelatedFileExtensions); .dll.config TransformConfig; $(ResolveReferencesDependsOn) $(TargetFileName).config Кладём файл в папку решения (уровень .sln) и подключаем его сразу после Microsoft.CSharp.targets. Можно в принципе подключать данный таск и напрямую в .csproj без создания дополнительного файла, но с доп. файлом автоматически решается проблема с наличием нескольких проектов, для которых нужно трансформировать app.config. Пример. Исходный app.config: Файл трансформации app.Release.config: В файле трансформаций используется операция SetAttributes, которая задаёт атрибуты для узла, который идентифицируется по атрибуту name (xdt:Locator="Match(name)"). Другие примеры трансформаций здесь. Вуаля, при сборке в конфигурации ConfigName, если рядом с app.config есть файл app.ConfigName.config, он будет использован для трансформации и сборка будет проведена с использованием промежуточного трансформированного файла. Пример таска отсюда. Еще бонусом небольшой лайфхак. Чтобы файлы трансформации в Solution Explorer не занимали много места, их можно показывать как дочерние от главного app.config: Для этого в .csproj нужно поправить регистрацию файлов трансформации, добавив тэг DependentUpon: App.config

Ответ 3



Как уже написал @NickVolynkin держать строки подключения к БД в App.config - плохая практика. Можно создать локальный файл конфигурации, например, ConnectStrings.config, в котором хранить строки подключения, и которого не будет в репозитории (для каждого разработчика он свой). Также написать класс-обработчик этой конфигурации, и при создании подключения к БД вызывать методы этого класса.

Ответ 4



Строки из app.config можно вынести в отдельный файл через атрибут configSource. В файлах web.config пишется что-то вроде этого: В файлах app.config пишем вот так: Во все проекты подключаем общий для всех файл connectionstrings.config как ссылку и настраиваем его копирование при сборке. В файле проекта должно получиться примерно вот это: Always Дальше этот файл можно добавить в .gitignore, позволив тем самым каждому разработчику иметь свой вариант этого файла. (Только не забудьте положить рядом файл вроде connectionstrings.sample.config чтобы разработчикам не пришлось каждый раз заполнять его с нуля методом проб и ошибок). При сборке этот файл надо будет генерировать на стороне сборочного сервера. Также можно при релизной сборке применить трансформацию к конфигу, заменив секцию connectionStrings целиком.

Как посмотреть исходный код программы?

#cpp #отладчик


Я хочу подправить исходный код, ничего серьезного, только вывод нескольких строк.
Программа написана скорее всего на С++. Мне использовать отладчик? Или как-то открыть
в IDE? Просто я не хочу запускать программу, хочу просто поковыряться в коде. И может
посоветуете какой нибудь? 
P.S. Сам файл - .exe
    


Ответы

Ответ 1



Исходный код раскрыть невозможно если для этого постарались обеспечить безопасность (особенно если это фирменная вещь). Но есть способы полностью или частично раскрыть код. IDA Pro - самый лучший из безплатных взломщиков, некоторые макросы возможно позволяют преобразовать код назад. Но не всегда. Особо хорошо раскрываются borland-продукты. Hiew.Exe бесплатная утилита, очень маленькая, позволяет править код на языке ассемблера. Можно править текстовые и целые константы. Можно ею даже сделать "перевод" программы на другой язык, затереть имя фирмы и т.п. Если есть PDB-файл, или подшита debug-info к файлу то код можно получить в среде разработки (если debug-info полная) редко можно использовать. Исходный код получить нельзя, но можно получить "номера строк и имена исходников", а так же имена/значения всех констант, локальных переменных, избежать "раздроблености функций" а так же получить классы с начинкой класса (почти все структуры кроме текста программы) что значительно упростит понимание работы программы. Для некоторых библиотек (dll) pdb-файлы можно скачать отдельно. Врядли уважающая себя фирма допустит утечку pdb своего стоящего продукта. Debug info, существует DebugInfo-информация встроеная в exe. Если есть такая информация, и соответствующая утилита (Например на Borland Delphi собран, и он есть в наличии), то можно сделать аналогичное предыдущему пункту. Но врядли уважающая себя фирма допустит такую "глупую" ошибку (аналогично pdb). Если файл написан на с# его можно почти полностью просмотреть в кодах с помощью disSharp (такие программы "подключают" в таблице импорта лишь mscorlib и всё). DisSharp плохо дизассемблирует некоторые части программы, но возможно его платная версия или платная версия подобных утилит раскрывает код лучше. Если файл написан на FoхPro, clipper и других подобный байт-кодовых языках - он раскрывается спец-утилитами (Refox например). Утилита exescope.exe ResourceHacker.exe и её-подобные утилиты позволяют смотреть шапку, подключенные библиотеки (по ним можно понять на чём писана программа) и редактировать ресурсы программы (ресурс-формы в.т.ч. delphi, иконки, картинки, таблицы ресурсо-строк). Если извесно чем создан код - думаю есть специальные утилиты способные его раскрыть (они платные и малодоступные). Опять-же, это при условии что нету паковщика кода (тогда нужно сначала применить депаковщик), шифровальщика/самомодифицирующегося кода. Если не разбит обфускатором так что не распутать. Чем больше код - тем сложнее разобраться. P.S. Лично моё мнение - раскрывается-взламывается всё, но на это нужно потратить много-много времени. Возможно год и более (зависит от опыта и инструментов, в свободном доступе хороших инструментов нету).

Ответ 2



Рад буду ошибаться, что такого способа для "новичка" просто нет. Вам нужно дизассемблеровать exe-файл в IDA или Hiew32, ну и там уже рассматривать код на языке asm(низкого уровня).

Ответ 3



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

Br не дружит с flexbox?

#css #flexbox


Верстал таблицу с помощью flexbox и заметил одну интересную особенность - элемент
br ничего не может внутри flexbox.

Пример:



.flexbox {
  display: flex;
  flex-wrap: wrap;
  border: 2px solid red;
  padding: 2px;
}
.item {
  width: 50px;
  height: 50px;
  margin: 2px;
  border: 2px solid blue;
}

.new-row, br {
  display: block;
  width: 100%;
  height: 0px;
}

Перенос с помощью div'a:

Перенос с помощью br:


В примере у div'а и br одни и те же свойства, но div переносит на новую строку элементы, а br - нет. Почему?


Ответы

Ответ 1



Таки переносит: .flexbox { display: flex; flex-wrap: wrap; border: 2px solid red; padding: 2px; } .item { width: 50px; height: 50px; margin: 2px; border: 2px solid blue; } .new-row, br { display: block; width: 100%; height: 0px; } br { content:'ПОЖАЛУЙСТА, ПЕРЕНЕСИ НА ДРУГУЮ СТРОКУ!'; }

Перенос с помощью div'a:

Перенос с помощью br:




Ответ 2



Реализация элемента br в CSS очень хорошо известна как тайна. Различные браузеры поддерживают различные свойства для этого элемента, с разным эффектом (хотя все они поддерживают display: none, чтобы удалить br из макета). Сам CSS признает эту странность еще в CSS1, выделив для неё целый подраздел, и даже сейчас в CSS3 он по-прежнему указан. Эта особенность flexbox не новая; про неё было известно с 2014 года. В основном, в текущих реализациях, br не создаёт основной блок, а вместо этого рассматривается как часть непрерывного текста, как описано в разделе 4 спецификации Flexbox, создавая невидимый элемент, который не может быть стилизован (потому что он невидимый). Это похоже на элемент display: table-cell, вызывающий создание вокруг себя анонимной таблицы, не смотря на то, что вы можете по-прежнему стилизовать элемент display: table-cell - в случае br элемент. Свойства стиля, которые вы применяете, не имеют эффекта, а настройки невидимого элемент выставляются по-умолчанию. В этом случае, поскольку br (в основном) пуст, и не имеет никакого свойства во flex'е, это приводит к невидимому элементу flex без каких-либо размеров и "прав", поэтому кажется, что br элемент полностью исчез. Еще в 2014 году CSSWG эта тайна была решена не путем изменения спецификации Flexbox, а просто добавлением специального определения br для css-display-3 для учета поведения, которое мы наблюдаем. Но такое определение не существует в текущей версии спецификации, а также FPWD (который был опубликован после резолюции!), ни HTML-спецификации, ни где-либо еще. Тем не менее, определение выглядит так, как в текущей спецификации css-display-3 (которая не определяет никаких новых свойств, а просто изменяет определение display): br { content: '\A'; display: contents; white-space: pre; } ...что означает, что элемент br не создаёт основной блок, а просто невидимый встроенный блок, содержащий одну новую строку. Поскольку это определение по-прежнему отсутствует в css-display-3, я бы пока ещё не стал рассматривать его. Ответ участника @BoltClock

Ответ 3



Тег br не имеет своей ширины и высоты, а после применения свойства flex он встал в ряд с остальными. В первом примере вы растягиваете блок на всю ширину, что позволяет занять ей всю строку. С br такой трюк не получится

В чём смысл существования reinterpret_cast?

#cpp #типы_данных #language_lawyer #неопределенное_поведение


В C++ существует оператор reinterpret_cast, смысл которого заключается в приведении
между типами, несовместимыми друг с другом.

Однако подобные преобразования нарушают strict aliasing rule, что провоцирует неопределённое
поведение. Те же преобразования, которые этого правила не нарушают, укладываются в
const_cast, static_cast и dynamic_cast.

В чём же тогда заключается смысл существования данного оператора, если его использование
нарушает стандарт?
    


Ответы

Ответ 1



reinterpret_cast используется не только для преобразования указателей одного типа в другой. Существует несколько разных преобразований. cppreference.com выделяет 11 вариантов преобразований: В свой собственный тип Указателя в интегральный тип Интегрального типа в указатель Типа std::nullptr_t в интегральный тип Указателя одного типа в указатель другого типа lvalue одного типа в ссылку на другой тип Указателя на функцию одного типа в указатель на функцию другого типа Указателя на функцию в void* Нулевого указателя любого типа в указатель любого другого типа rvalue указатель одного типа на функцию-член в указатель другого типа на функцию-член rvalue указатель члена-данных одного типа в указатель ну другой член-данных другого типа Type aliasing-правила затрагивают только пункты 5 и 6 и результат может быть безопасно использован (т.е. без нарушения strict-aliasing) в следующих случаях: Результирующий тип есть динамический тип исходного объекта Результирующий тип и динамический тип указывают на одинаковый тип T Результирующий тип есть знаковый или беззнаковый вариант типа исходного объекта Результирующий тип есть агрегатный тип или union, в котором содержится элемент или нестатический член данных, используемый в качестве исходного объекта. Т.е. можно получить указатель на структуру по указателю на её член. Результирующий тип есть базовый класс динамического типа исходного объекта и этот тип является standard-layout классом и не содержит нестатических членов-данных, и результирующий тип - первый базовый класс. Результирующий тип есть указатель на char, unsigned char или std::byte. Некоторые реализации ослабляют эти правила в качестве нестандартных расширений языка.

Ответ 2



Существует ровно один вид преобразования между несовместимыми типами, не нарушающий strict aliasing rule — из произвольного указателя на указатель типа char*. То есть reinterpret_cast позволяет представить произвольный объект в виде последовательности байт (так как стандартом гарантируется однобайтовая длина char-а). Вот пример грамотного использования этого вида преобразования: template void putIntoStream(const T* object, std::ostream& out) { out.write(reinterpret_cast(object), sizeof(T)); } Для всего остального есть memcpy().

Ответ 3



Несмотря на то, что использование reinterpret_cast в большинстве случаев приводит к неопределенному поведению, библиотеки могут использовать его в своих реализациях, тестируя их для конкретных компиляторов. Для пользователя библиотек поведение уже не будет неопределённым, т.к. оно проверено и документировано, но ему придётся учитывать список поддерживаемых компиляторов. Иногда это единственный способ разработки кросплатформенной библиотеки. Кроме того, всё еще есть случаи, когда приходится жертвовать переносимостью для достижения других целей (в частности, это актуально для микроконтроллеров).