Страницы

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

Показаны сообщения с ярлыком потоки-данных. Показать все сообщения
Показаны сообщения с ярлыком потоки-данных. Показать все сообщения

четверг, 9 апреля 2020 г.

Прочитать с середины файл без чтения его начала на Rust'е

#файлы #потоки_данных #filestream #rust #fstream

                    
let f = File::open("file").unwrap();
let reader = BufReader::new(f).seek(io::SeekFrom::Start(2));
for b in reader.iter().next() {
    println!("{}", b);
}


Выводит то, что находится внутри io::SeekFrom::Start, т.е. 2.
    


Ответы

Ответ 1



Какой-то странный цикл у вас. По идее должно быть как-то так: let f = File::open("file").unwrap(); let mut reader = BufReader::new(f); reader.seek(io::SeekFrom::Start(2)).unwrap(); for b in reader.bytes() { println!("{}", b); } Метод seek() возвращает Result, то есть новую позицию в файле. Он вызывается на &mut self, значит reader должен быть mut, иначе не заработает. Что делает ваш код: вы открываете файл и смещаете указатель на 2 байта, сохраняя Result в reader. Потом вы преобразовываете Result в итератор с помощью iter() и вызываете на итераторе next(), получаете Option, равный Some(2). А потом по опции итерируете (Option<_> реализует IntoIterator, так что этому типу можно итерировать). Итератор весело выдаёт один элемент — 2. Чтобы избежать подобных ошибок в будущем, внимательно читайте документацию на используемые трейты и типы: ни в трейте Read, ни в типе BufReader нет метода iter(), однако в Read есть метод bytes(), который вам был нужен. А вот метод Seek::seek возвращает Result. Кроме того стоит больше прочитать про интерфейс итераторов, так как вы, судя по всему, до конца не поняли эту идею, раз вызываете на итераторе метод next() явно.

воскресенье, 29 марта 2020 г.

Преобразование из String в массив байтов и обратно

#java #кодировка #потоки_данных


Написал на Java следующую последовательность действий:


Получаю из строки с кириллицей массив байтов

byte[] bytes="новая строка".getBytes();

Получается следующий массив: 

[-19, -18, -30, -32, -1, 32, -15, -14, -16, -18, -22, -32]
Передаю его на вход классу ByteArrayOutputStream

ByteArrayOutputStream baos=new ByteArrayOutputStream();
baos.write(bytes);

Выполняю обратное преобразование из массива байтов в строку

System.out.println(baos.toString());

Программа выводит в консоль текст новая строка


Вопрос: так как кириллица в юникоде имеет кодепойнты, превышающие 1 тысячу (кодепойнт
буквы А, к примеру, равен 1040), а байт в Java может принимать значения от -128 до
127, следовательно при попытке преобразовать строку в массив типа byte должна происходить
потеря информации, как следствие - при вызове метода toString() строка должна восстановиться
некорректно. Но этого не произошло. В чем тут причина?
    


Ответы

Ответ 1



Это не юникод. String.getBytes() использует кодировку по-умолчанию платформы: Encodes this String into a sequence of bytes using the platform's default charset, storing the result into a new byte array. Кодировка по-умолчанию задается настройками Java, ее можно проверить с помощью: System.getProperty("file.encoding"); Для получения байтов в юникоде, задайте кодировку явно: byte[] bytes="новая строка".getBytes("UTF-8"); Получится больше 12 байтов. Обновление по вопросам в комментарии: Разве UTF-8 выдает байты, эквивалентные юникодовскому представлению? У юникода бывают разные представления. UTF-8 — одно из них. Я знаю, что char выдает кодепойнты юникода. Если вывести System.out.println((byte)'н'), то это будет равно 61. Здесь можно посмотреть как строчная кириллическая «н» представляется в разных кодировках: https://unicode-table.com/en/043D/ UTF-8: Десятичное значение: 53437 Байты: 208 189 UTF-16BE: Десятичное значение: 1085 Байты: 4 61 Для char в Java, согласно спецификации (§3.1 Unicode) используется кодировка UTF-16. Это тоже двухбайтовая кодировка. Соответственно, когда Вы приводите char к byte Вы получаете младший байт в этой кодировке. Получить байты в "UTF-16BE" можно так: byte[] bytes="новая строка".getBytes("UTF-16BE"); Если вывести байты, как Вы предложили byte[] bytes="новая строка".getBytes("UTF-8"), то там первый байт равен -48, а не 61. Кодировка UTF-8, как указано ранее беззнаковые (от 0 до 255) байты: 208 и 189. Знаковые байты, соответственно, -48 и -67.

четверг, 19 марта 2020 г.

Захват видео с веб-камеры пользователя

#php #video #потоки_данных


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


Ответы

Ответ 1



Сложное решение, скажу я вам честно. Раньше реализовывал с помощью видео-серверов. На опыте это - Wowza Media Server, но дорогая, сцука. И обязательно флеш на стороне клиента. Но, конечно, можно сделать и приопретарное ПО, как это сделали мне. Еще как вариант: сейчас есть такая новинка, правда не во всех браузерах - возможность брать изображение с вебки javascript'ом. Суть заключается в том, что мы получаем картинку, каким-то образом кодируем её и отправляем туда, куда нам нужно.

Ответ 2



getUserMedia(js) + websockets. Из канваса берём base64 кадра и кидаем на сервак. Но это уж вообще извращение. Пример работы с getUserMedia

Ответ 3



haxevideo + crtmp + довести самому

воскресенье, 8 марта 2020 г.

Как распарсить Stream

#c_sharp #потоки_данных #filestream


Можно ли распарсить поток? То есть получить из него имя файла, путь к файлу, ну и
то что лежит в файле(в виде текста конечно)?
    


Ответы

Ответ 1



В общем случае такой информации в потоках нет. Эти сущности предоставляют собственно уже содержимое ресурса (например, файла) и некоторые базовые свойства (например, размер, см. свойство Length -- однако не все потоки это поддерживают), а также возможность навигации и чтения. Так что все, что вы можете вытянуть из стрима -- собственно его содержимое. Если же у вас есть именно FileStream, то полный путь к файлу, включая имя, можно взять из свойства Name. Содержимое удобнее всего прочитать через StreamReader: using (FileStream stream = ...) using (var reader = new StreamReader(stream)) { string content = reader.ReadToEnd(); }

четверг, 13 февраля 2020 г.

Выполнение нескольких потоков asynctask в цикле

#java #потоки_данных #android #android_asynctask


Разрабатываю приложение в котором необходимо выполнить несколько потоков в цикле.
Имеется 4 Spinner-а.Данные для каждого спиннера берутся из базы данных на сервере в
в каждом отдельном поток AsyncTasc. Мне нужно сделать чтобы в первом спиннере при выборе
пункта "Все" показывались результаты всех спиннеров. Для этого делаю несколько вложенных
в друг друга циклов. Но при вызове в каждом цикле new example().execute() данные не
успевают передаваться. При Debug-е данные показываются но при выполнении программы
в обычном режиме нет. 
Как сделать чтобы выполнение кода выполнялось только после окончания выполнения AsyncTasc?
    


Ответы

Ответ 1



класс AsyncTask так же имеет метод get() , который дожидается выполнения задачи , а затем возвращает ее результат , если преопределение onPostExecute() вам не подходит (пример использования) Так же это не совсем решение вашей проблемы , но если вы выполняете более одного потока параллельно , запускать их на выполнение следует через: asyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); Данное решение ускорит обработку фоновых задач , так как указывает запускать поток параллельно с уже запущенными . Дело в том , что с API11 запуск потока через execute() ставит все следующие после первого потоки в очередь и они дожидаются окончания выполнения предыдущих , то есть задачи выполняются последовательно , а не параллельно.

Ответ 2



onPostExecute(). есть такой метод в асинктаске. Он выполняется на UI потоке. В него и положите код, который надо выполнить после операций с AsyncTask

Ответ 3



Воспользуйтесь переопределенным методом onPostExecute, который выполнится после выполнения задачи в потоке doInBackground

Трансляция twitch.tv в android

#android #webview #потоки_данных #twitch


Делаю приложение игровой тематики, в которой одна из рубрик - прямые трансляции игр.
Собственно, есть прямые адреса на стримы, к примеру http://player.twitch.tv/?channel=starladder1

Что пытаюсь сделать я:

final WebView webView = (WebView) findViewById(R.id.webView);
webView.getSettings().setJavaScriptEnabled(true);
webView.getSettings().setUseWideViewPort(true);
webView.getSettings().setLoadWithOverviewMode(true);
webView.setWebChromeClient(new WebChromeClient());
webView.loadUrl(url);


Результат - открывается webview в котором пишется, что надо установить flash player..
Хотя в официальном приложении twitch воспроизводится всё отлично без флэша. Понимаю,
что возможно даже не в ту сторону копаю, но есть ли у кого какие догадки? Буду рад
любой помощи!  
    


Ответы

Ответ 1



Официальное приложение не использует WebView, а использует api твича и проигрывает видео плеером.

Ответ 2



Нашел решение для WebView. Все оказалось просто: webView.loadUrl("http://www.twitch.tv/" + chanelName+ "/popout");

суббота, 8 февраля 2020 г.

Разбить программу на потоки без сторонних библиотек [закрыт]

#c #многопоточность #потоки_данных


        
             
                
                    
                        
                            Закрыт. На этот вопрос невозможно дать объективный ответ.
Ответы на него в данный момент не принимаются.
                            
                        
                    
                
                            
                                
                
                        
                            
                        
                    
                        
                            Хотите улучшить этот вопрос? Переформулируйте вопрос,
чтобы на него можно было дать ответ, основанный на фактах и цитатах, отредактировав его.
                        
                        Закрыт 4 года назад.
                                                                                
           
                
        
Сабж. Понятно, что есть много хороших и разных библиотек для распараллеливания программ
на потоки и задачи. А как самому написать библиотеку для многопоточности на голом Си?
Что для этого нужно (просто план, пошагово)? Что почитать по этому поводу?    


Ответы

Ответ 1



Вам все равно придется иметь дело с библиотеками. API ОС под которую пишите это и есть библиотека. А всякое разнообразие других библиотек для многопоточности это просто обертки над API. И ещё в самом C нету поддержки многопоточности. Так что ответ ни как не получится на голом С писать многопоточный код. Даже в С++ в новом стандарте многопоточность реализована в стандартной библиотеке, а не в самом языке. Если хотите писать многопоточный код, то к примеру для *nix систем вам надо по изучать библиотеку pthread. Ну а для Windows нужно читать доку по API windows которая отвечает за многопоточность.

Улучшить быстродействие StreamReader.ReadLine()

#c_sharp #net #потоки_данных


Собственно есть много(~2GB) больших(~10MB) текстовых файлов. Каждая строка в файле
это запись лога. Нужно пройти по всем файлам и по всем строками и применить Regex(...).

И как и ожидалось Regex.IsMatch() прилично замедляет выполнение.
Но, по мимо этого профайлер показал что 44% времени тратится на sr.ReadLine()

вот стандартная часть кода:

using (StreamReader sr = File.OpenText(file))
{
    while ((line = sr.ReadLine()) != null) // <-- 44% Time
    {
        //... 
    }
}


Вопрос: есть способ как то быстрее читать файл построчно?
    


Ответы

Ответ 1



Насколько я смог понять отсюда и отсюда, File.OpenText создаёт StreamReader с довольно небольшим буфером для чтения. Метод ReadLine, в свою очередь, использует буфер именно этого размера. Поэтому первым делом я бы попробовал создать FileStream и StreamReader поверх него, задав размер буфера побольше: const int bufferSize = 16 * 1024 * 1024; // 16Mb FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, bufferSize, FileOptions.SequentialScan); using (StreamReader sr = new StreamReader(fs, Encoding.UTF8, true, bufferSize)) { ... }

Ответ 2



Обращение к файловой системе — это традиционное узкое место многих приложений. В отличие от C++, где есть нюансы, в C# метод ReadLine заметно не оптимизируется. Можете попробовать FileOptions.SequentialScan, но на многое не рассчитывайте. Вам поможет только SSD.

Ответ 3



Если воспользоваться winapi, то можно присобачить чтение через memory mapped file, что, теоретически, должно сильно повысить производительность. Ещё желательно правильно выставить набор флагов для открытия файла.

вторник, 28 января 2020 г.

Как правильно выполнить метод в отдельном потоке?

#c_sharp #wpf #потоки_данных #многопоточность


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


Ответы

Ответ 1



Для начала, структурируйте вашу программу. Часть, которая занимается представлением (View), должна быть отделена от управляющей части (ViewModel), и от различных движков (Model). Когда ViewModel решает, что нужно открыть файл, запрос на открытие и разбор содержимого должен уйти в движок разбора файла и построения объектной модели. Модель сама по себе вполне может быть однопоточной, а вот бизнес-логика пусть занимается перебрасыванием информации между потоками. Итак, на уровне модели ваш код прост и линеен: public Document ReadFromFilename(string filename) { using (var fs = new FileStream(filename, FileMode.Open)) return ReadFromStream(fs); } protected Document ReadFromStream(IStream stream) { ... На уровне VM вам нужно немного больше: public void async OpenDocumentAsync(string filename) { try { // установить статус ожидания this.ReadStatus = ReadStatus.Reading; // распарсить документ var doc = await DocumentHelper.GetDocumentAsync(filename); // создать VM-структуру var vmDoc = new VM.Document(doc); // установить текущую страницу и создать соответствующие подструктуры await vmDoc.SwitchToPageAsync(0); // доложить, что всё в порядке this.ReadStatus = ReadStatus.Ready; // не забыть обновить свойство DataContext'а this.Document = vmDoc; } catch (<что нужно>) { // доложить, что что-то пошло не так this.ReadStatus = ReadStatus.Failed; } } Метод DocumentHelper.GetDocumentAsync будет выглядеть как-то так: public Task GetDocumentAsync(string filename) { var t = new Task(() => model.ReadFromFilename(filename)); t.Start(taskSchedulers[model]); return t; }

Ответ 2



new Thread(() => MyMethod()).Start(); Метод в отдельном потоке... В чем проблема-то? С данными: int i = 0; new Thread(() => { MessageBox.Show(i.ToString()); }).Start(); Если .Net Framework 4 или выше, то ниже Вам написали пример. Также, что касается примера ниже, читайте про async/await

Ответ 3



На выбор: Task.Run(()=> /*code*/); Task.Factory.StartNew(Method, params);

Ответ 4



Здесь я описывал два способа взаимодействия GUI с рабочими потоками.

Реализация stdin и stdout

#python #python_3x #потоки_данных


В задаче (кроме самого алгоритма решения) необходимо реализовать прием данных через
stdin, а вывод через stdout. До этого обычно реализовывал прием через input, а вывод
через print или просто возвращал значение без печати через return. 
Как принять данные с помощью stdin/stdout не улавливаю. 
Огромная просьба, дать ссылку или пример кода, чтобы разобраться.
    


Ответы

Ответ 1



По умолчанию input() читает данные из stdin, print() печатает данные в stdout. Так что можете считать вашу задачу решённой. В Питоне stdin, stdout представлены sys.stdin, sys.stdout объектами (текстовые потоки, как правило), которые в общем случае могут быть любого типа (если их интерфейс достаточно file-like) и могут быть переопределены кем-угодно (IDLE, bpython, ipython, IDE, win-unicode-console, etc). Иногда достаточно предоставить объект, который поддерживает единственный метод .write(), если нужно только print() функцию поддерживать. В других случаях, даже экземпляр io.TextIOWrapper (тип sys.stdin/sys.stdout по умолчанию) может быть недостаточным, если .fileno() не возвращает настоящий file descriptor (см. детали в Redirect stdout to a file in Python?). При запуске Питона, sys.stdin/sys.stdout обычно указывают на стандартные потоки ввода/вывода, унаследованные от родительского процесса или полученные от консоли. Интерактивный ввод/вывод как правило связан с терминалом. Из оболочки легко перенаправить ввод/вывод из файла, канала (pipe) $ python ваша-программа.py <входной-файл # `sys.__stdin__` это входной-файл $ echo abc | python ваша-программа.py # `sys.__stdin__` это pipe (`echo` пишет с одного конца, мы читаем с другого) Работа напрямую с sys.stdin, sys.stdout такая же как с другими текстовыми файлами. Например, чтобы прочитать текстовые строчки из стандартного ввода и записать введённые символы (Unicode codepoint) в каждой строке в обратном порядке в стандартный вывод: #!/usr/bin/env python3 import sys for line in sys.stdin: print(line.rstrip('\n')[::-1]) Кодировка, используемая sys.stdin/sys.stdout, чтобы текст в байты превратить и обратно, может зависеть от окружения. Чтобы избежать кракозяб или UnicodeEncodeError исключения из-за работы с произвольными Unicode символами в Windows консоль и на других платформах следуйте по приведённым здесь ссылкам, которые показывают win-unicode-console (PEP 528 возможно упразднит этот пакет), LC_* (locale), PYTHONIOENCODING решения. print() это удобный wrapper вокруг sys.stdout.write(). input() часто можно рассматривать как wrapper вокруг sys.stdin.readline(), рассчитанный на интерактивный ввод (поддержка истории ввода, редактирования с помощью readline модуля, если доступен). Для продвинутой поддержки интерактивного ввода в терминале, посмотрите на prompt_toolkit: #!/usr/bin/env python from prompt_toolkit import prompt # $ pip install prompt_toolkit if __name__ == '__main__': answer = prompt('Give me some input: ') print('You said: %s' % answer)

Ответ 2



stdin и stdout это файлоподобные объекты, предоставляемые OS. Для чтения и записи в них нужно импортнуть sys - import sys. sys.stdin.read() использовать для чтения из stdin для записи в stdout можно использовать print(он так и используется - самый распространенный метод записи в stdout). т.е. print пишет в sys.stdout. Пример: import sys str = sys.stdin.read() print str

воскресенье, 26 января 2020 г.

Многопоточность или многонитевость?

#многопоточность #потоки_данных #терминология


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

В программировании есть два различных понятия stream и thread. 

Первое обозначает объект для выполнения операций (чаще всего передача данных или
их накопление), второе же обозначает объект, который позволяет выполнить некий программный
код параллельно с другими ветками кода. 

Первое слово переводится на русский язык как поток - тут всё логично, их так все
и называют. Второе же слово переводится как нить. 

Так почему в различного рода литературе и других медиа источниках это слово упорно
переводят, как поток? Более того, в русском языке прочно закрепился термин многопоточность,
который является аналогом (но никак не переводом) слова multithreading? Чем же можно
объяснить столь любопытное явление? Или всё таки есть разница между многопоточностью
и многонитевостью? А если есть разница, то какой в английском языке существует аналог
термину многонитевость?
    


Ответы

Ответ 1



Поток = нить (если мы говорим про "потоки" (Thread), а не потоки (Stream)). А про подмену понятия, можно почитать в Вики Перевод английского термина thread как «поток» в контексте, связанном с программированием, противоречит его же переводу «нить» в общеязыковом контексте, а также создает коллизии с термином stream («поток»). Однако, термин «поток» связан с переводами иностранной технической литературы, выполненными в 1970-х годах издательством «Мир». В настоящее время в «академических кругах» (то есть в учебниках, методических пособиях, курсах вузов, диссертациях и пр.) он считается эталонным. Термины же «нить», «тред» и т. п. считаются техническими жаргонизмами.

Ответ 2



Термин поток означал раньше process, а thread - то есть нить понятие возникло относительно недавно, когда стало выделяться понятиe нити как части процесса. Сейчас в общем понятие потока и нити синонимы, хотя надо понимать, что иногда под потоком может пониматься процесс. Но под нитью процесс никогда не понимается. Различия между процессом и нитью

Ответ 3



Помимо тупого калькирования, при котором термин переходит в другой язык в форме буквального перевода (возможно, даже частичного), существует ещё семантическое заимствование, при котором термином в целевом языке становится слово, лучше всего подходящее по смыслу. "Многонитевость" - это тупая калька с английского. Оригинальный термин просто переведён по частям. Более того, иногда можно встретить людей, которые используют в качестве термина частичную кальку - "многотредовость". "Многопоточность" - это полноценное заимствование на уровне семантики. Для обеих частей термина подобраны русские слова, идеально соответствующее смыслу самого понятия, а не того слова, которым оно обозначается в чужом языке. Очевидно, что слово "поток" подходит по смыслу гораздо лучше, чем слово "нить". Это даже сами американцы понимают, потому что когда они говорят о потоке комманд, они используют термин "control flow". Ну, а то, что русское слово "поток" соответствует сразу двум понятиям ("thread" и "stream"), вообще не проблема. Как правило, из контекста всегда можно понять, какое из этих двух понятий имеется в виду. А контекст - это всегда самое главное. От него смысл зависит в гораздо большей степени, чем от самого текста. Мой любимый пример, который это иллюстрирует: "Американцы слишком много жрут". Казалось бы, смысл фразы очевиден. А теперь представьте, что контекстом для неё является разговор двух автомобилистов, обсуждающих достоинства и недостатки различных автомобилей. В таком контексте смысл фразы был бы иным: "Автомобили американского производства потребляют слишком много топлива".

пятница, 24 января 2020 г.

Передавать и принимать поток. Socket

#c_sharp #сокет #xaml #uwp #потоки_данных


Записываю картинку с камеры в поток:

var stream = new InMemoryRandomAccessStream();
await _mediaCapture.StartRecordToStreamAsync(encodingProfile,stream);


Задача: как-то разбить этот на байты и передать его по сокету, а на приеме снова
создать поток? Получается своего рода трансляция.

Поток необходимо шифровать и дешифровать с помощью aes. Метод шифрования реализован,
принимает массив байт. Как передать туда поток?
    


Ответы

Ответ 1



Вот такой код получается: private async Task SendStreamAsync(MediaEncodingProfile encodingProfile, MediaCapture mediaCapture) { var socket = new DatagramSocket(); var outputStream = await socket.GetOutputStreamAsync(new HostName("example.com"), "12345"); var writeOnlyStream = new WriteOnlyStreamStream(outputStream); await mediaCapture.StartRecordToStreamAsync(encodingProfile, writeOnlyStream); return new CompositeDisposable {writeOnlyStream, outputStream, socket}; } private sealed class WriteOnlyStreamStream : IRandomAccessStream { readonly IOutputStream _outputStream; public WriteOnlyStreamStream(IOutputStream outputStream) { _outputStream = outputStream; } public IInputStream GetInputStreamAt(ulong position) { throw new NotSupportedException(); //or we can return empty stream } public IOutputStream GetOutputStreamAt(ulong position) { return _outputStream; } public ulong Size { get { return 0; } set { } } public bool CanRead => false; public bool CanWrite => true; public IRandomAccessStream CloneStream() { throw new NotSupportedException(); } public ulong Position => 0; public void Seek(ulong position) { } public void Dispose() { this._outputStream.Dispose(); } public IAsyncOperationWithProgress ReadAsync(IBuffer buffer, uint count, InputStreamOptions options) { throw new NotSupportedException(); } public IAsyncOperationWithProgress WriteAsync(IBuffer buffer) { return _outputStream.WriteAsync(buffer); } public IAsyncOperation FlushAsync() { return _outputStream.FlushAsync(); } } Что здесь происходит: Создали Udp сокет (в нем пакеты будут теряться, биться, никакой целостности) Создали спец-класс обертку, чтобы пропихнуть IOutputStream внутрь MediaCapture. Здесь есть варианты, можно вместо исключений возвращать пустой IInputStream Создали IDisposable, который надо будет закрыть после всех операций (используем Reactive Extensions). Как правильнее посоветовали в вопросах, здесь лучше использовать TCP сокеты. Для клиентской части будет всё 1-в-1, только классы немного поменяются. Для серверной части надо использовать класс StreamSocketListener (он есть в uwp), с которого уже слушать какой-нибудь порт.

Прослушивание массива Stream'ов в Java

#java #сокет #потоки_данных #epoll #android_bluetooth


Существует ли в Java какой-либо специфический механизм мультиплексирования событий
ввода-вывода, подобный epoll?

P.S. В частности меня интересует прослушка массива BluetoothSocket'ов (Android).
    


Ответы

Ответ 1



Ответ - нет. Если программа в Java многосокетная, обычно создаються Thread'ы на каждое соединение. Java - многоплатформенная система, и не на всех платформах может быть аналог epoll. PS. Попробуй java.nio.channels.Selector, теоритичечки он должен работать и с Bluetooth соединениями.

четверг, 23 января 2020 г.

Как организовать рестрим rtmp?

#php #python #потоки_данных #streaming #rtmp


У меня есть rtmp поток и rtmp сервер, на который нужно отправить этот поток с определенным
именем. Как лучше всего это можно организовать?(желательно на php или python, хотя
можно и со сторонними утилитами)
    


Ответы

Ответ 1



Cо сторонними утилитами Подобного проще всего достичь с помощью FFMpeg: /usr/bin/ffmpeg -re \ -i 'rtmp://src_stream:1935/play' \ -vcodec copy -acodec copy \ -f flv 'rtmp://dst_stream:1935/publish'; Например, эту командочку, можно было бы вызвать из любого удобного вам окружения. Более подробно про команды рассказано тут: FFmpeg Streaming Guide; FFmpeg for streaming; Онлайн вещание через Nginx-RTMP — несколько готовых рецептов; Про аргументы командной строки FFMpeg. Можно пойти немного дальше, и использовать nginx c nginx-rtmp-module. Streaming with nginx-rtmp-module Getting started with nginx RTMP Attempting to Stream a Webcam to an RTMP Server nginx-rtmp-module wiki: exec_push При этом nginx.conf всего скорее будет иметь вид: #user nobody; worker_processes 1; error_log logs/error.log debug; events { worker_connections 1024; } rtmp { server { listen 1935; ping 30s; notify_method get; application src { live on; exec_push ffmpeg -i 'rtmp://src_stream:1935/play' -vcodec copy -acodec copy -f flv 'rtmp://dst_stream:1935/publish' 2>> '/var/log/ffmpeg-$name.log'; } } } Hа python Решение на Python легко организовать через PyAV. Это питонячие биндинги к libav. О том что это такое и как это использовать можно почитать тут: Про обработку видео в Python. Про работу с RTMP в PyAV есть комментарий автора проекта: Can I use PyAV to built a RTMP retransmit-server?. Пример https://gist.github.com/w495/c4aa54e4783c2d3766407a5f4f7bc81d import av # Откроем ресурс на чтение input_resource = av.open( 'rtmp://src_stream:1935/play' ) # Откроем ресурс на запись. output_resource = av.open( 'rtmp://dst_stream:1935/publish', mode='w', format='flv' ) # Список потоков входного ресурса: видео и аудио input_streams = list() # Список потоков выходного ресурса: видео и аудио output_streams = list() # Для входного и выходного ресурсов возьмём поток видео. for stream in input_resource.streams: if stream.type == 'video': input_streams += [stream] # Создадим видео-поток для выходного ресурса. Кодек `h264`. output_streams += [output_resource.add_stream('h264')] break # Для входного и выходного ресурсов возьмём поток аудио. for stream in input_resource.streams: if stream.type == 'audio': input_streams += [stream] # Создадим аудио-поток для выходного ресурса. Кодек `aac`. output_streams += [output_resource.add_stream('aac')] break # В этом списке будем хранить пакеты выходного потока. output_packets = list() # Применим «инверсное мультиплексирование». Получим пакеты из потока. for packet in input_resource.demux(input_streams): # Получим все кадры пакета. for frame in packet.decode(): # Сбросим PTS для самостоятельного вычислении при кодировании. frame.pts = None # Закодируем соответствующие кадры для выходных потоков. for stream in output_streams: if packet.stream.type == stream.type: output_packets += [stream.encode(frame)] # Сбросим буфферы кодировщика. ??? Нужно ли ??? for stream in output_streams: output_packets += [stream.encode(None)] # Для каждого пакета применим «прямое мультиплексирование». for packet in output_packets: if packet: output_resource.mux(packet) output_resource.close() Это немного искусственный пример, и нужно помнить про некоторые особенности потокового видео. В частности, — оно потенциально бесконечно, и это означает, что вы не сможете использовать списки пакетов и кадров (list). В вашей задаче, всего скорее, будут нужны генераторы последовательностей и итераторы: Python Practice Book: Iterators & Generators; Python wiki: Iterator; Python wiki: Generators.

Загрузка видео на сайт в виде Blob

#javascript #html #потоки_данных #youtube #blob


Если посмотреть на youtube.com, то url у любого видео выглядит вот так: blob:https://www.youtube.com/17c9289e-4450-4ea0-a0bd-56570172d62a.
Это говорит о том, что видео было загружено в виде бинарного объекта и обработано функцией
window.URL.createObjectURL(). 

Я не понимаю как они это делают со всем видео целиком, ведь оно большого размера,
а url у видео не меняется до конца времени проигрывания (если плеер не решил поменять
качество или сервер). 

Вопрос заключается в том, как загружать видео на клиент в виде Blobа так, как делают
это на youtube.com.
    


Ответы

Ответ 1



D-side, подсказал посмотреть в сторону MediaSource. Этот объект позволяет задать url объекта video как window.URL.createObjectURL(mediaSource). Это позволяет задавать источник в виде Blob'а, но с одним важным свойством: мы можем догружать данные в mediaSource, например, при получении продолжения видео по AJAX или каким-либо другим способом. Пример работы с MDN: var video = document.querySelector('video'); var assetURL = 'frag_bunny.mp4'; var mimeCodec = 'video/mp4; codecs="avc1.42E01E, mp4a.40.2"'; if ('MediaSource' in window && MediaSource.isTypeSupported(mimeCodec)) { var mediaSource = new MediaSource; video.src = URL.createObjectURL(mediaSource); mediaSource.addEventListener('sourceopen', sourceOpen); } else { console.error('Unsupported MIME type or codec: ', mimeCodec); } function sourceOpen (_) { var mediaSource = this; var sourceBuffer = mediaSource.addSourceBuffer(mimeCodec); fetchData(assetURL, function (buf) { sourceBuffer.addEventListener('updateend', function (_) { mediaSource.endOfStream(); video.play(); }); sourceBuffer.appendBuffer(buf); }); }; Метод рабочий, но есть свои приколы, например, 'video/mp4; codecs="avc1.42E01E, mp4a.40.2"' - единственный майм кодек, который работает и в Chrome и в Mozilla. Если хочется работать с webm: 'video/webm; codecs="vp9,vorbis"' в Mozilla, то придется включать флаг в about:config, что не очень приятно для пользователя.

Возможно ли записывать и читать из одного экземпляра Stream?

#c_sharp #потоки_данных


Мне не хватает фундаментального понимания такой штуки, как Stream. Фраза "абстракция
над последовательностью байтов", которую встречаю везде, не спасает.

Как известно, ничто не мешает написать что-то вроде этого:

var fs = File.Open("file.txt", FileMode.OpenOrCreate, FileAccess.ReadWrite);
var sw = new StreamWriter(fs);
var sr = new StreamReader(fs);


Здесь и пишущему, и читающему Stream'ам присваивается один и тот же экземпляр базового
(не в смысле ооп, просто как поле). Несмотря на то, что они будут вести свои счетчики
передвижения по файлу, свои буферы, интуитивно понятно, что можно записывать в один
и тот же файл (=базовый Stream) и читать из него условно в один момент времени, ничего
в этом такого нет.

А что представляет собой Stream применительно к сетевому взаимодействию?

У меня возникла задача удаленно, через SSH, взаимодействовать с shell лунукса. Насколько
правильно (неправильно) и для передачи данных, и для их чтения с сервера использовать
один и тот же экземпляр Stream (как в случае с файлом)?

В случае, если Stream представляет собой только пришедшие с сервера байты, то нет
смысла туда что-то еще писать. А если это "канал", поток байтов клиент-сервер, то есть
смысл. Или все зависит от конкретной реализации наследника класса Stream?

Словом, немного запутался.
    


Ответы

Ответ 1



Фраза "абстракция над последовательностью байтов", которую встречаю везде, не спасает. И тем не менее именно эта фраза и должна спасать :) Возможно, цитата с MSDN привнесёт больше ясности: Предоставляет универсальное представление последовательности байтов. Этот класс является абстрактным. То есть, Stream - это абстрактный класс, представляющий последовательность байтов (да, я просто переставил слова в предыдущей цитате). То есть, в вашем случае - это последовательность пришедших с сервера байтов. Update Входящий поток - это набор данных, пришедших с сервера. Вот, грубо (очень грубо) говоря, вы скачиваете файл потоком. Вы можете писать в этот поток - но вы будете писать в скачиваемый файл, на сервере этот файл останется неизменным. Точно так же вы можете писать в локальный файл. Просто в случае потока, получаемого с сервера, вы пишете в свой экземпляр файла. Но вы же можете отправить исходящий поток, и таким образом организовать канал самостоятельно.

Ответ 2



Применительно к сетевому взаимодействию - NetworkStream - это обертка над сокетом. Все, что пишется в NetworkStream - уходит на сервер. То, что прислал сервер - можно прочитать из того же экземпляра NetworkStream. Насколько правильно (неправильно) и для передачи данных, и для их чтения с сервера использовать один и тот же экземпляр Stream (как в случае с файлом)? Это нормально, и именно так и задумано. И NetworkStream, и лежащие под ними сокеты - это двунаправленные каналы.

среда, 22 января 2020 г.

Как считать из потока текстовый файл ?

#java #потоки_данных


Нужно считать текстовый файл из потока, как это сделано с картинкой.
Важно: считывание в ОП а не в файл.

ZipInputStream zis;
BufferedImage tmpImage;     
tmpImage = null;
tmpImage = ImageIO.read(zis);
    


Ответы

Ответ 1



Используя только классы из стандартной библиотеки Java, избежать циклов и прочего говнокода не получится никак. Имея произвольный InputStream, прочитать из него текст в виде строки можно следующим образом: import java.nio.charset.Charset; import java.io.*; static public String readTextFromInputStream(InputStream in, Charset cs) { StringBuilder text = new StringBuilder(); BufferedReader reader = new BufferedReader(new InputStreamReader(in, cs)); String line = null; String newline = System.getProperty("line.separator"); while ((line = reader.readLine()) != null) { text.append(line); text.append(newline); } return text.toString(); } Где параметр cs означает предполагаемую кодировку текста. Использовать примерно так: String text = readTextFromInputStream(in, Charset.forName("CP1251")); Если хотите избежать всего этого говнокода, у вас два варианта: либо подключить внешние библиотеки (к примеру, Apache Commons IO), либо использовать нормальные языки для JVM, к примеру, Scala, в которой решение займет одну строку: def readFromInputStream(in: InputStream, cs: Codec) = Source.fromInputStream(in)(cs).mkString Дополнение 1. Если хочется сохранить разбиение на строки, то модифицируем первоначальный вариант функции readFromInputStream следующим образом (так, чтобы она возвращала список строк): import java.util.List; import java.util.ArrayList; static public List readLinesFromInputStream(InputStream in, Charset cs) { List lines = new ArrayList(); BufferedReader reader = new BufferedReader(new InputStreamReader(in, cs)); String line = null; String newline = System.getProperty("line.separator"); while ((line = reader.readLine()) != null) { lines.add(line + newline); } return lines; }

Многопоточный перебор массива

#c_sharp #многопоточность #потоки_данных


Здравствуйте. Есть следующий код, который загружает файл со словами в массив, допустим,
содержание файла такое:
Привет
Пока
Магазин
Телефон
Монитор
.... // и т.д. Очень много слов 
Нужно сделать потоки для этого кода. Я пока не разобрался, как.
class Test
{

    static string Text;
    static string[] ReadFile;
    static int Threads;

    static void Main()
    {

        Console.Write("Введите слово которое необходимо проверить: ");
        Text = Console.ReadLine();

        Console.Write("Введите количество потоков: ");
        Threads = Convert.ToInt32(Console.ReadLine());

        ReadFile = System.IO.File.ReadAllLines("slova.txt");

        for (int i = 0; i < Threads; i++) // ну типо потоки запускаем
        {
            (new Thread(new ThreadStart(Slova))).Start();
        }
    }

    static void Slova()
    {

       for (int i = 0; i < ReadFile.Length; i++)
       {
            if (ReadFile[i] == Text)
            {
              Console.Write("Слово " + Text + " успешно найдено в файле " + ReadFile);
            }
       }
    }
}

Дело в том, что этот код находит строку в файле и сверяет её с переменной Text столько
раз, сколько установлено потоков, то есть если потоков 50, то он возьмет первую строку
из файла и проверит её 50 раз, далее вторую и так далее, и сообщение о нахождении строки
тоже 50 раз.
Можно сделать в место for 
foreach (string textline in ReadFile) { .. } // тоже самое будет

Как это исправить? Чтобы потоки хорошо работали. Я не очень разбираюсь в C#. Помогите,
пожалуйста.    


Ответы

Ответ 1



Вы запускаете на каждую итерацию цикла новый поток. Вот и получается 50 потоков. Используйте готовый мультипотоковый цикл. Parallel.For(0, length, i => { // Тело цикла. }); подробней о Parallel.For Или разделите цикл на N частей по длине и в каждой создайте поток. Получите N-поточный цикл.

Ответ 2



Можно использовать PLINQ. Удобная вещь особенно для многопоточной обработки данных. Вот еще одна интересная статья пэтой теме.

вторник, 31 декабря 2019 г.

C++. Программа пропускает строчку кода(считывание переменной)

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


Доброго времени суток.
Возникла проблема с С++. Если кратко - в одной строчке не происходит считывание с
помощью потока ввода cin.
Код ниже. Место где происходит ошибка - обозначено комментарием. Пробовал очищать
поток перед считыванием user_num_to_sum с помощью cin.clear() - don't help.

#include  //cin, cout
#include  //_getch()
#include  //vector

using std::cout;
using std::cin;
using std::vector;


int main () {
    vector numbers; // вектор из целых чисел
    int num = 0; // число которое заносим в конец вектора
    int user_num_to_sum = 0; // число элементов вектора для суммирования(пример:
если число 3, то суммируем первые 3 элемента)

    cout << "Write a few numbers: \n";
    while(cin >> num) {
        numbers.push_back(num);// заносим числа в вектор
        }
    cout << "How much elements of vector do you want to sum?\n";
    cin >> user_num_to_sum; // ERROR: программа пропускает данную строчку и выполняет
следующую подставляя в user_num_to_sum значение 0, которое было задано при инициализации.
    cout << "The sum of first " << user_num_to_sum << " numbers -> ";

//код еще не готов полностью, программа смысла не имеет

    _getch();

    return 0;
}


Я и останавливаю цикл while(cin >> num) вводом ошибочного символа '|'. Данный приём
использует в своей книге Страуструп. Вот только потом почему-то после остановки цикла
не срабатывает считывание целого числа user_num_to_sum.

P.S. Сработал вариант с использованием cin.clear(), но только в случае завершения
ввода данных в вектор путём нажатия Ctrl+Z. 
Если же завершить его путём ввода неверных данных(к примеру '|' при считывании данных
типа int), то cin.clear() не срабатывает. Вопрос: почему?
    


Ответы

Ответ 1



while(cin >> num) { // Пока мы можем прочитать int, читаем его ... // и что-то делаем } // Вышли из цикла, т. к. int прочитать нельзя ... // Тут мы ничего не читали cin >> user_num_to_sum; // Опа! Чиатем ещё int Но ведь состояние потока не изменилось - int как нельзя было прочитать, так и сейчас нельзя. Если ввод последовательности чисел заканчивается неким нечисловым вводом, следует прочитать это нечто как строку и только потом считывать следующее число. Если же ввод завершался нажатием ctrl+z, то там вроде вообще eof выставляется. Также для сброса маркера ошибки надо перед чтением вызвать cin.clear().

Ответ 2



while(cin >> num) { numbers.push_back(num);// заносим числа в вектор } std::string s; cin.clear(); // сбрасываем ошибку в cin cin >> s; // убираем из cin нечисловые символы cout << "How much elements of vector do you want to sum?\n"; cin >> user_num_to_sum; // ERROR: программа пропускает данную строчку и выполняет следующую подставляя в user_num_to_sum значение 0, которое было задано при инициализации. Вот так Ваш код будет работать корректно при завершении заполнения вектора любым нечисловым символом. Собственно, ответ на последний вопрос: cin.clear() сбрасывает флаги (состояние) ошибки в потоке, но последний введенный символ (группа символов) в нем остается, поэтому их нужно оттуда убрать, например в какую-то ненужную строку. П.С. Вопрос получился неожиданно интересным и заслуживает поощрения в виде плюса. П.П.С. Нашелся вариант без лишней переменной (проверил, нужно #include ) cout << "Write a few numbers (end with any non-number input): \n"; while(cin >> num) { numbers.push_back(num);// заносим числа в вектор } cin.clear(); // сбрасываем флаг ошибки cin.ignore(std::numeric_limits::max(), '\n'); // пропускаем все до символа новой строки cout << "How much elements of vector do you want to sum?\n"; cin >> user_num_to_sum;

В чем разница между методами map и flatMap в Java 8?

#java #потоки_данных #java_8 #java_stream #java_faq


Чем отличаются методы Stream.map и Stream.flatMap друг от друга?
    


Ответы

Ответ 1



И map и flatMap могут быть применены к стриму Stream и оба возвращают стрим Stream. Разница заключается в том, что операция map создает одно выходное значение для каждого входного значения, тогда как операция flatMap создает произвольное число(ноль или больше) значений для каждого входного значения. Операция map(О работе map на русском) в качестве аргумента принимает Function(например, лямбду), которая вызывается для каждого значения входного стрима(который ), преобразует это значение в другое значение, и посылает получившееся значение в выходной стрим(который ). Т.е. map для каждого объекта в стриме возвращает по 1 объекту, потом преобразует все объекты в итоговый стрим. Операция flatMap(О работе flatMap на русском) принимает функцию (которая преобразует каждое значение входного стрима в стрим), применяет ее к каждому элементу, и на выходе возвращает стрим с одним, несколькими или ни c одним из элементов для каждого элемента входящего стрима. Т.е., flatMap возвращает по стриму для каждого объекта в первоначальном стриме, а затем результирующие потоки объединяются в исходный стрим. Пример для map: есть одномерный массив array с числами. Нужно получить массив из первоначального массива, в котором к каждому числу прибавлена 1. Решение: array = Arrays.stream(array) //преобразовываем массив в стрим .map(i -> i+1) //преобразовываем каждый элемент стрима .toArray(); //преобразовываем стрим в массив map к каждому значению стрима прибавляет 1, потом все новые значения преобразует в итоговый стрим. Пример для flatMap: есть двухмерный array с числами, надо получить одномерный массив с числами. Решение: secondArray = Arrays.stream(array) .flatMapToInt(i -> Arrays.stream(i)) //преобразовываем Stream в Stream .toArray(); // преобразовываем Stream в int[] В этом примере создается стрим состоящий из каждого элемента первоначального массива - т.е. стрим из массивов. Потом с помощью i -> Arrays.stream(i) преобразовываем каждый элемент(который является массивом) стрима в стрим с числами. После этого flatMap собирает все получившееся стримы в один итоговый стрим.