Определите размер канала, не называя чтение ()

NullPointerException s - исключения, возникающие при попытке использовать ссылку, которая указывает на отсутствие местоположения в памяти (null), как если бы она ссылалась на объект. Вызов метода по нулевой ссылке или попытка получить доступ к полю нулевой ссылки вызовет функцию NullPointerException. Они наиболее распространены, но другие способы перечислены на странице NullPointerException javadoc.

Вероятно, самый быстрый пример кода, который я мог бы придумать для иллюстрации NullPointerException, be:

public class Example {

    public static void main(String[] args) {
        Object obj = null;
        obj.hashCode();
    }

}

В первой строке внутри main я явно устанавливаю ссылку Object obj равной null. Это означает, что у меня есть ссылка, но она не указывает на какой-либо объект. После этого я пытаюсь обработать ссылку так, как если бы она указывала на объект, вызывая метод на нем. Это приводит к NullPointerException, потому что нет кода для выполнения в местоположении, на которое указывает ссылка.

(Это техничность, но я думаю, что она упоминает: ссылка, которая указывает на null, равна 't то же, что и указатель C, указывающий на недопустимую ячейку памяти. Нулевой указатель буквально не указывает на в любом месте , который отличается от указаний на местоположение, которое оказывается недопустимым.)

8
задан Chris Upchurch 8 April 2009 в 19:30
поделиться

12 ответов

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

2
ответ дан 5 December 2019 в 05:19
поделиться

В зависимости от Вашей реализации Unix ioctl/FIONREAD мог бы добиться цели

err = ioctl(pipedesc, FIONREAD, &bytesAvailable);

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

16
ответ дан 5 December 2019 в 05:19
поделиться

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

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

Таким образом, я боюсь, что нет никакого общего решения.

4
ответ дан 5 December 2019 в 05:19
поделиться

Некоторые реализации UNIX возвращают число байтов, которые могут быть считаны в st_size поле после вызова fstat(), но это не портативно.

6
ответ дан 5 December 2019 в 05:19
поделиться

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

Каналы не seekable, и, и при этом не возможно отложить данные в конец чтения канала.

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

2
ответ дан 5 December 2019 в 05:19
поделиться

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

Можно сделать это на двух шагах. Во-первых, используйте выбор () системный вызов, чтобы узнать, доступны ли данные или нет. Пример здесь: http://www.developerweb.net/forum/showthread.php?t=2933

Во-вторых, если выбор говорит Вам, что данные доступны, назовите чтение () однажды, и только однажды, с большим размером блока. Это будет только для чтения, поскольку много байтов доступны, или до размера Вашего блока, какой бы ни меньше. Если выбор () возвратит true, читайте (), то будет всегда возвращаться сразу же.

2
ответ дан 5 December 2019 в 05:19
поделиться

Я не думаю, что это возможно. Каналы представляют потоковый протокол, а не ориентированный на пакет. IOW, если Вы пишете в канал дважды, однажды с, скажем, 250 байтами и однажды с, скажем, 520 байтами, нет никакого способа сказать, сколько байтов Вы доберетесь от другого конца в одном запросе чтения. Вы могли добраться 256, 256, и затем остальные.

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

0
ответ дан 5 December 2019 в 05:19
поделиться

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

Какую платформу Вы используете?

0
ответ дан 5 December 2019 в 05:19
поделиться

Нет никакого портативного способа сказать объем данных, прибывающий из канала. Единственная вещь, которую Вы могли сделать, состоит в том, чтобы считать и обработать данные, как это прибывает.

Для этого Вы могли использовать что-то как кольцевой буфер

0
ответ дан 5 December 2019 в 05:19
поделиться

Вы можете заключить его в объект с буферизацией, которую можно перемотать. Это возможно только для небольших объемов данных.

Один из способов сделать это в C - определить stuct и обернуть все функции, работающие с конвейерами для вашей структуры.

0
ответ дан 5 December 2019 в 05:19
поделиться

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

0
ответ дан 5 December 2019 в 05:19
поделиться

В Windows можно всегда использовать PeekNamedPipe, но я сомневаюсь, что это - то, что Вы хотите сделать так или иначе.

0
ответ дан 5 December 2019 в 05:19
поделиться
Другие вопросы по тегам:

Похожие вопросы: