Вопрос

Я создаю программу на Java с сокетами.Я могу отправлять команды клиенту и от клиента к серверу.Для чтения команд я использую BufferedReader.Чтобы написать их, a PrintWriter Но теперь я хочу передать файл через это розетка (Не просто создать второе соединение).
Сначала я записываю в outputstream, сколько байт содержит файл.Например, 40000 байт.Поэтому я записываю номер 40000 через сокет, но другая сторона соединения считывает 78.

Вот я и подумал:Тот Самый BufferedReader читает больше, чем просто строку (позвонив readLine()) и на этом пути я теряю несколько байт из файла-данных.Потому что они находятся в буфере из BufferedReader.
Итак, число 78 это байт файла, который я хочу передать.

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


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

public void flushStreamToStream(InputStream is, OutputStream os, boolean closeIn, boolean closeOut) throws IOException {
    byte[] buffer = new byte[BUFFERSIZE];
    int bytesRead;
    if ((!closeOut) && closeIn) { // To Socket from File
        action = "Upload";
        os.write(is.available()); // Here I write 400000
        max = is.available();
        System.out.println("Bytes to send: " + max);
        while ((bytesRead = is.read(buffer)) != -1) {
            startTiming(); // Two lines to compute the speed
            os.write(buffer, 0, bytesRead);
            stopTiming(); // Speed compution
            process += bytesRead;
        }
        os.flush();
        is.close();
        return;
    }
    if ((!closeIn) && closeOut) { // To File from Socket
        action = "Download";
        int bytesToRead = -1;
        bytesToRead = is.read(); // Here he reads 78.
        System.out.println("Bytes to read: " + bytesToRead);
        max = bytesToRead;
        int nextBufferSize;
        while ((nextBufferSize = Math.min(BUFFERSIZE, bytesToRead)) > 0) {
            startTiming();
            bytesRead = is.read(buffer, 0, nextBufferSize);
            bytesToRead -= bytesRead;
            process += nextBufferSize;
            os.write(buffer, 0, bytesRead);
            stopTiming();
        }
        os.flush();
        os.close();
        return;
    }
    throw new IllegalArgumentException("The only two boolean combinations are: closeOut == false && closeIn == true AND closeOut == true && closeIn == false");
}

Вот решение:
Благодаря предложению Джеймса
Я думаю , что лагинимайнеб anwser был частью решения.

Прочтите команды.

DataInputStream in = new DataInputStream(is); // Originally a BufferedReader
// Read the request line
String str;
while ((str = in.readLine()) != null) {
    if (str.trim().equals("")) {
       continue;
    }
    handleSocketInput(str);
}

Теперь flushStreamToStream:

public void flushStreamToStream(InputStream is, OutputStream os, boolean closeIn, boolean closeOut) throws IOException {
    byte[] buffer = new byte[BUFFERSIZE];
    int bytesRead;
    if ((!closeOut) && closeIn) { // To Socket from File
        action = "Upload";
        DataOutputStream dos = new DataOutputStream(os);
        dos.writeInt(is.available());

        max = is.available();
        System.out.println("Bytes to send: " + max);
        while ((bytesRead = is.read(buffer)) != -1) {
            startTiming();
            dos.write(buffer, 0, bytesRead);
            stopTiming();
            process += bytesRead;
        }
        os.flush();
        is.close();
        return;
    }
    if ((!closeIn) && closeOut) { // To File from Socket
        action = "Download";
        DataInputStream dis = new DataInputStream(is);
        int bytesToRead = dis.readInt();
        System.out.println("Bytes to read: " + bytesToRead);
        max = bytesToRead;
        int nextBufferSize;
        while ((nextBufferSize = Math.min(BUFFERSIZE, bytesToRead)) > 0) {
            startTiming();
            bytesRead = is.read(buffer, 0, nextBufferSize);
            bytesToRead -= bytesRead;
            process += nextBufferSize;
            os.write(buffer, 0, bytesRead);
            stopTiming();
        }
        os.flush();
        os.close();
        return;
    }
    throw new IllegalArgumentException("The only two boolean combinations are: closeOut == false && closeIn == true AND closeOut == true && closeIn == false");
}

Martijn.

Это было полезно?

Решение

DataInputStream - это, скорее всего, то, что вы хотите использовать.Кроме того, не используйте метод available(), поскольку он, как правило, бесполезен.

Другие советы

Я не уверен, что правильно понял ваше объяснение.

Однако, да - у вас нет реального контроля над тем, сколько на самом деле прочитает BufferedReader.Смысл такого считывателя в том, что он оптимистично считывает фрагменты базового ресурса по мере необходимости для пополнения своего буфера.Итак, когда вы впервые позвоните readLine, он увидит, что его внутреннего буфера недостаточно для выполнения вашего запроса, и будет выходите и считывайте в свой буфер столько байтов, сколько вам захочется из основного источника, который, как правило, будет намного больше, чем вы просили только что.Как только буфер заполнен, он возвращает вашу строку из буферизованного содержимого.

Таким образом, как только вы переносите входной поток в BufferedReader, вы должны быть уверены, что будете читать этот поток только через тот же буферизованный reader.Если вы этого не сделаете, вы в конечном итоге потеряете данные (так как некоторые байты будут израсходованы и теперь находятся в кэше BufferedReader, ожидая отправки).

BufferedReader предполагает, что это единственное средство чтения из базового входного потока.

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

Так что да, ваш диагноз точен.

Просто дикий удар здесь - 40000 - это 1001110001000000 в двоичном формате.Итак, первые семь битов здесь равны 1001110, что равно 78.Это означает, что вы записываете 2 байта информации, но считываете семь бит.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top