252 lines
5.2 KiB
Java
252 lines
5.2 KiB
Java
/*
|
|
FileWritable.java
|
|
*
|
|
* Copyright (c) 2000, Ted Nelson, Tuomas Lukka and Vesa Parkkinen
|
|
*
|
|
* You may use and distribute under the terms of either the GNU Lesser
|
|
* General Public License, either version 2 of the license or,
|
|
* at your choice, any later version. Alternatively, you may use and
|
|
* distribute under the terms of the XPL.
|
|
*
|
|
* See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of
|
|
* the licenses.
|
|
*
|
|
* This software is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README
|
|
* file for more details.
|
|
*
|
|
*/
|
|
/*
|
|
* Written by Tuomas Lukka & Vesa Parkkinen
|
|
*/
|
|
package org.gzigzag;
|
|
import java.util.*;
|
|
import java.io.*;
|
|
|
|
/** A Writable that is just a file.
|
|
*
|
|
* Default: caching off..
|
|
*/
|
|
|
|
// Beginning of block:
|
|
// long: index of next block
|
|
// long: offset in subfile0 to the name.
|
|
|
|
public class FileWritable implements Writable {
|
|
public static final String rcsid =
|
|
"$Id: FileWritable.java,v 1.6 2000/09/19 10:32:00 ajk Exp $";
|
|
public static final boolean dbg = false;
|
|
static final void p(String s) { if(dbg) System.out.println(s); }
|
|
static final void pa(String s) { System.out.println(s); }
|
|
|
|
public static final int BUF_SIZE = 512;
|
|
|
|
RandomAccessFile f;
|
|
|
|
byte[] r_buffer;
|
|
byte[] w_buffer;
|
|
|
|
boolean cache;
|
|
boolean dirty;
|
|
|
|
// read buffer offset
|
|
long off;
|
|
// write buffer offset
|
|
long w_off;
|
|
// read bytes in buffer
|
|
int r_size;
|
|
// bytes written
|
|
int written;
|
|
|
|
/*
|
|
* XXX TODO: not quite there yet...
|
|
*/
|
|
public void write(long offset, byte[] data) {
|
|
//p("write");
|
|
try {
|
|
if( ! cache ){
|
|
f.seek(offset);
|
|
f.write(data);
|
|
return;
|
|
}else {
|
|
// clear read cache
|
|
if ( offset < off + r_size &&
|
|
offset + data.length > off ) {
|
|
|
|
off = 0;
|
|
r_size = 0;
|
|
}
|
|
|
|
if ( data.length > BUF_SIZE ){
|
|
//p(" > ");
|
|
flush();
|
|
f.seek(offset);
|
|
f.write(data);
|
|
return;
|
|
}
|
|
if ( offset + data.length < w_off ){
|
|
//p(" under ");
|
|
f.seek(offset);
|
|
f.write(data);
|
|
//return;
|
|
}else if ( offset > w_off + written ){
|
|
//p(" over ");
|
|
flush();
|
|
w_off = offset;
|
|
written = data.length;
|
|
System.arraycopy( data, 0, w_buffer, 0, written );
|
|
dirty = true;
|
|
}else if ( offset < w_off && offset + data.length > w_off ){
|
|
//p(" partial ");
|
|
flush();
|
|
f.seek(offset);
|
|
f.write(data);
|
|
|
|
} else if( offset == w_off + written &&
|
|
BUF_SIZE - written > data.length ) {
|
|
//p(" hit: " + offset);
|
|
System.arraycopy( data, 0, w_buffer, written, data.length);
|
|
written += data.length;
|
|
//p(" written = " + written);
|
|
dirty = true;
|
|
}else {
|
|
//p(" other ");
|
|
flush();
|
|
f.seek(offset);
|
|
f.write(data);
|
|
return;
|
|
}
|
|
|
|
}
|
|
} catch(Exception e) {
|
|
ZZLogger.exc(e);
|
|
throw new ZZError(" "+e);
|
|
}
|
|
}
|
|
|
|
|
|
public byte[] read(long offset, int n) {
|
|
//p("read");
|
|
try {
|
|
|
|
byte[] b = new byte[n];
|
|
|
|
if( ! cache ){
|
|
f.seek(offset);
|
|
f.read(b);
|
|
return b;
|
|
} else {
|
|
if( offset < w_off + written &&
|
|
offset + n > w_off ) {
|
|
flush();
|
|
}
|
|
if ( offset > off && offset - off + n < r_size ){
|
|
|
|
System.arraycopy(r_buffer, (int)(offset - off), b, 0, n );
|
|
return b;
|
|
}
|
|
|
|
f.seek(offset);
|
|
|
|
r_size = f.read(r_buffer);
|
|
System.arraycopy(r_buffer, 0, b, 0, n );
|
|
off = offset;
|
|
return b;
|
|
}
|
|
|
|
} catch(Exception e) {
|
|
ZZLogger.exc(e);
|
|
throw new ZZError(" read "+offset+" "+n+" "+e);
|
|
}
|
|
}
|
|
|
|
|
|
public void read(long offset, byte b[], int o, int n) {
|
|
//p("read2");
|
|
try {
|
|
if (! cache ){
|
|
f.seek(offset);
|
|
f.read(b, o, n);
|
|
}else {
|
|
if( offset + o < w_off + written &&
|
|
offset + o + n > w_off ) {
|
|
flush();
|
|
}
|
|
|
|
if ( offset + o> off && offset + o - off + n < r_size ){
|
|
|
|
System.arraycopy(r_buffer, (int)(offset + o - off),
|
|
b, o, n );
|
|
}else {
|
|
f.seek(offset + o);
|
|
r_size = f.read(r_buffer);
|
|
System.arraycopy(r_buffer, 0, b, o, n );
|
|
off = offset + o;
|
|
}
|
|
}
|
|
|
|
} catch(Exception e) {
|
|
ZZLogger.exc(e);
|
|
throw new ZZError(" read " +e);
|
|
}
|
|
|
|
}
|
|
|
|
public long length() {
|
|
try {
|
|
return f.length();
|
|
|
|
} catch(Exception e) {
|
|
ZZLogger.exc(e);
|
|
throw new ZZError(" "+e);
|
|
}
|
|
}
|
|
|
|
|
|
public void flush() {
|
|
if ( ! cache ) return;
|
|
if( ! dirty || written == 0) return;
|
|
|
|
try{
|
|
|
|
f.seek(w_off);
|
|
f.write(w_buffer, 0, written);
|
|
dirty = false;
|
|
//p("FLUSH " + written);
|
|
written = 0;
|
|
|
|
} catch(Exception e) {
|
|
ZZLogger.exc(e);
|
|
throw new ZZError(" "+e);
|
|
}
|
|
|
|
}
|
|
|
|
public FileWritable(RandomAccessFile f) {
|
|
|
|
/*
|
|
* set this to true, if you want to test caching
|
|
*/
|
|
this(f, false);
|
|
}
|
|
|
|
public FileWritable(RandomAccessFile f, boolean b) {
|
|
//p("FW: create");
|
|
this.f = f;
|
|
cache = b;
|
|
|
|
if ( cache ){
|
|
r_buffer = new byte[BUF_SIZE];
|
|
w_buffer = new byte[BUF_SIZE];
|
|
}else{
|
|
r_buffer = null;
|
|
}
|
|
dirty = false;
|
|
r_size = 0;
|
|
}
|
|
}
|
|
|
|
|
|
|