mirror of
https://github.com/corda/corda.git
synced 2025-01-22 04:18:31 +00:00
Merge pull request #84 from dscho/random-access-file
Write support for the RandomAccessFile
This commit is contained in:
commit
02e433ce61
@ -619,7 +619,7 @@ Java_java_io_File_openDir(JNIEnv* e, jclass, jstring path)
|
||||
#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
|
||||
d->handle = FindFirstFileW(RUNTIME_ARRAY_BODY(buffer), &(d->data));
|
||||
#else
|
||||
d->handle = FindFirstFileExW(RUNTIME_ARRAY_BODY(buffer), FindExInfoStandard, &(d->data), FindExSearchNameMatch, NULL, 0);
|
||||
d->handle = FindFirstFileExW(RUNTIME_ARRAY_BODY(buffer), FindExInfoStandard, &(d->data), FindExSearchNameMatch, NULL, 0);
|
||||
#endif
|
||||
if (d->handle == INVALID_HANDLE_VALUE) {
|
||||
d->dispose();
|
||||
@ -803,28 +803,29 @@ Java_java_io_FileOutputStream_close(JNIEnv* e, jclass, jint fd)
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_java_io_RandomAccessFile_open(JNIEnv* e, jclass, jstring path,
|
||||
jlongArray result)
|
||||
jboolean allowWrite, jlongArray result)
|
||||
{
|
||||
string_t chars = getChars(e, path);
|
||||
if (chars) {
|
||||
jlong peer = 0;
|
||||
jlong length = 0;
|
||||
int flags = (allowWrite ? O_RDWR | O_CREAT : O_RDONLY) | OPEN_MASK;
|
||||
#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
|
||||
#if defined(PLATFORM_WINDOWS)
|
||||
int fd = ::_wopen(chars, O_RDONLY | OPEN_MASK);
|
||||
int fd = ::_wopen(chars, flags);
|
||||
#else
|
||||
int fd = ::open((const char*)chars, O_RDONLY | OPEN_MASK);
|
||||
int fd = ::open((const char*)chars, flags, 0644);
|
||||
#endif
|
||||
releaseChars(e, path, chars);
|
||||
if (fd == -1) {
|
||||
releaseChars(e, path, chars);
|
||||
if (fd == -1) {
|
||||
throwNewErrno(e, "java/io/IOException");
|
||||
return;
|
||||
return;
|
||||
}
|
||||
struct ::stat fileStats;
|
||||
if(::fstat(fd, &fileStats) == -1) {
|
||||
::close(fd);
|
||||
struct ::stat fileStats;
|
||||
if(::fstat(fd, &fileStats) == -1) {
|
||||
::close(fd);
|
||||
throwNewErrno(e, "java/io/IOException");
|
||||
return;
|
||||
return;
|
||||
}
|
||||
peer = fd;
|
||||
length = fileStats.st_size;
|
||||
@ -860,8 +861,8 @@ Java_java_io_RandomAccessFile_readBytes(JNIEnv* e, jclass, jlong peer,
|
||||
#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
|
||||
int fd = (int)peer;
|
||||
if(::lseek(fd, position, SEEK_SET) == -1) {
|
||||
throwNewErrno(e, "java/io/IOException");
|
||||
return -1;
|
||||
throwNewErrno(e, "java/io/IOException");
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint8_t* dst = reinterpret_cast<uint8_t*>
|
||||
@ -871,16 +872,16 @@ Java_java_io_RandomAccessFile_readBytes(JNIEnv* e, jclass, jlong peer,
|
||||
e->ReleasePrimitiveArrayCritical(buffer, dst, 0);
|
||||
|
||||
if(bytesRead == -1) {
|
||||
throwNewErrno(e, "java/io/IOException");
|
||||
return -1;
|
||||
throwNewErrno(e, "java/io/IOException");
|
||||
return -1;
|
||||
}
|
||||
#else
|
||||
HANDLE hFile = (HANDLE)peer;
|
||||
LARGE_INTEGER lPos;
|
||||
lPos.QuadPart = position;
|
||||
if(!SetFilePointerEx(hFile, lPos, nullptr, FILE_BEGIN)) {
|
||||
throwNewErrno(e, "java/io/IOException");
|
||||
return -1;
|
||||
throwNewErrno(e, "java/io/IOException");
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint8_t* dst = reinterpret_cast<uint8_t*>
|
||||
@ -888,8 +889,9 @@ Java_java_io_RandomAccessFile_readBytes(JNIEnv* e, jclass, jlong peer,
|
||||
|
||||
DWORD bytesRead = 0;
|
||||
if(!ReadFile(hFile, dst + offset, length, &bytesRead, nullptr)) {
|
||||
throwNewErrno(e, "java/io/IOException");
|
||||
return -1;
|
||||
e->ReleasePrimitiveArrayCritical(buffer, dst, 0);
|
||||
throwNewErrno(e, "java/io/IOException");
|
||||
return -1;
|
||||
}
|
||||
e->ReleasePrimitiveArrayCritical(buffer, dst, 0);
|
||||
#endif
|
||||
@ -897,6 +899,52 @@ Java_java_io_RandomAccessFile_readBytes(JNIEnv* e, jclass, jlong peer,
|
||||
return (jint)bytesRead;
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jint JNICALL
|
||||
Java_java_io_RandomAccessFile_writeBytes(JNIEnv* e, jclass, jlong peer,
|
||||
jlong position, jbyteArray buffer,
|
||||
int offset, int length)
|
||||
{
|
||||
#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
|
||||
int fd = (int)peer;
|
||||
if(::lseek(fd, position, SEEK_SET) == -1) {
|
||||
throwNewErrno(e, "java/io/IOException");
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint8_t* dst = reinterpret_cast<uint8_t*>
|
||||
(e->GetPrimitiveArrayCritical(buffer, 0));
|
||||
|
||||
int64_t bytesWritten = ::write(fd, dst + offset, length);
|
||||
e->ReleasePrimitiveArrayCritical(buffer, dst, 0);
|
||||
|
||||
if(bytesWritten == -1) {
|
||||
throwNewErrno(e, "java/io/IOException");
|
||||
return -1;
|
||||
}
|
||||
#else
|
||||
HANDLE hFile = (HANDLE)peer;
|
||||
LARGE_INTEGER lPos;
|
||||
lPos.QuadPart = position;
|
||||
if(!SetFilePointerEx(hFile, lPos, nullptr, FILE_BEGIN)) {
|
||||
throwNewErrno(e, "java/io/IOException");
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint8_t* dst = reinterpret_cast<uint8_t*>
|
||||
(e->GetPrimitiveArrayCritical(buffer, 0));
|
||||
|
||||
DWORD bytesWritten = 0;
|
||||
if(!WriteFile(hFile, dst + offset, length, &bytesWritten, nullptr)) {
|
||||
e->ReleasePrimitiveArrayCritical(buffer, dst, 0);
|
||||
throwNewErrno(e, "java/io/IOException");
|
||||
return -1;
|
||||
}
|
||||
e->ReleasePrimitiveArrayCritical(buffer, dst, 0);
|
||||
#endif
|
||||
|
||||
return (jint)bytesWritten;
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_java_io_RandomAccessFile_close(JNIEnv* /* e*/, jclass, jlong peer)
|
||||
{
|
||||
|
@ -11,29 +11,40 @@
|
||||
package java.io;
|
||||
|
||||
import java.lang.IllegalArgumentException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.FileChannel;
|
||||
|
||||
public class RandomAccessFile {
|
||||
private long peer;
|
||||
private File file;
|
||||
private long position = 0;
|
||||
private long length;
|
||||
private boolean allowWrite;
|
||||
|
||||
public RandomAccessFile(String name, String mode)
|
||||
throws FileNotFoundException
|
||||
{
|
||||
if (! mode.equals("r")) throw new IllegalArgumentException();
|
||||
file = new File(name);
|
||||
this(new File(name), mode);
|
||||
}
|
||||
|
||||
public RandomAccessFile(File file, String mode)
|
||||
throws FileNotFoundException
|
||||
{
|
||||
if (file == null) throw new NullPointerException();
|
||||
if (mode.equals("rw")) allowWrite = true;
|
||||
else if (! mode.equals("r")) throw new IllegalArgumentException();
|
||||
this.file = file;
|
||||
open();
|
||||
}
|
||||
|
||||
private void open() throws FileNotFoundException {
|
||||
long[] result = new long[2];
|
||||
open(file.getPath(), result);
|
||||
open(file.getPath(), allowWrite, result);
|
||||
peer = result[0];
|
||||
length = result[1];
|
||||
}
|
||||
|
||||
private static native void open(String name, long[] result)
|
||||
private static native void open(String name, boolean allowWrite, long[] result)
|
||||
throws FileNotFoundException;
|
||||
|
||||
private void refresh() throws IOException {
|
||||
@ -53,7 +64,7 @@ public class RandomAccessFile {
|
||||
}
|
||||
|
||||
public void seek(long position) throws IOException {
|
||||
if (position < 0 || position > length()) throw new IOException();
|
||||
if (position < 0 || (!allowWrite && position > length())) throw new IOException();
|
||||
|
||||
this.position = position;
|
||||
}
|
||||
@ -122,6 +133,14 @@ public class RandomAccessFile {
|
||||
private static native int readBytes(long peer, long position, byte[] buffer,
|
||||
int offset, int length);
|
||||
|
||||
public void write(int b) throws IOException {
|
||||
int count = writeBytes(peer, position, new byte[] { (byte)b }, 0, 1);
|
||||
if (count > 0) position += count;
|
||||
}
|
||||
|
||||
private static native int writeBytes(long peer, long position, byte[] buffer,
|
||||
int offset, int length);
|
||||
|
||||
public void close() throws IOException {
|
||||
if (peer != 0) {
|
||||
close(peer);
|
||||
@ -130,4 +149,50 @@ public class RandomAccessFile {
|
||||
}
|
||||
|
||||
private static native void close(long peer);
|
||||
|
||||
public FileChannel getChannel() {
|
||||
return new FileChannel() {
|
||||
public void close() {
|
||||
if (peer != 0) RandomAccessFile.close(peer);
|
||||
}
|
||||
|
||||
public boolean isOpen() {
|
||||
return peer != 0;
|
||||
}
|
||||
|
||||
public int read(ByteBuffer dst, long position) throws IOException {
|
||||
if (!dst.hasArray()) throw new IOException("Cannot handle " + dst.getClass());
|
||||
// TODO: this needs to be synchronized on the Buffer, no?
|
||||
byte[] array = dst.array();
|
||||
return readBytes(peer, position, array, dst.position(), dst.remaining());
|
||||
}
|
||||
|
||||
public int read(ByteBuffer dst) throws IOException {
|
||||
int count = read(dst, position);
|
||||
if (count > 0) position += count;
|
||||
return count;
|
||||
}
|
||||
|
||||
public int write(ByteBuffer src, long position) throws IOException {
|
||||
if (!src.hasArray()) throw new IOException("Cannot handle " + src.getClass());
|
||||
byte[] array = src.array();
|
||||
return writeBytes(peer, position, array, src.position(), src.remaining());
|
||||
}
|
||||
|
||||
public int write(ByteBuffer src) throws IOException {
|
||||
int count = write(src, position);
|
||||
if (count > 0) position += count;
|
||||
return count;
|
||||
}
|
||||
|
||||
public long position() throws IOException {
|
||||
return getFilePointer();
|
||||
}
|
||||
|
||||
public FileChannel position(long position) throws IOException {
|
||||
seek(position);
|
||||
return this;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
14
classpath/java/nio/BufferUnderflowException.java
Normal file
14
classpath/java/nio/BufferUnderflowException.java
Normal file
@ -0,0 +1,14 @@
|
||||
/* Copyright (c) 2008-2013, Avian Contributors
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software
|
||||
for any purpose with or without fee is hereby granted, provided
|
||||
that the above copyright notice and this permission notice appear
|
||||
in all copies.
|
||||
|
||||
There is NO WARRANTY for this software. See license.txt for
|
||||
details. */
|
||||
|
||||
package java.nio;
|
||||
|
||||
public class BufferUnderflowException extends RuntimeException {
|
||||
}
|
@ -244,4 +244,13 @@ public abstract class ByteBuffer
|
||||
protected void checkGet(int position, int amount) {
|
||||
if (amount > limit-position) throw new IndexOutOfBoundsException();
|
||||
}
|
||||
|
||||
public ByteBuffer order(ByteOrder order) {
|
||||
if (order != ByteOrder.BIG_ENDIAN) throw new UnsupportedOperationException();
|
||||
return this;
|
||||
}
|
||||
|
||||
public ByteOrder order() {
|
||||
return ByteOrder.BIG_ENDIAN;
|
||||
}
|
||||
}
|
||||
|
33
classpath/java/nio/channels/FileChannel.java
Normal file
33
classpath/java/nio/channels/FileChannel.java
Normal file
@ -0,0 +1,33 @@
|
||||
/* Copyright (c) 2008-2013, Avian Contributors
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software
|
||||
for any purpose with or without fee is hereby granted, provided
|
||||
that the above copyright notice and this permission notice appear
|
||||
in all copies.
|
||||
|
||||
There is NO WARRANTY for this software. See license.txt for
|
||||
details. */
|
||||
|
||||
package java.nio.channels;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
public abstract class FileChannel implements Channel {
|
||||
|
||||
public static enum MapMode {
|
||||
PRIVATE, READ_ONLY, READ_WRITE
|
||||
};
|
||||
|
||||
public abstract int read(ByteBuffer dst) throws IOException;
|
||||
|
||||
public abstract int read(ByteBuffer dst, long position) throws IOException;
|
||||
|
||||
public abstract int write(ByteBuffer dst) throws IOException;
|
||||
|
||||
public abstract int write(ByteBuffer dst, long position) throws IOException;
|
||||
|
||||
public abstract long position() throws IOException;
|
||||
|
||||
public abstract FileChannel position(long position) throws IOException;
|
||||
}
|
Loading…
Reference in New Issue
Block a user