55 |
public class RandomAccessFile implements DataOutput, DataInput |
public class RandomAccessFile implements DataOutput, DataInput |
56 |
{ |
{ |
57 |
|
|
|
static |
|
|
{ |
|
|
if (Configuration.INIT_LOAD_LIBRARY) |
|
|
{ |
|
|
System.loadLibrary ("javaio"); |
|
|
} |
|
|
} |
|
|
|
|
|
/*************************************************************************/ |
|
|
|
|
58 |
/* |
/* |
59 |
* Instance Variables |
* Instance Variables |
60 |
*/ |
*/ |
61 |
|
|
62 |
/** |
private FileDescriptor fd; |
|
* The native file descriptor for this file |
|
|
*/ |
|
|
private int native_fd; |
|
63 |
|
|
64 |
/** |
/** |
65 |
* Whether or not this file is open in read only mode |
* Whether or not this file is open in read only mode |
66 |
*/ |
*/ |
67 |
private boolean read_only; |
private boolean readOnly; |
68 |
|
|
69 |
// Used for DataOutput methods writing values to the underlying file |
// Used for DataOutput methods writing values to the underlying file |
70 |
private byte[] buf = new byte[8]; |
private byte[] buf = new byte[8]; |
94 |
* is not allowed |
* is not allowed |
95 |
* @exception IOException If any other error occurs |
* @exception IOException If any other error occurs |
96 |
*/ |
*/ |
97 |
public |
public RandomAccessFile(String name, String mode) throws IOException |
|
RandomAccessFile(String name, String mode) throws IllegalArgumentException, |
|
|
SecurityException, |
|
|
IOException |
|
98 |
{ |
{ |
99 |
this(new File(name), mode); |
this(new File(name), mode); |
100 |
} |
} |
123 |
public RandomAccessFile(File file, String mode) |
public RandomAccessFile(File file, String mode) |
124 |
throws IllegalArgumentException, SecurityException, IOException |
throws IllegalArgumentException, SecurityException, IOException |
125 |
{ |
{ |
126 |
|
String name = file.getPath(); |
127 |
|
|
128 |
// Check the mode |
// Check the mode |
129 |
if (!mode.equals("r") && !mode.equals("rw")) |
if (!mode.equals("r") && !mode.equals("rw") && !mode.equals("rws") && |
130 |
|
!mode.equals("rwd")) |
131 |
throw new IllegalArgumentException("Bad mode value: " + mode); |
throw new IllegalArgumentException("Bad mode value: " + mode); |
132 |
|
|
133 |
// The obligatory SecurityManager stuff |
// The obligatory SecurityManager stuff |
135 |
if (sm != null) |
if (sm != null) |
136 |
{ |
{ |
137 |
if (mode.equals("r")) |
if (mode.equals("r")) |
138 |
sm.checkRead(file.getPath()); |
sm.checkRead(name); |
139 |
else if (mode.equals("rw")) |
else |
140 |
sm.checkWrite(file.getPath()); |
sm.checkWrite(name); |
141 |
} |
} |
142 |
|
|
143 |
if (mode.equals("r")) |
if (mode.equals("r")) |
144 |
read_only = true; |
readOnly = true; |
145 |
|
|
146 |
if (read_only) |
fd = new FileDescriptor(); |
147 |
native_fd = open(file.getPath(), true); |
fd.open(name, mode); |
|
else |
|
|
native_fd = open(file.getPath(), false); |
|
148 |
} |
} |
149 |
|
|
150 |
/*************************************************************************/ |
/*************************************************************************/ |
154 |
*/ |
*/ |
155 |
|
|
156 |
/** |
/** |
|
* This native method opens the file with the desired access mode |
|
|
*/ |
|
|
private native int open(String name, boolean read_only) throws IOException; |
|
|
|
|
|
/*************************************************************************/ |
|
|
|
|
|
/** |
|
157 |
* This method closes the file and frees up all file related system |
* This method closes the file and frees up all file related system |
158 |
* resources. Since most operating systems put a limit on how many files |
* resources. Since most operating systems put a limit on how many files |
159 |
* may be opened at any given time, it is a good idea to close all files |
* may be opened at any given time, it is a good idea to close all files |
161 |
*/ |
*/ |
162 |
public void close() throws IOException |
public void close() throws IOException |
163 |
{ |
{ |
164 |
if (native_fd != -1) |
fd.close(); |
|
closeInternal(native_fd); |
|
|
|
|
|
native_fd = -1; |
|
165 |
} |
} |
166 |
|
|
167 |
/*************************************************************************/ |
/*************************************************************************/ |
168 |
|
|
169 |
/** |
/** |
|
* Native methods that actually closes the file |
|
|
*/ |
|
|
private native void closeInternal(int native_fd) throws IOException; |
|
|
|
|
|
/*************************************************************************/ |
|
|
|
|
|
/** |
|
170 |
* This method returns a <code>FileDescriptor</code> object that |
* This method returns a <code>FileDescriptor</code> object that |
171 |
* represents the native file handle for this file. |
* represents the native file handle for this file. |
172 |
* |
* |
176 |
*/ |
*/ |
177 |
public final FileDescriptor getFD() throws IOException |
public final FileDescriptor getFD() throws IOException |
178 |
{ |
{ |
179 |
return(new FileDescriptor(native_fd)); |
return(fd); |
180 |
} |
} |
181 |
|
|
182 |
/*************************************************************************/ |
/*************************************************************************/ |
191 |
*/ |
*/ |
192 |
public long getFilePointer() throws IOException |
public long getFilePointer() throws IOException |
193 |
{ |
{ |
194 |
return(getFilePointerInternal(native_fd)); |
return(fd.getFilePointer()); |
195 |
} |
} |
196 |
|
|
197 |
/*************************************************************************/ |
/*************************************************************************/ |
198 |
|
|
|
/** |
|
|
* This native method actually retrieves the file pointer |
|
|
*/ |
|
|
private native long getFilePointerInternal(int native_fd) throws IOException; |
|
|
|
|
|
/*************************************************************************/ |
|
|
|
|
199 |
/** |
/** |
200 |
* This method returns the length of the file in bytes |
* This method returns the length of the file in bytes |
201 |
* |
* |
205 |
*/ |
*/ |
206 |
public long length() throws IOException |
public long length() throws IOException |
207 |
{ |
{ |
208 |
return(lengthInternal(native_fd)); |
return(fd.getLength()); |
209 |
} |
} |
210 |
|
|
211 |
/*************************************************************************/ |
/*************************************************************************/ |
212 |
|
|
213 |
/** |
/** |
|
* This native method determines the actual file length |
|
|
*/ |
|
|
private native long lengthInternal(int native_fd) throws IOException; |
|
|
|
|
|
/*************************************************************************/ |
|
|
|
|
|
/** |
|
214 |
* This method sets the current file position to the specified offset |
* This method sets the current file position to the specified offset |
215 |
* from the beginning of the file. Note that some operating systems will |
* from the beginning of the file. Note that some operating systems will |
216 |
* allow the file pointer to be set past the current end of the file. |
* allow the file pointer to be set past the current end of the file. |
222 |
*/ |
*/ |
223 |
public void seek(long pos) throws IOException |
public void seek(long pos) throws IOException |
224 |
{ |
{ |
225 |
seekInternal(native_fd, pos); |
fd.seek(pos, fd.SET, false); |
226 |
} |
} |
227 |
|
|
228 |
/*************************************************************************/ |
/*************************************************************************/ |
229 |
|
|
230 |
/** |
/** |
|
* This native method does the actual file offset seeking |
|
|
*/ |
|
|
private native void seekInternal(int native_fd, long pos) throws IOException; |
|
|
|
|
|
/*************************************************************************/ |
|
|
|
|
|
/** |
|
231 |
* This method sets the length of the file to the specified length. If |
* This method sets the length of the file to the specified length. If |
232 |
* the currently length of the file is longer than the specified length, |
* the currently length of the file is longer than the specified length, |
233 |
* then the file is truncated to the specified length. If the current |
* then the file is truncated to the specified length. If the current |
242 |
*/ |
*/ |
243 |
public void setLength(long newlen) throws IOException |
public void setLength(long newlen) throws IOException |
244 |
{ |
{ |
245 |
if (read_only) |
if (readOnly) |
246 |
throw new IOException("File is open read only"); |
throw new IOException("File is open read only"); |
247 |
|
|
248 |
setLengthInternal(native_fd, newlen); |
fd.setLength(newlen); |
249 |
} |
} |
250 |
|
|
251 |
/*************************************************************************/ |
/*************************************************************************/ |
252 |
|
|
253 |
/** |
/** |
|
* This native method does the actual work of setting the file length |
|
|
*/ |
|
|
private native void setLengthInternal(int native_fd, long newlen) |
|
|
throws IOException; |
|
|
|
|
|
/*************************************************************************/ |
|
|
|
|
|
/** |
|
254 |
* This method reads a single byte of data from the file and returns it |
* This method reads a single byte of data from the file and returns it |
255 |
* as an integer. |
* as an integer. |
256 |
* |
* |
258 |
* |
* |
259 |
* @exception IOException If an error occurs |
* @exception IOException If an error occurs |
260 |
*/ |
*/ |
261 |
public synchronized int read() throws IOException |
public int read() throws IOException |
262 |
{ |
{ |
263 |
int rc = readInternal(native_fd, buf, 0, 1); |
return(fd.read()); |
|
if (rc == 0) |
|
|
return(-1); |
|
|
|
|
|
return(buf[0] & 0xFF); |
|
264 |
} |
} |
265 |
|
|
266 |
/*************************************************************************/ |
/*************************************************************************/ |
278 |
*/ |
*/ |
279 |
public int read(byte[] buf) throws IOException |
public int read(byte[] buf) throws IOException |
280 |
{ |
{ |
281 |
int rc = readInternal(native_fd, buf, 0, buf.length); |
return(read(buf, 0, buf.length)); |
|
if (rc == 0) |
|
|
return(-1); |
|
|
else |
|
|
return(rc); |
|
282 |
} |
} |
283 |
|
|
284 |
/*************************************************************************/ |
/*************************************************************************/ |
297 |
*/ |
*/ |
298 |
public int read(byte[] buf, int offset, int len) throws IOException |
public int read(byte[] buf, int offset, int len) throws IOException |
299 |
{ |
{ |
300 |
int rc = readInternal(native_fd, buf, offset, len); |
return(fd.read(buf,offset, len)); |
|
if (rc == 0) |
|
|
return(-1); |
|
|
else |
|
|
return(rc); |
|
301 |
} |
} |
302 |
|
|
303 |
/*************************************************************************/ |
/*************************************************************************/ |
304 |
|
|
305 |
/** |
/** |
|
* This native method actually reads the bytes from the file |
|
|
*/ |
|
|
private native int readInternal(int native_fd, byte[] buf, |
|
|
int offset, int len); |
|
|
|
|
|
/*************************************************************************/ |
|
|
|
|
|
/** |
|
306 |
* This method reads a Java boolean value from an input stream. It does |
* This method reads a Java boolean value from an input stream. It does |
307 |
* so by reading a single byte of data. If that byte is zero, then the |
* so by reading a single byte of data. If that byte is zero, then the |
308 |
* value returned is <code>false</code> If the byte is non-zero, then |
* value returned is <code>false</code> If the byte is non-zero, then |
838 |
* The actual number of bytes skipped is returned. This method will not |
* The actual number of bytes skipped is returned. This method will not |
839 |
* skip any bytes if passed a negative number of bytes to skip. |
* skip any bytes if passed a negative number of bytes to skip. |
840 |
* |
* |
841 |
* @param num_bytes The requested number of bytes to skip. |
* @param numBytes The requested number of bytes to skip. |
842 |
* |
* |
843 |
* @return The number of bytes actually skipped. |
* @return The number of bytes actually skipped. |
844 |
* |
* |
845 |
* @exception IOException If an error occurs. |
* @exception IOException If an error occurs. |
846 |
*/ |
*/ |
847 |
public int skipBytes(int n) throws EOFException, IOException |
public int skipBytes(int numBytes) throws EOFException, IOException |
848 |
{ |
{ |
849 |
if (n <= 0) |
if (numBytes < 0) |
850 |
|
throw new IllegalArgumentException("Can't skip negative bytes: " + |
851 |
|
numBytes); |
852 |
|
|
853 |
|
if (numBytes == 0) |
854 |
return(0); |
return(0); |
855 |
|
|
856 |
long file_length = this.length(); |
long curPos = fd.getFilePointer(); |
857 |
long file_position = this.getFilePointer(); |
long newPos = fd.seek(numBytes, fd.CUR, true); |
858 |
int skip_length = (int) Math.min(n, file_length - file_position); |
|
859 |
long total_skipped = skipInternal(native_fd, skip_length); |
return((int)(newPos-curPos)); |
|
|
|
|
return((int)total_skipped); |
|
860 |
} |
} |
861 |
|
|
862 |
/*************************************************************************/ |
/*************************************************************************/ |
863 |
|
|
|
/* |
|
|
* Native method that does the actual byte skipping. |
|
|
*/ |
|
|
private native int skipInternal(int native_fd, int n); |
|
|
|
|
|
/*************************************************************************/ |
|
|
|
|
864 |
/** |
/** |
865 |
* This method writes a single byte of data to the file. The file must |
* This method writes a single byte of data to the file. The file must |
866 |
* be open for read-write in order for this operation to succeed. |
* be open for read-write in order for this operation to succeed. |
869 |
* |
* |
870 |
* @exception IOException If an error occurs |
* @exception IOException If an error occurs |
871 |
*/ |
*/ |
872 |
public synchronized void write(int b) throws IOException |
public void write(int b) throws IOException |
873 |
{ |
{ |
874 |
if (read_only) |
if (readOnly) |
875 |
throw new IOException("File is open read only"); |
throw new IOException("File is open read only"); |
876 |
|
|
877 |
buf[0] = (byte)b; |
fd.write(b); |
|
|
|
|
writeInternal(native_fd, buf, 0, 1); |
|
878 |
} |
} |
879 |
|
|
880 |
/*************************************************************************/ |
/*************************************************************************/ |
887 |
*/ |
*/ |
888 |
public void write(byte[] buf) throws IOException |
public void write(byte[] buf) throws IOException |
889 |
{ |
{ |
890 |
if (read_only) |
write(buf, 0, buf.length); |
|
throw new IOException("File is open read only"); |
|
|
|
|
|
writeInternal(native_fd, buf, 0, buf.length); |
|
891 |
} |
} |
892 |
|
|
893 |
/*************************************************************************/ |
/*************************************************************************/ |
904 |
*/ |
*/ |
905 |
public void write(byte[] buf, int offset, int len) throws IOException |
public void write(byte[] buf, int offset, int len) throws IOException |
906 |
{ |
{ |
907 |
if (read_only) |
if (readOnly) |
908 |
throw new IOException("File is open read only"); |
throw new IOException("File is open read only"); |
909 |
|
|
910 |
writeInternal(native_fd, buf, offset, len); |
fd.write(buf, offset, len); |
911 |
} |
} |
912 |
|
|
913 |
/*************************************************************************/ |
/*************************************************************************/ |
914 |
|
|
915 |
/** |
/** |
|
* This native method does the actual writing of the bytes |
|
|
*/ |
|
|
private native void writeInternal(int native_fd, byte[] buf, |
|
|
int offset, int len); |
|
|
|
|
|
/*************************************************************************/ |
|
|
|
|
|
/** |
|
916 |
* This method writes a Java <code>boolean</code> to the underlying output |
* This method writes a Java <code>boolean</code> to the underlying output |
917 |
* stream. For a value of <code>true</code>, 1 is written to the stream. |
* stream. For a value of <code>true</code>, 1 is written to the stream. |
918 |
* For a value of <code>false</code>, 0 is written. |
* For a value of <code>false</code>, 0 is written. |
958 |
*/ |
*/ |
959 |
public final void writeBytes(String s) throws IOException |
public final void writeBytes(String s) throws IOException |
960 |
{ |
{ |
961 |
if (s.length() == 0) |
int len = s.length(); |
962 |
|
|
963 |
|
if (len == 0) |
964 |
return; |
return; |
965 |
|
|
966 |
byte[] buf = new byte[s.length()]; |
byte[] buf = new byte[len]; |
967 |
|
|
968 |
for (int i = 0; i < s.length(); i++) |
for (int i = 0; i < len; i++) |
969 |
buf[i] = (byte)(s.charAt(i) & 0xFF); |
buf[i] = (byte)(s.charAt(i) & 0xFF); |
970 |
|
|
971 |
write(buf); |
write(buf); |
1181 |
{ |
{ |
1182 |
synchronized (this) |
synchronized (this) |
1183 |
{ |
{ |
1184 |
|
// FIXME: Need to convert NIO to 64 bit |
1185 |
if (ch == null) |
if (ch == null) |
1186 |
ch = new gnu.java.nio.FileChannelImpl(native_fd, |
ch = new gnu.java.nio.FileChannelImpl( |
1187 |
this); |
(int)(fd.getNativeFd() & 0xFFFF), this); |
1188 |
} |
} |
1189 |
return ch; |
return ch; |
1190 |
} |
} |