KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > armedbear > lisp > FileStream


1 /*
2  * FileStream.java
3  *
4  * Copyright (C) 2004 Peter Graves
5  * $Id: FileStream.java,v 1.16 2004/09/18 20:28:19 piso Exp $
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20  */

21
22 package org.armedbear.lisp;
23
24 import java.io.File JavaDoc;
25 import java.io.FileNotFoundException JavaDoc;
26 import java.io.IOException JavaDoc;
27 import java.io.RandomAccessFile JavaDoc;
28
29 public final class FileStream extends Stream
30 {
31     private static final int BUFSIZE = 4096;
32
33     private final RandomAccessFile JavaDoc raf;
34     private final Pathname pathname;
35     private final int bytesPerUnit;
36     private final byte[] outputBuffer;
37
38     private int outputBufferOffset;
39
40     public FileStream(Pathname pathname, String JavaDoc namestring,
41                       LispObject elementType, LispObject direction,
42                       LispObject ifExists)
43         throws IOException JavaDoc
44     {
45         File JavaDoc file = new File JavaDoc(namestring);
46         String JavaDoc mode = null;
47         if (direction == Keyword.INPUT) {
48             mode = "r";
49             isInputStream = true;
50         } else if (direction == Keyword.OUTPUT) {
51             mode = "rw";
52             isOutputStream = true;
53         } else if (direction == Keyword.IO) {
54             mode = "rw";
55             isInputStream = true;
56             isOutputStream = true;
57         }
58         Debug.assertTrue(mode != null);
59         raf = new RandomAccessFile JavaDoc(file, mode);
60         // ifExists is ignored unless we have an output stream.
61
if (isOutputStream) {
62             if (ifExists == Keyword.OVERWRITE)
63                 raf.seek(0);
64             else if (ifExists == Keyword.APPEND)
65                 raf.seek(raf.length());
66             else
67                 raf.setLength(0);
68         }
69         this.pathname = pathname;
70         this.elementType = elementType;
71         if (elementType == Symbol.CHARACTER || elementType == Symbol.BASE_CHAR) {
72             isCharacterStream = true;
73             bytesPerUnit = 1;
74         } else {
75             isBinaryStream = true;
76             int width;
77             try {
78                 width = Fixnum.getValue(elementType.cadr());
79             }
80             catch (ConditionThrowable t) {
81                 width = 8;
82             }
83             bytesPerUnit = width / 8;
84         }
85         if (isBinaryStream && isOutputStream && !isInputStream && bytesPerUnit == 1)
86             outputBuffer = new byte[BUFSIZE];
87         else
88             outputBuffer = null;
89     }
90
91     public LispObject typeOf()
92     {
93         return Symbol.FILE_STREAM;
94     }
95
96     public LispClass classOf()
97     {
98         return BuiltInClass.FILE_STREAM;
99     }
100
101     public LispObject typep(LispObject typeSpecifier) throws ConditionThrowable
102     {
103         if (typeSpecifier == Symbol.FILE_STREAM)
104             return T;
105         if (typeSpecifier == BuiltInClass.FILE_STREAM)
106             return T;
107         return super.typep(typeSpecifier);
108     }
109
110     public Pathname getPathname()
111     {
112         return pathname;
113     }
114
115     public LispObject listen() throws ConditionThrowable
116     {
117         try {
118             return raf.getFilePointer() < raf.length() ? T : NIL;
119         }
120         catch (IOException JavaDoc e) {
121             signal(new StreamError(this, e));
122             // Not reached.
123
return NIL;
124         }
125     }
126
127     public LispObject fileLength() throws ConditionThrowable
128     {
129         final long length;
130         if (isOpen()) {
131             try {
132                 length = raf.length();
133             }
134             catch (IOException JavaDoc e) {
135                 signal(new StreamError(this, e));
136                 // Not reached.
137
return NIL;
138             }
139         } else {
140             String JavaDoc namestring = pathname.getNamestring();
141             if (namestring == null)
142                 return signal(new SimpleError("Pathname has no namestring: " +
143                                               pathname.writeToString()));
144             File JavaDoc file = new File JavaDoc(namestring);
145             length = file.length(); // in 8-bit bytes
146
}
147         if (isCharacterStream)
148             return number(length);
149         // "For a binary file, the length is measured in units of the
150
// element type of the stream."
151
return number(length / bytesPerUnit);
152     }
153
154     // Returns -1 at end of file.
155
protected int _readChar() throws ConditionThrowable
156     {
157         try {
158             return raf.read();
159         }
160         catch (IOException JavaDoc e) {
161             signal(new StreamError(this, e));
162             // Not reached.
163
return -1;
164         }
165     }
166
167     protected void _unreadChar(int n) throws ConditionThrowable
168     {
169         try {
170             long pos = raf.getFilePointer();
171             if (pos > 0)
172                 raf.seek(pos - 1);
173         }
174         catch (IOException JavaDoc e) {
175             signal(new StreamError(this, e));
176         }
177     }
178
179     protected boolean _charReady() throws ConditionThrowable
180     {
181         return true;
182     }
183
184     public void _writeChar(char c) throws ConditionThrowable
185     {
186         try {
187             raf.write((byte)c);
188             if (c == '\n')
189                 charPos = 0;
190             else
191                 ++charPos;
192         }
193         catch (IOException JavaDoc e) {
194             signal(new StreamError(this, e));
195         }
196     }
197
198     public void _writeChars(char[] chars, int start, int end)
199         throws ConditionThrowable
200     {
201         _writeString(new String JavaDoc(chars, start, end - start));
202     }
203
204     public void _writeString(String JavaDoc s) throws ConditionThrowable
205     {
206         try {
207             raf.writeBytes(s);
208             int index = s.lastIndexOf('\n');
209             if (index < 0)
210                 charPos += s.length();
211             else
212                 charPos = s.length() - (index + 1);
213         }
214         catch (IOException JavaDoc e) {
215             signal(new StreamError(this, e));
216         }
217     }
218
219     public void _writeLine(String JavaDoc s) throws ConditionThrowable
220     {
221         try {
222             raf.writeBytes(s);
223             raf.write((byte)'\n');
224             charPos = 0;
225         }
226         catch (IOException JavaDoc e) {
227             signal(new StreamError(this, e));
228         }
229     }
230
231     // Reads an 8-bit byte.
232
public int _readByte() throws ConditionThrowable
233     {
234         try {
235             return raf.read(); // Reads an 8-bit byte.
236
}
237         catch (IOException JavaDoc e) {
238             signal(new StreamError(this, e));
239             // Not reached.
240
return -1;
241         }
242     }
243
244     // Writes an 8-bit byte.
245
public void _writeByte(int n) throws ConditionThrowable
246     {
247         if (outputBuffer != null) {
248             writeByteToBuffer((byte)n);
249         } else {
250             try {
251                 raf.write((byte)n); // Writes an 8-bit byte.
252
}
253             catch (IOException JavaDoc e) {
254                 signal(new StreamError(this, e));
255             }
256         }
257     }
258
259     public void _finishOutput() throws ConditionThrowable
260     {
261         if (outputBuffer != null)
262             flushOutputBuffer();
263     }
264
265     public void _clearInput() throws ConditionThrowable
266     {
267         try {
268             raf.seek(raf.length());
269         }
270         catch (IOException JavaDoc e) {
271             signal(new StreamError(this, e));
272         }
273     }
274
275     protected long _getFilePosition() throws ConditionThrowable
276     {
277         if (outputBuffer != null)
278             flushOutputBuffer();
279         try {
280             long pos = raf.getFilePointer();
281             return pos / bytesPerUnit;
282         }
283         catch (IOException JavaDoc e) {
284             signal(new StreamError(this, e));
285             // Not reached.
286
return -1;
287         }
288     }
289
290     protected boolean _setFilePosition(LispObject arg) throws ConditionThrowable
291     {
292         if (outputBuffer != null)
293             flushOutputBuffer();
294         try {
295             long pos;
296             if (arg == Keyword.START)
297                 pos = 0;
298             else if (arg == Keyword.END)
299                 pos = raf.length();
300             else {
301                 long n = Fixnum.getValue(arg); // FIXME arg might be a bignum
302
pos = n * bytesPerUnit;
303             }
304             raf.seek(pos);
305         }
306         catch (IOException JavaDoc e) {
307             signal(new StreamError(this, e));
308         }
309         return true;
310     }
311
312     public void _close() throws ConditionThrowable
313     {
314         if (outputBuffer != null)
315             flushOutputBuffer();
316         try {
317             raf.close();
318             setOpen(false);
319         }
320         catch (IOException JavaDoc e) {
321             signal(new StreamError(this, e));
322         }
323     }
324
325     private void writeByteToBuffer(byte b) throws ConditionThrowable
326     {
327         if (outputBufferOffset == BUFSIZE)
328             flushOutputBuffer();
329         outputBuffer[outputBufferOffset++] = b;
330     }
331
332     private void flushOutputBuffer() throws ConditionThrowable
333     {
334         if (outputBufferOffset > 0) {
335             try {
336                 raf.write(outputBuffer, 0, outputBufferOffset);
337                 outputBufferOffset = 0;
338             }
339             catch (IOException JavaDoc e) {
340                 signal(new StreamError(this, e));
341             }
342         }
343     }
344
345     public String JavaDoc toString()
346     {
347         return unreadableString("FILE-STREAM");
348     }
349
350     // ### make-file-stream pathname element-type direction if-exists => stream
351
private static final Primitive MAKE_FILE_STREAM =
352         new Primitive("make-file-stream", PACKAGE_SYS, false,
353                       "pathname element-type direction if-exists")
354     {
355         public LispObject execute(LispObject first, LispObject second,
356                                   LispObject third, LispObject fourth)
357             throws ConditionThrowable
358         {
359             Pathname pathname = Pathname.coerceToPathname(first);
360             LispObject elementType = second;
361             LispObject direction = third;
362             LispObject ifExists = fourth;
363             if (direction != Keyword.INPUT && direction != Keyword.OUTPUT &&
364                 direction != Keyword.IO)
365                 signal(new LispError("Direction must be :INPUT, :OUTPUT, or :IO."));
366             String JavaDoc namestring = pathname.getNamestring();
367             if (namestring == null)
368                 return NIL;
369             try {
370                 return new FileStream(pathname, namestring, elementType,
371                                       direction, ifExists);
372             }
373             catch (FileNotFoundException JavaDoc e) {
374                 return NIL;
375             }
376             catch (IOException JavaDoc e) {
377                 return signal(new StreamError(null, e));
378             }
379         }
380     };
381 }
382
Popular Tags