Files
gzz-mirror/Java/storage/FileWritable.java
2026-09-14 20:19:29 -04:00

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