mirror of
https://github.com/corda/corda.git
synced 2025-02-02 01:08:09 +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)
|
#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
|
||||||
d->handle = FindFirstFileW(RUNTIME_ARRAY_BODY(buffer), &(d->data));
|
d->handle = FindFirstFileW(RUNTIME_ARRAY_BODY(buffer), &(d->data));
|
||||||
#else
|
#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
|
#endif
|
||||||
if (d->handle == INVALID_HANDLE_VALUE) {
|
if (d->handle == INVALID_HANDLE_VALUE) {
|
||||||
d->dispose();
|
d->dispose();
|
||||||
@ -803,28 +803,29 @@ Java_java_io_FileOutputStream_close(JNIEnv* e, jclass, jint fd)
|
|||||||
|
|
||||||
extern "C" JNIEXPORT void JNICALL
|
extern "C" JNIEXPORT void JNICALL
|
||||||
Java_java_io_RandomAccessFile_open(JNIEnv* e, jclass, jstring path,
|
Java_java_io_RandomAccessFile_open(JNIEnv* e, jclass, jstring path,
|
||||||
jlongArray result)
|
jboolean allowWrite, jlongArray result)
|
||||||
{
|
{
|
||||||
string_t chars = getChars(e, path);
|
string_t chars = getChars(e, path);
|
||||||
if (chars) {
|
if (chars) {
|
||||||
jlong peer = 0;
|
jlong peer = 0;
|
||||||
jlong length = 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(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
|
||||||
#if defined(PLATFORM_WINDOWS)
|
#if defined(PLATFORM_WINDOWS)
|
||||||
int fd = ::_wopen(chars, O_RDONLY | OPEN_MASK);
|
int fd = ::_wopen(chars, flags);
|
||||||
#else
|
#else
|
||||||
int fd = ::open((const char*)chars, O_RDONLY | OPEN_MASK);
|
int fd = ::open((const char*)chars, flags, 0644);
|
||||||
#endif
|
#endif
|
||||||
releaseChars(e, path, chars);
|
releaseChars(e, path, chars);
|
||||||
if (fd == -1) {
|
if (fd == -1) {
|
||||||
throwNewErrno(e, "java/io/IOException");
|
throwNewErrno(e, "java/io/IOException");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
struct ::stat fileStats;
|
struct ::stat fileStats;
|
||||||
if(::fstat(fd, &fileStats) == -1) {
|
if(::fstat(fd, &fileStats) == -1) {
|
||||||
::close(fd);
|
::close(fd);
|
||||||
throwNewErrno(e, "java/io/IOException");
|
throwNewErrno(e, "java/io/IOException");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
peer = fd;
|
peer = fd;
|
||||||
length = fileStats.st_size;
|
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)
|
#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
|
||||||
int fd = (int)peer;
|
int fd = (int)peer;
|
||||||
if(::lseek(fd, position, SEEK_SET) == -1) {
|
if(::lseek(fd, position, SEEK_SET) == -1) {
|
||||||
throwNewErrno(e, "java/io/IOException");
|
throwNewErrno(e, "java/io/IOException");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t* dst = reinterpret_cast<uint8_t*>
|
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);
|
e->ReleasePrimitiveArrayCritical(buffer, dst, 0);
|
||||||
|
|
||||||
if(bytesRead == -1) {
|
if(bytesRead == -1) {
|
||||||
throwNewErrno(e, "java/io/IOException");
|
throwNewErrno(e, "java/io/IOException");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
HANDLE hFile = (HANDLE)peer;
|
HANDLE hFile = (HANDLE)peer;
|
||||||
LARGE_INTEGER lPos;
|
LARGE_INTEGER lPos;
|
||||||
lPos.QuadPart = position;
|
lPos.QuadPart = position;
|
||||||
if(!SetFilePointerEx(hFile, lPos, nullptr, FILE_BEGIN)) {
|
if(!SetFilePointerEx(hFile, lPos, nullptr, FILE_BEGIN)) {
|
||||||
throwNewErrno(e, "java/io/IOException");
|
throwNewErrno(e, "java/io/IOException");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t* dst = reinterpret_cast<uint8_t*>
|
uint8_t* dst = reinterpret_cast<uint8_t*>
|
||||||
@ -888,8 +889,9 @@ Java_java_io_RandomAccessFile_readBytes(JNIEnv* e, jclass, jlong peer,
|
|||||||
|
|
||||||
DWORD bytesRead = 0;
|
DWORD bytesRead = 0;
|
||||||
if(!ReadFile(hFile, dst + offset, length, &bytesRead, nullptr)) {
|
if(!ReadFile(hFile, dst + offset, length, &bytesRead, nullptr)) {
|
||||||
throwNewErrno(e, "java/io/IOException");
|
e->ReleasePrimitiveArrayCritical(buffer, dst, 0);
|
||||||
return -1;
|
throwNewErrno(e, "java/io/IOException");
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
e->ReleasePrimitiveArrayCritical(buffer, dst, 0);
|
e->ReleasePrimitiveArrayCritical(buffer, dst, 0);
|
||||||
#endif
|
#endif
|
||||||
@ -897,6 +899,52 @@ Java_java_io_RandomAccessFile_readBytes(JNIEnv* e, jclass, jlong peer,
|
|||||||
return (jint)bytesRead;
|
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
|
extern "C" JNIEXPORT void JNICALL
|
||||||
Java_java_io_RandomAccessFile_close(JNIEnv* /* e*/, jclass, jlong peer)
|
Java_java_io_RandomAccessFile_close(JNIEnv* /* e*/, jclass, jlong peer)
|
||||||
{
|
{
|
||||||
|
@ -11,29 +11,40 @@
|
|||||||
package java.io;
|
package java.io;
|
||||||
|
|
||||||
import java.lang.IllegalArgumentException;
|
import java.lang.IllegalArgumentException;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.channels.FileChannel;
|
||||||
|
|
||||||
public class RandomAccessFile {
|
public class RandomAccessFile {
|
||||||
private long peer;
|
private long peer;
|
||||||
private File file;
|
private File file;
|
||||||
private long position = 0;
|
private long position = 0;
|
||||||
private long length;
|
private long length;
|
||||||
|
private boolean allowWrite;
|
||||||
|
|
||||||
public RandomAccessFile(String name, String mode)
|
public RandomAccessFile(String name, String mode)
|
||||||
throws FileNotFoundException
|
throws FileNotFoundException
|
||||||
{
|
{
|
||||||
if (! mode.equals("r")) throw new IllegalArgumentException();
|
this(new File(name), mode);
|
||||||
file = new File(name);
|
}
|
||||||
|
|
||||||
|
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();
|
open();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void open() throws FileNotFoundException {
|
private void open() throws FileNotFoundException {
|
||||||
long[] result = new long[2];
|
long[] result = new long[2];
|
||||||
open(file.getPath(), result);
|
open(file.getPath(), allowWrite, result);
|
||||||
peer = result[0];
|
peer = result[0];
|
||||||
length = result[1];
|
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;
|
throws FileNotFoundException;
|
||||||
|
|
||||||
private void refresh() throws IOException {
|
private void refresh() throws IOException {
|
||||||
@ -53,7 +64,7 @@ public class RandomAccessFile {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void seek(long position) throws IOException {
|
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;
|
this.position = position;
|
||||||
}
|
}
|
||||||
@ -122,6 +133,14 @@ public class RandomAccessFile {
|
|||||||
private static native int readBytes(long peer, long position, byte[] buffer,
|
private static native int readBytes(long peer, long position, byte[] buffer,
|
||||||
int offset, int length);
|
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 {
|
public void close() throws IOException {
|
||||||
if (peer != 0) {
|
if (peer != 0) {
|
||||||
close(peer);
|
close(peer);
|
||||||
@ -130,4 +149,50 @@ public class RandomAccessFile {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static native void close(long peer);
|
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) {
|
protected void checkGet(int position, int amount) {
|
||||||
if (amount > limit-position) throw new IndexOutOfBoundsException();
|
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…
x
Reference in New Issue
Block a user