14K
14K

Reputation: 439

Writing data back to binary file

I am trying to write char, double and integer back to my binary file base on my String arraylist. However, after finishing writing and I read the binary file again it generates erros. Anyone could help with this I really appreciate it.

ArrayList<String>temp = new ArrayList<String>();
    for(int i = 0;i<temp.size();i++){
                String decimalPattern = "([0-9]*)\\.([0-9]*)";  
                boolean match = Pattern.matches(decimalPattern, temp.get(i));
                if(Character.isLetter(temp.get(i).charAt(0))){
                    os.writeChar(temp.get(i).charAt(0));
                }
                else if(match == true){
                    Double d = Double.parseDouble(temp.get(i));
                    os.writeDouble(d);
                }       
                else
                {
                 int in = Integer.parseInt(temp.get(i));
                 os.writeInt(in);
                }
            }
            os.close();
         }

Upvotes: 1

Views: 1184

Answers (1)

An SO User
An SO User

Reputation: 24998

This is a very simple example which will show you how to read your data sequentially:

public void readFile(String absoluteFilePath){
    ByteBuffer buf = ByteBuffer.allocate(2+4+8) // creating a buffer that is suited for data you are reading
    Path path = Paths.get(absoluteFilePath);

    try(FileChannel fileChannel = (FileChannel)Files.newByteChannel(path,Enum.setOf(READ))){
        while(true){
            int bytesRead = fileChannel.read(buf);
            if(bytesRead==-1){
                break;
            }
            buf.flip(); //get the buffer ready for reading.
            char c = buf.asCharBuffer().readChar(); // create a view buffer and read char
            buf.position(buf.position() + 2); //now, lets go to the int
            int i = buf.asIntBuffer().readInt(); //read the int
            buf.position(buf.position()+ 4); //now, lets go for the double.
            double d = buf.asDoubleBuffer().readDouble();
            System.out.println("Character: " + c + " Integer: " + i + " Double: " + d);
            buf.clear();
        }
    }catch(IOException e){
        e.printStackTrace();
    }// AutoClosable so no need to explicitly close
}  

Now, assuming that you always write data as (char,int,double) into your file and that there are no chances where your data would be out of order or incomplete as (char,int) / (char,double), you can simply read the data randomly by specifying the position in the file, measured in bytes, from where to fetch the data as:

channel.read(byteBuffer,position);  

In your case, the data is always 14 bytes in size as 2 + 4 + 8 so all your read positions will be multiples of 14.

First block at: 0 * 14 = 0  
Second block at: 1 * 14 = 14  
Third block at: 2 * 14 = 28

and so on..

enter image description here

Similar to reading, you can also write using

channel.write(byteBuffer,position)  

Again, positions will be multiples of 14.

This applies in case of FileChannel which is a super class of ReadableByteChannel which is a dedicated channel for reading, WritableByteChannel which is a dedicated channel for writing and SeekableByteChannel which can do both reading and writing but is a little bit more complex.

When using channels and ByteBuffer, take care as to how you read. There is nothing to prevent me from reading 14 bytes as a set of 7 characters. Although this looks scary, this gives you complete flexibility on how you read and write data

Upvotes: 2

Related Questions