2 |
26 Feb 07 |
jari |
1 |
package org.tigr.microarray.mev.r; |
2 |
26 Feb 07 |
jari |
2 |
|
2 |
26 Feb 07 |
jari |
3 |
import java.io.*; |
2 |
26 Feb 07 |
jari |
4 |
|
2 |
26 Feb 07 |
jari |
/** <b>RFileInputStream</b> is an {@link InputStream} to transfer files |
2 |
26 Feb 07 |
jari |
from <b>Rserve</b> server to the client. It is used very much like |
2 |
26 Feb 07 |
jari |
a {@link FileInputStream}. Currently mark and seek is not supported. |
2 |
26 Feb 07 |
jari |
The current implementation is also "one-shot" only, that means the file |
2 |
26 Feb 07 |
jari |
can be read only once. |
2 |
26 Feb 07 |
jari |
@version $Id$ |
2 |
26 Feb 07 |
jari |
11 |
*/ |
2 |
26 Feb 07 |
jari |
12 |
public class RFileInputStream extends InputStream { |
2 |
26 Feb 07 |
jari |
/** Rtalk class to use for communication with the Rserve */ |
2 |
26 Feb 07 |
jari |
14 |
Rtalk rt; |
2 |
26 Feb 07 |
jari |
/** set to <code>true</code> when {@link #close} was called. |
2 |
26 Feb 07 |
jari |
Any subsequent read requests on closed stream result in an |
2 |
26 Feb 07 |
jari |
{@link IOException} or error result */ |
2 |
26 Feb 07 |
jari |
18 |
boolean closed; |
2 |
26 Feb 07 |
jari |
/** set to <code>true</code> once EOF is reached - or more specifically |
2 |
26 Feb 07 |
jari |
the first time remore fread returns OK and 0 bytes */ |
2 |
26 Feb 07 |
jari |
21 |
boolean eof; |
2 |
26 Feb 07 |
jari |
22 |
|
2 |
26 Feb 07 |
jari |
/** tries to open file on the R server, using specified {@link Rtalk} object |
2 |
26 Feb 07 |
jari |
and filename. Be aware that the filename has to be specified in host |
2 |
26 Feb 07 |
jari |
format (which is usually unix). In general you should not use directories |
2 |
26 Feb 07 |
jari |
since Rserve provides an own directory for every connection. Future Rserve |
2 |
26 Feb 07 |
jari |
servers may even strip all directory navigation characters for security |
2 |
26 Feb 07 |
jari |
purposes. Therefore only filenames without path specification are considered |
2 |
26 Feb 07 |
jari |
valid, the behavior in respect to absolute paths in filenames is undefined. */ |
2 |
26 Feb 07 |
jari |
30 |
RFileInputStream(Rtalk rti, String fn) throws IOException { |
2 |
26 Feb 07 |
jari |
31 |
rt=rti; |
2 |
26 Feb 07 |
jari |
32 |
Rpacket rp=rt.request(Rtalk.CMD_openFile,fn); |
2 |
26 Feb 07 |
jari |
33 |
if (rp==null || !rp.isOk()) |
2 |
26 Feb 07 |
jari |
34 |
throw new IOException((rp==null)?"Connection to Rserve failed":("Request return code: "+rp.getStat())); |
2 |
26 Feb 07 |
jari |
35 |
closed=false; eof=false; |
2 |
26 Feb 07 |
jari |
36 |
} |
2 |
26 Feb 07 |
jari |
37 |
|
2 |
26 Feb 07 |
jari |
/** reads one byte from the file. This function should be avoided, since |
2 |
26 Feb 07 |
jari |
{@link RFileInputStream} provides no buffering. This means that each |
2 |
26 Feb 07 |
jari |
call to this function leads to a complete packet exchange between |
2 |
26 Feb 07 |
jari |
the server and the client. Use {@link #read(byte[],int,int)} instead |
2 |
26 Feb 07 |
jari |
whenever possible. In fact this function calls <code>#read(b,0,1)</code>. |
2 |
26 Feb 07 |
jari |
@return -1 on any failure, or the acquired byte (0..255) on success */ |
2 |
26 Feb 07 |
jari |
44 |
public int read() throws IOException { |
2 |
26 Feb 07 |
jari |
45 |
byte[] b=new byte[1]; |
2 |
26 Feb 07 |
jari |
46 |
if (read(b,0,1)<1) return -1; |
2 |
26 Feb 07 |
jari |
47 |
return b[0]; |
2 |
26 Feb 07 |
jari |
48 |
} |
2 |
26 Feb 07 |
jari |
49 |
|
2 |
26 Feb 07 |
jari |
/** Reads specified number of bytes (or less) from the remote file. |
2 |
26 Feb 07 |
jari |
@param b buffer to store the read bytes |
2 |
26 Feb 07 |
jari |
@param off offset where to strat filling the buffer |
2 |
26 Feb 07 |
jari |
@param len maximal number of bytes to read |
2 |
26 Feb 07 |
jari |
@return number of bytes read or -1 if EOF reached |
2 |
26 Feb 07 |
jari |
55 |
*/ |
2 |
26 Feb 07 |
jari |
56 |
public int read(byte[] b, int off, int len) throws IOException { |
2 |
26 Feb 07 |
jari |
57 |
if (closed) throw new IOException("File is not open"); |
2 |
26 Feb 07 |
jari |
58 |
if (eof) return -1; |
2 |
26 Feb 07 |
jari |
59 |
Rpacket rp=rt.request(Rtalk.CMD_readFile,len); |
2 |
26 Feb 07 |
jari |
60 |
if (rp==null || !rp.isOk()) |
2 |
26 Feb 07 |
jari |
61 |
throw new IOException((rp==null)?"Connection to Rserve failed":("Request return code: "+rp.getStat())); |
2 |
26 Feb 07 |
jari |
62 |
byte[] rd=rp.getCont(); |
2 |
26 Feb 07 |
jari |
63 |
if (rd==null) { |
2 |
26 Feb 07 |
jari |
64 |
eof=true; |
2 |
26 Feb 07 |
jari |
65 |
return -1; |
2 |
26 Feb 07 |
jari |
66 |
}; |
2 |
26 Feb 07 |
jari |
67 |
int i=0; |
2 |
26 Feb 07 |
jari |
68 |
while(i<rd.length) { b[off+i]=rd[i]; i++; }; |
2 |
26 Feb 07 |
jari |
69 |
return rd.length; |
2 |
26 Feb 07 |
jari |
70 |
} |
2 |
26 Feb 07 |
jari |
71 |
|
2 |
26 Feb 07 |
jari |
/** close stream - is not related to the actual Rconnection, calling |
2 |
26 Feb 07 |
jari |
close does not close the Rconnection |
2 |
26 Feb 07 |
jari |
74 |
*/ |
2 |
26 Feb 07 |
jari |
75 |
public void close() throws IOException { |
2 |
26 Feb 07 |
jari |
76 |
Rpacket rp=rt.request(Rtalk.CMD_closeFile,(byte[])null); |
2 |
26 Feb 07 |
jari |
77 |
if (rp==null || !rp.isOk()) |
2 |
26 Feb 07 |
jari |
78 |
throw new IOException((rp==null)?"Connection to Rserve failed":("Request return code: "+rp.getStat())); |
2 |
26 Feb 07 |
jari |
79 |
closed=true; |
2 |
26 Feb 07 |
jari |
80 |
} |
2 |
26 Feb 07 |
jari |
81 |
} |