Qual é o propósito do método flip de ByteBuffer? (E por que é chamado de “flip”?)

96

Por que o método flip () de ByteBuffer é chamado de "flip"? O que é "invertido" aqui? De acordo com o apidoc, dois giros sucessivos não restaurarão o estado original e vários giros provavelmente tenderão limit()a se tornar zero.

Posso "desviar" de alguma forma para reutilizar os bytes que ultrapassaram o limite?

Posso concatenar a cauda para ser invertida com alguns outros dados?

Suzan Cioc
fonte
5
Ele "vira" o buffer de leitura para gravação (e vice-versa). thushw.blogspot.com/2009/10/…
Brian Roach
2
@BrianRoach: ele muda de leitura para escrita, mas não é tão útil para escrita para leitura, a menos que você esteja escrevendo estruturas de tamanho fixo. Para virar para escrever para ler, use reset.
nneonneo de
Lembre-se de fazer perguntas "objetivas"; ou, pelo menos, fazer a pergunta predominante parecer objetiva: D
@nneonneo - Era meio que não questionável, não ia gastar muito tempo explicando os detalhes, portanto, apenas um comentário e um link.
Brian Roach

Respostas:

131

Um caso de uso bastante comum para o ByteBufferé construir alguma estrutura de dados peça por peça e, em seguida, gravar essa estrutura inteira no disco. flipé usado para mudar ByteBufferde "leitura de I / O" ( putting) para "gravação de I / O" ( getting): após uma sequência de puts ser usada para preencher o ByteBuffer, flipdefinirá o limite do buffer para a posição atual e redefinir a posição para zero. Isso tem o efeito de fazer um futuro getou writedo buffer gravar tudo o que estava putno buffer e nada mais.

Depois de terminar o put, você pode querer reutilizar o ByteBufferpara construir outra estrutura de dados. Para "desviá-lo", ligue clear. Isso redefine o limite da capacidade (tornando todo o buffer utilizável) e a posição para 0.

Portanto, um cenário de uso típico:

ByteBuffer b = new ByteBuffer(1024);
for(int i=0; i<N; i++) {
    b.clear();
    b.put(header[i]);
    b.put(data[i]);
    b.flip();
    out.write(b);
}
Nneonneo
fonte
A WritableByteChannel, como FileChannelou SocketChannel.
nneonneo
6
Ou qualquer outra coisa que tenha um write(ByteBuffer)método. (Não é realmente relevante qual é o seu tipo ...)
Stephen C de
1
Ele deve Buffer.clearredefinir o limite para capacidade e posição para 0. Buffer.resetredefinir apenas a posição para mark.
Kelvin Ng de
1
@KelvinNg: Você está certo; Eu alterei a resposta para refletir isso. Obrigado pela boa captura!
nneonneo,
1
@ user963241: ler do I / O no buffer, escrever do buffer no I / O.
nneonneo
7

Flip atribui o valor da posição atual à propriedade limit e define a propriedade position para 0. Flip é útil para drenar apenas os elementos ativos de um buffer.

Por exemplo, o programa abaixo imprime "hello" e não os elementos vazios do buffer. O limite e a posição das chamadas de método podem ser substituídos com flip.

CharBuffer cbuff = CharBuffer.allocate(40);
cbuff.put("hello"); 
// what below two line of code is what flip does
cbuff.limit(cbuff.position());
cbuff.position(0);      
while(cbuff.hasRemaining()) {
    System.out.println(cbuff.get());
}

Consulte http://www.zoftino.com/java-nio-tutorial para obter mais informações sobre buffers e canais.

Arnav Rao
fonte
Obrigado pelo link para a cobertura muito extensa! É ótimo quando as fontes são incluídas. Os documentos da API java pareciam usar a palavra 'flip' sem explicação, como se fosse um termo comum da ciência da computação, mas obviamente algumas pessoas (inclusive eu) não acharam que seja o caso.
John Meyer
3

ByteBuffer é mal projetado. Há muitas reclamações de programadores decentes.

Portanto, não tente raciocinar sobre isso, apenas estude e use a API com cuidado.

Agora eu não posso falar mal disso sem apresentar uma alternativa, então aqui está:

Um buffer tem um fixo capacity; mantém 2 ponteiros: starte end. get()retorna o byte na startposição e incrementos start. put()coloca o byte na endposição e incrementa end. Não flip()!

irreputável
fonte
6
Então, quais são as reclamações? Se você tiver alguma reclamação pessoal, tudo bem, mas não basta apenas dizer "X API é uma merda, as pessoas dizem".
nneonneo de
13
Publicar esse link é literalmente tudo o que você precisava fazer em primeiro lugar. Nunca o acusei de mentir, apenas lhe pedi que elaborasse a fonte e a natureza das queixas.
nneonneo de
2
este é apenas um lugar onde as pessoas oferecem sua ajuda voluntariamente, com a quantidade adequada de esforço que escolherem. Não preciso expandir cada resposta em um artigo acadêmico bem pesquisado.
irreputável de
8
e este também é um lugar onde as pessoas não acreditarão na palavra de alguém, a menos que pareça confiável.
arunmoezhi
8
Você nem precisa fornecer fontes. É flagrantemente óbvio que ByteBuffer é mal projetado. flip não preenche um propósito, apenas apresenta uma fonte de bugs quando você se esquece de inverter. Se eles sentiram uma necessidade incontrolável de colocá-lo, pelo menos crie classes diferentes de ByteBuffers invertidos e não invertidos, para que o sistema de tipos possa detectar os bugs.
Gurgeh
0

O método flip () torna um buffer pronto para uma nova sequência de canais de gravação ou operações relativas de obtenção: Ele define o limite para a posição atual e, em seguida, define a posição para zero.

O Buffer rastreia os dados gravados nele. Após a escrita, o método flip () é chamado para alternar do modo de escrita para o modo de leitura.

vkohli
fonte