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?


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

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.


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()!


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.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.