Pergunta

Eu estou fazendo um programa em Java com Sockets. Eu posso enviar comandos para o cliente e do cliente para o servidor. Para ler os comandos que eu uso um BufferedReader. Para escrevê-los, um PrintWriter Mas agora eu quero transferir um arquivo por meio de que tomada (Não basta criar uma segunda ligação) .
Primeiro eu escrevo para o outputstream como muitos bytes do arquivo contém. Por exemplo 40.000 bytes. Então eu escrever o número 40000 através do socket, mas o outro lado da conexão lê 78.

Então eu estava pensando: O BufferedReader lê mais do que apenas a linha (chamando readLine()) e nessa maneira que eu perder alguns bytes do arquivo-dados. Porque eles estão no buffer do BufferedReader.
Portanto, o número 78 é um byte do arquivo que eu quero transmitir.

É este modo de pensar direito, ou não. Se assim for, como sovle este problema.
Espero que eu tenha explicado bem.


Aqui está o meu código, mas o meu idioma padrão é holandês. Então, alguma variável-nome pode soar stange.

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");
}

Aqui está a solução:
Graças ao James sugestão
Eu acho que laginimaineb anwser era um pedaço da solução.

Leia os comandos.

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);
}

Agora, o 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.

Foi útil?

Solução

DataInputStream é mais provável que você deseja usar. Além disso, não use o método disponível () como é geralmente inútil.

Outras dicas

Eu não tenho certeza que eu tenho seguido a sua explicação.

No entanto, sim - você não tem nenhum controle real sobre o quanto um BufferedReader irá realmente ler. O ponto de tal leitor é um que optimistically lê pedaços do recurso subjacente como necessário para repor o seu tampão. Então, quando você primeiro readLine chamada, ele vai ver que seu buffer interno não tem o suficiente para servir youthe pedido, e sair e ler no entanto muitos bytes se sente como em seu buffer a partir da fonte subjacente , que geralmente será muito mais do que você pediu naquele momento. Uma vez que o tampão foi povoada, ele retorna a sua linha a partir do conteúdo tamponada.

Assim, uma vez que você envolver um fluxo de entrada em um BufferedReader, você deve ter certeza de somente leitura que o fluxo através do mesmo leitor em buffer. Se você não você vai acabar perdendo dados (como alguns bytes terá sido consumido e está agora sentado no cache do BufferedReader à espera de ser servido).

A BufferedReader assume que é a única leitura do fluxo de entrada subjacente.

Seu objetivo é minimizar o número de leituras do fluxo subjacente (que são caros, como eles podem delegar muito profundamente). Para esse fim, ele mantém um buffer, que enche lendo como muitos bytes quanto possível para ela, em uma única chamada para o fluxo subjacente.

Então, sim, o seu diagnóstico é preciso.

Apenas uma facada selvagem aqui - 40000 é 1001110001000000 em binário. Agora, os primeiros bits sete aqui estão 1001110, que é 78. Ou seja, você está escrevendo 2 bytes de informação, mas a leitura sete bits.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top