java.nio.Buffer why such a strange implementation

When I think `buffer' the first thing that comes to mind is a circular buffer. The API would provide available/read/get and free/write/put but there would not be this confusing flip() business like with java.nio.Buffer. Off hand I could not say which one is more efficient in different szenarios.

But I can certainly say that the java.nio.Buffer interface seems to be intended to introduce bugs into client code. With the blink of an eye you flip-flopped the buffer once to often and nothing works anymore.

Does anyone have an idea what is so cool about the flip() as compared to a straight forward circular buffer implementation?

Harald.

[665 byte] By [pifpafpufa] at [2007-10-2 4:58:37]
# 1

> When I think `buffer' the first thing that comes to mind is a circular buffer

Its not the first thing that comes to my mind.

Having some sort of magic automatic circular buffer would confuse the life out of me!

I have a buffer of size 20, and write 10 bytes in to it.

Then I want to read from it.

What happens then with your auto-circular buffer approach?

aconst_nulla at 2007-7-16 1:02:45 > top of Java-index,Other Topics,Algorithms...
# 2

I make a Circular Buffer with normal Stream.

I send to you, could be a start point for NIO.

import java.io.*;

import java.text.*;

/**

* CircularFileOutputStream -

* Fecha de creaci髇: (29/8/01 13:26:08)

* @author: JPBM

*/

public class CircularFileOutputStream extends java.io.OutputStream {

public final static int DEFAULTMAGIC = 1246773837;

// Numero Magico en HEXADECIMAL 4A50424D

public final static int DEFAULTSIZE = 65536; // 64 Kb Tama駉 por defecto

public final static String DEFAULTOPEN = "rw";

// por defecto lectura escritura

public static String LINESEPARATOR = System.getProperty("line.separator");

public static String DEFAULTEOF = LINESEPARATOR + "EOF" + LINESEPARATOR;

// Fin de fichero

public final static int SIZEOFHEADER = 12; // Tama駉 de la cabecera

public final static int OFFSETPOS = 4; // Desplazamiento de Pos actual

private SimpleDateFormat formatoFecha = new SimpleDateFormat("hh:mm:ss.SSS");

// Variable que se utiliza para crear un formato para escribir la fecha

private RandomAccessFile raf; // Fichero de acceso aleatorio

private long posactual = -1; // Posicion actual dentro del fichero

private long size = -1; // Tama駉 maximo

/**

* Constructor

* @param file java.io.File

* @exception java.io.IOException La descripci髇 de excepci髇.

*/

public CircularFileOutputStream(java.io.File file) throws java.io.FileNotFoundException, java.io.IOException {

this(file.getPath(), DEFAULTSIZE);// Tama駉 por defecto

}

/**

* Constructor

* @param file java.io.File Fichero a escribir.

* @param maxsize int Maximo tama駉 del fichero circular.

* @exception java.io.IOException La descripci髇 de excepci髇.

*/

public CircularFileOutputStream(java.io.File file, long maxsize) throws java.io.FileNotFoundException, java.io.IOException {

SecurityManager security = System.getSecurityManager();

if (security != null) {

security.checkWrite(file.getPath());

}

raf = new RandomAccessFile(file, DEFAULTOPEN);

checkMagic(DEFAULTMAGIC, maxsize);// Comprueba el n鷐ero MAGICO

}

/**

* Constructor.

* @param name java.lang.String

* @exception java.io.FileNotFoundException La descripci髇 de excepci髇.

*/

public CircularFileOutputStream(String name) throws java.io.FileNotFoundException, java.io.IOException {

this(name, DEFAULTSIZE);// Se pone el tama駉 por defecto

}

/**

* Constructor.

* @param name java.lang.String

* @exception java.io.FileNotFoundException La descripci髇 de excepci髇.

*/

public CircularFileOutputStream(String name, long maxsize) throws java.io.FileNotFoundException, java.io.IOException {

SecurityManager security = System.getSecurityManager();

if (security != null) {

security.checkWrite(name);

}

raf = new RandomAccessFile(name, DEFAULTOPEN);

checkMagic(DEFAULTMAGIC, maxsize);// Comprueba el n鷐ero MAGICO

}

public void close() throws IOException {

raf.close();

}

public void checkMagic(int magic, long maxsize) throws IOException {

long pos = 0;

if (raf.length() > SIZEOFHEADER + getEOFString().length()) {

raf.seek(0);

raf.writeInt(magic);

pos = getPos(); // Comprueba la posici髇

if(pos>maxsize)pos = pos % maxsize;

setSize(maxsize); // Pone el tama駉 del fichero

} else {

setSize(maxsize); // Pone el tama駉 del fichero

raf.seek(0); // Se situa en el inicio y pone el n鷐ero magico

raf.writeInt(magic);// Pone el numero magico

}

setPos(pos); // Comprueba la posici髇 Cero en caso de que no haya magic

}

/**

* Fecha de creaci髇: (31/7/00 17:11:05)

*/

public void finalize()

{

try{

raf.close();

}catch(Throwable t)

{

}

}

public void flush() throws IOException {

}

/**

* Inserte aqu?la descripci髇 del m閠odo.

* Fecha de creaci髇: (30/8/01 10:57:00)

* @return String

*/

public String getEOFString(){

return DEFAULTEOF + formatoFecha.format(new java.util.Date())+LINESEPARATOR;

}

/**

* Inserte aqu?la descripci髇 del m閠odo.

* Fecha de creaci髇: (30/8/01 10:57:00)

* @return long

*/

public long getPos()throws java.io.IOException{

if(posactual<SIZEOFHEADER)

return readPos();

else

return posactual-SIZEOFHEADER;

}

/**

* Inserte aqu?la descripci髇 del m閠odo.

* Fecha de creaci髇: (30/8/01 10:57:00)

* @return long

*/

public long getSize()throws IOException {

if(size>SIZEOFHEADER)

return size;

else return raf.length();

}

/**

* Inserte aqu?la descripci髇 del m閠odo.

* Fecha de creaci髇: (30/8/01 13:01:44)

* @param args java.lang.String[]

*/

public static void main(String[] args)

{

try{

PrintWriter cf = new PrintWriter(new CircularFileOutputStream("d:\\juanpfich"), true);

cf.println("Hola soy edui");

for(int i =0; i <= 35000; i ++)

{

cf.println("Hola soy edui" + i);

}

}catch(IOException t)

{

System.out.println(t);

t.printStackTrace();

}

}

/**

* Inserte aqu?la descripci髇 del m閠odo.

* Fecha de creaci髇: (30/8/01 10:57:00)

* @return long

*/

public long readPos() throws java.io.IOException{

raf.seek(OFFSETPOS);// Lee a partir de la cuarta posicion

return raf.readLong();// Lee a partir de la cuarta posicion

}

/**

* Inserte aqu?la descripci髇 del m閠odo.

* Fecha de creaci髇: (30/8/01 10:57:00)

* @param newPos long

*/

private synchronized void setPos(long newPos)throws IOException {

if (newPos < 0) {

throw new IllegalArgumentException("Pos < 0");

}

posactual = newPos+SIZEOFHEADER;// Pone la nueva posicion

raf.seek(OFFSETPOS);// Se situa

raf.writeLong(newPos);// Guarda la posicion

writeEOFString();// A馻de la cadena

}

/**

*

* Fecha de creaci髇: (30/8/01 10:57:00)

* @param newSize long

*/

public synchronized void setSize(long newSize) throws IOException{

if (newSize < SIZEOFHEADER + getEOFString().length()) {

throw new IllegalArgumentException("File Size < " + SIZEOFHEADER);

}

size = newSize;

raf.setLength(size);

}

public void write(byte b[]) throws IOException {

write(b,0, b.length);

}

public synchronized void write(byte b[], int off, int len) throws IOException {

intini = (int)((getSize()) -(getPos() + SIZEOFHEADER) )- len;

// Escribe en el inicio

if(ini>=0)

{

raf.seek(posactual);

raf.write(b,off,len);

setPos(posactual+ len-SIZEOFHEADER);

}else{

// Reescribe

ini = ini * (-1);

raf.seek(posactual);

raf.write(b, off, len -ini);

raf.seek(SIZEOFHEADER);

raf.write(b,off+len -ini,ini);

setPos(ini);

}

}

public synchronized void write(int b) throws java.io.IOException

{

long pos = posactual % size;

if(posactual >= size)

{

raf.seek(SIZEOFHEADER);// Posicion actual

raf.write(b);

setPos(0);// Pone la posicion inicial

}else{

raf.seek(pos);// Posicion actual

raf.write(b);

setPos((pos+1)-SIZEOFHEADER);// Pone una posactual mas (para eso resto 8)

}

}

/**

* Inserte aqu?la descripci髇 del m閠odo.

* Fecha de creaci髇: (30/8/01 10:57:00)

* @param newPos long

*/

private void writeEOFString()throws IOException {

String cadena = getEOFString();// A馻de la cadena

intini = (int)((getSize()) - (getPos()+SIZEOFHEADER)) - cadena.length();

// Escribe en el inicio

if(ini>=0)

{

raf.seek(posactual);

raf.writeBytes(cadena);

}else{

// Reescribe

ini = ini * -1;

raf.seek(posactual);

raf.writeBytes(cadena.substring(0, cadena.length()-ini));

raf.seek(SIZEOFHEADER);

raf.writeBytes(cadena.substring(cadena.length()-ini, cadena.length()) );

}

}

}

barbywarea at 2007-7-16 1:02:45 > top of Java-index,Other Topics,Algorithms...
# 3

> > When I think `buffer' the first thing that comes to

> mind is a circular buffer

>

> Its not the first thing that comes to my mind.

> Having some sort of magic automatic circular buffer

> would confuse the life out of me!

Well, the "circular" refers to the implementation. If it scares you, don't look at it. The interface would be easier than the java.nio.Buffer API.

> I have a buffer of size 20, and write 10 bytes in to

> it.

> Then I want to read from it.

Exactly that is what you get with a circular buffer. In contrast to java.nio.Buffer, there would be no flip(), just read and write and of course a way to check how much room or data is available.

Harald.

pifpafpufa at 2007-7-16 1:02:45 > top of Java-index,Other Topics,Algorithms...
# 4
A lot of code but no answer to my question. Harald.
pifpafpufa at 2007-7-16 1:02:45 > top of Java-index,Other Topics,Algorithms...
# 5
> A lot of code but no answer to my question.> 42?
sabre150a at 2007-7-16 1:02:45 > top of Java-index,Other Topics,Algorithms...
# 6
> Well, the "circular" refers to the implementation. > If it scares you, don't look at it. The interface would be easier > than the java.nio.Buffer API.What would your interface look like
aconst_nulla at 2007-7-16 1:02:45 > top of Java-index,Other Topics,Algorithms...
# 7

> What would your interface look like

read, write, put, get as needed

availableData may be called before read/get

availableSpace should better be called before write/put

capacity()

clear() => availableSpace()==capacity(), availableData()==0

readMark/readReset

writeMark/writeReset

So basically everything you have in Buffer, except flip(). Things that become ambiguous, like mark(), need to be split into two methods obviously.

Harald.

pifpafpufa at 2007-7-16 1:02:45 > top of Java-index,Other Topics,Algorithms...