Получение смешанных носителей через сокет Java. Твой лучше? - PullRequest
1 голос
/ 01 марта 2011

Я собираюсь дать упражнение по программированию на Java, и я бы хотел, чтобы мои студенты сами открыли для себя сущность HTTP, а не чтобы URLConnection делал всю работу за них.Чтобы оценить сложность, я придумал следующий фрагмент, который анализирует ответ (imho, одна из самых сложных частей задания), который возвращает, например, "HTTP / 1.1 200 OK" ,добавьте в вектор заголовки * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * вз} проб}первый байт содержимого, так что DataInputStream или InputStreamReader впоследствии можно безопасно построить поверх него.

Мне интересно знать, если кто-то сбольше опыта классов Java может предложить более элегантные альтернативы.Одна вещь, которая меня не устраивает, заключается в том, что каждый отдельный is.read () неизбежно будет генерировать дополнительный системный вызов (при условии, что Socket.getInputStream () используется для подачи , это аргумент).

public static String recvHttpHeaders(InputStream is, Vector<String> headers) 
throws Exception {
byte line[] = new byte[512];
String pending=null;
String status=null;
boolean complete=false, CR=false;
int n=0;

while (!complete) {
    int x = is.read();
    switch(x) {
    case -1: throw new Exception("something went wrong");
    case '\r': 
            if (CR) throw new Exception("encoding mismatch CRCR");
            CR=true;
            break;
    case '\n': // bare LF are accepted silently.
            String ln = new String(line,0,n,"ASCII");
            if (pending!=null) ln = pending + ln;
            if (status==null) status = ln;
            else headers.add(ln);
            complete = ln.length()==0;
            pending = null;
            n=0; CR=false;
            break;
    default:
            if (CR) throw new Exception("encoding mismatch ?CR");
            if (n>=512) {
                String part = new String(line, "ASCII");
                if (pending!=null) pending += part;
                else pending = part;
                n=0;
            }
            line[n++]=(byte)x;
            break;
    }
}
return status;
}

edit : по общему признанию, здесь хотелось бы использовать xxx.readline () , чтобы избежать путаницы с реконструкцией линий.BufferedReader (или любой другой * Reader, фактически) преобразует байты в символы в соответствии с одной кодировкой.Это означает, что я больше не могу выбирать этот набор символов для содержимого, если я использовал эту функцию при разборе заголовка.Я не нашел ни одного класса уровня байтов со встроенной способностью чтения.

решение для повышения производительности : Спасибо за указание на BufferedInputStream.Я сделал несколько дополнительных тестов, и, действительно, вызов как

   BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
   String status = recvHttpHeaders(bis, headers);
   rawCopy(bis, output);

действительно уменьшает количество выполняемых системных вызовов и все еще позволяет мне правильно получать двоичный контент без изменений.

Ответы [ 2 ]

0 голосов
/ 28 августа 2012

Следуя комментариям Срипати Кришнана и Адама Пейнтера, способ улучшить его - это использовать BufferedInputStream, чтобы производительность оставалась приемлемой, а преобразование кодировки не происходило.

0 голосов
/ 01 марта 2011

Вы должны использовать BufferedReader для чтения текстов. Оберните ваш поток ввода:

BufferedReder br = new BufferedReader(new InputStreamReader(is));

Затем используйте readLine (), чтобы прочитать материал построчно:

String line = null;
while((line = br.readLine()) != null) {
    // deal with the line
}
...