]> gerrit.simantics Code Review - simantics/r.git/blob - bundles/org.simantics.r.scl/src/org/rosuda/REngine/Rserve/RFileInputStream.java
(refs #6833) Test RExp inheritance in SCL
[simantics/r.git] / bundles / org.simantics.r.scl / src / org / rosuda / REngine / Rserve / RFileInputStream.java
1 package org.rosuda.REngine.Rserve;
2
3 // JRclient library - client interface to Rserve, see http://www.rosuda.org/Rserve/
4 // Copyright (C) 2004 Simon Urbanek
5 // --- for licensing information see LICENSE file in the original JRclient distribution ---
6
7 import java.io.*;
8 import org.rosuda.REngine.*;
9 import org.rosuda.REngine.Rserve.protocol.*;
10
11 /** <b>RFileInputStream</b> is an {@link InputStream} to transfer files
12     from <b>Rserve</b> server to the client. It is used very much like
13     a {@link FileInputStream}. Currently mark and seek is not supported.
14     The current implementation is also "one-shot" only, that means the file
15     can be read only once.
16     @version $Id$
17 */
18 public class RFileInputStream extends InputStream {
19     /** RTalk class to use for communication with the Rserve */
20     RTalk rt;
21     /** set to <code>true</code> when {@link #close} was called.
22         Any subsequent read requests on closed stream  result in an 
23         {@link IOException} or error result */
24     boolean closed;
25     /** set to <code>true</code> once EOF is reached - or more specifically
26         the first time remore fread returns OK and 0 bytes */
27     boolean eof;
28
29     /** tries to open file on the R server, using specified {@link RTalk} object
30         and filename. Be aware that the filename has to be specified in host
31         format (which is usually unix). In general you should not use directories
32         since Rserve provides an own directory for every connection. Future Rserve
33         servers may even strip all directory navigation characters for security
34         purposes. Therefore only filenames without path specification are considered
35         valid, the behavior in respect to absolute paths in filenames is undefined. */
36     RFileInputStream(RTalk rti, String fn) throws IOException {
37         rt=rti;
38         RPacket rp=rt.request(RTalk.CMD_openFile,fn);
39         if (rp==null || !rp.isOk())
40             throw new IOException((rp==null)?"Connection to Rserve failed":("Request return code: "+rp.getStat()));
41         closed=false; eof=false;
42     }
43
44     /** reads one byte from the file. This function should be avoided, since
45         {@link RFileInputStream} provides no buffering. This means that each
46         call to this function leads to a complete packet exchange between
47         the server and the client. Use {@link #read(byte[],int,int)} instead
48         whenever possible. In fact this function calls <code>#read(b,0,1)</code>.
49         @return -1 on any failure, or the acquired byte (0..255) on success */
50     public int read() throws IOException {
51         byte[] b=new byte[1];
52         if (read(b,0,1)<1) return -1;
53         return b[0];
54     }
55
56     /** Reads specified number of bytes (or less) from the remote file.
57         @param b buffer to store the read bytes
58         @param off offset where to strat filling the buffer
59         @param len maximal number of bytes to read
60         @return number of bytes read or -1 if EOF reached
61     */
62     public int read(byte[] b, int off, int len) throws IOException {
63         if (closed) throw new IOException("File is not open");
64         if (eof) return -1;
65         RPacket rp=rt.request(RTalk.CMD_readFile,len);
66         if (rp==null || !rp.isOk())
67             throw new IOException((rp==null)?"Connection to Rserve failed":("Request return code: "+rp.getStat()));
68         byte[] rd=rp.getCont();
69         if (rd==null) {
70             eof=true;
71             return -1;
72         };
73         int i=0;
74         while(i<rd.length) { b[off+i]=rd[i]; i++; };
75         return rd.length;
76     }
77
78     /** close stream - is not related to the actual RConnection, calling
79         close does not close the RConnection
80     */
81     public void close() throws IOException {
82         RPacket rp=rt.request(RTalk.CMD_closeFile,(byte[])null);
83         if (rp==null || !rp.isOk())
84             throw new IOException((rp==null)?"Connection to Rserve failed":("Request return code: "+rp.getStat()));
85         closed=true;
86     }
87 }