KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > python > core > PyFile


1 // Copyright (c) Corporation for National Research Initiatives
2
package org.python.core;
3
4 import java.io.*;
5
6 // To do:
7
// - readinto(array)
8
// - modes w, a should disallow reading
9
// - what to do about buffer size?
10
// - isatty()
11
// - fileno() (defined, but always raises an exception, for urllib)
12

13 /**
14  * A python file wrapper around a java stream, reader/writer or file.
15  */

16
17 public class PyFile extends PyObject
18 {
19
20     private static class FileWrapper {
21         protected boolean reading;
22         protected boolean writing;
23         protected boolean binary;
24
25         void setMode(String JavaDoc mode) {
26             reading = mode.indexOf('r') >= 0;
27             writing = mode.indexOf('w') >= 0 || mode.indexOf("+") >= 0 ||
28                       mode.indexOf('a') >= 0;
29             binary = mode.indexOf('b') >= 0;
30         }
31         public String JavaDoc read(int n) throws java.io.IOException JavaDoc {
32             throw new java.io.IOException JavaDoc("file not open for reading");
33         }
34         public int read() throws java.io.IOException JavaDoc {
35             throw new java.io.IOException JavaDoc("file not open for reading");
36         }
37         public int available() throws java.io.IOException JavaDoc {
38             throw new java.io.IOException JavaDoc("file not open for reading");
39         }
40         public void unread(int c) throws java.io.IOException JavaDoc {
41             throw new java.io.IOException JavaDoc("file doesn't support unread");
42         }
43         public void write(String JavaDoc s) throws java.io.IOException JavaDoc {
44             throw new java.io.IOException JavaDoc("file not open for writing");
45         }
46         public long tell() throws java.io.IOException JavaDoc {
47             throw new java.io.IOException JavaDoc("file doesn't support tell/seek");
48         }
49         public void seek(long pos, int how) throws java.io.IOException JavaDoc {
50             throw new java.io.IOException JavaDoc("file doesn't support tell/seek");
51         }
52         public void flush() throws java.io.IOException JavaDoc {
53         }
54         public void close() throws java.io.IOException JavaDoc {
55         }
56         public void truncate(long position) throws java.io.IOException JavaDoc {
57             throw new java.io.IOException JavaDoc("file doesn't support truncate");
58         }
59
60         public Object JavaDoc __tojava__(Class JavaDoc cls) throws IOException {
61             return null;
62         }
63         protected byte[] getBytes(String JavaDoc s) {
64             // Yes, I known the method is depricated, but it is the fastest
65
// way of converting between between byte[] and String
66
if (binary) {
67                 byte[] buf = new byte[s.length()];
68                 s.getBytes(0, s.length(), buf, 0);
69                 return buf;
70             } else
71                 return s.getBytes();
72         }
73         protected String JavaDoc getString(byte[] buf, int offset, int len) {
74             // Yes, I known the method is depricated, but it is the fastest
75
// way of converting between between byte[] and String
76
if (binary) {
77                 return new String JavaDoc(buf, 0, offset, len);
78             } else
79                 return new String JavaDoc(buf, offset, len);
80         }
81     }
82
83     private static class InputStreamWrapper extends FileWrapper {
84         java.io.InputStream JavaDoc istream;
85
86         public InputStreamWrapper(java.io.InputStream JavaDoc s) {
87             istream = s;
88         }
89
90         public String JavaDoc read(int n) throws java.io.IOException JavaDoc {
91             if (n == 0)
92                 // nothing to do
93
return "";
94             if (n < 0) {
95                 // read until we hit EOF
96
byte buf[] = new byte[1024];
97                 StringBuffer JavaDoc sbuf = new StringBuffer JavaDoc();
98                 for (int read=0; read >= 0; read=istream.read(buf))
99                     sbuf.append(getString(buf, 0, read));
100                 return sbuf.toString();
101             }
102             // read the next chunk available, but make sure it's at least
103
// one byte so as not to trip the `empty string' return value
104
// test done by the caller
105
//int avail = istream.available();
106
//n = (n > avail) ? n : avail;
107
byte buf[] = new byte[n];
108             int read = istream.read(buf);
109             if (read < 0)
110                 // EOF encountered
111
return "";
112             return new String JavaDoc(buf, 0, 0, read);
113         }
114
115         public int read() throws java.io.IOException JavaDoc {
116             return istream.read();
117         }
118
119         public int available() throws java.io.IOException JavaDoc {
120             return istream.available();
121         }
122
123         public void unread(int c) throws java.io.IOException JavaDoc {
124             ((java.io.PushbackInputStream JavaDoc)istream).unread(c);
125         }
126
127         public void close() throws java.io.IOException JavaDoc {
128             istream.close();
129         }
130
131         public Object JavaDoc __tojava__(Class JavaDoc cls) throws IOException {
132             if (InputStream.class.isAssignableFrom(cls))
133                 return istream;
134             return null;
135         }
136     }
137
138     private static class OutputStreamWrapper extends FileWrapper {
139         private java.io.OutputStream JavaDoc ostream;
140
141         public OutputStreamWrapper(java.io.OutputStream JavaDoc s) {
142             ostream = s;
143         }
144
145         private static final int MAX_WRITE = 30000;
146
147         public void write(String JavaDoc s) throws java.io.IOException JavaDoc {
148             byte[] bytes = getBytes(s);
149             int n = bytes.length;
150             int i = 0;
151             while (i < n) {
152                 int sz = n-i;
153                 sz = sz > MAX_WRITE ? MAX_WRITE : sz;
154                 ostream.write(bytes, i, sz);
155                 i += sz;
156             }
157         }
158
159         public void flush() throws java.io.IOException JavaDoc {
160             ostream.flush();
161         }
162
163         public void close() throws java.io.IOException JavaDoc {
164             ostream.close();
165         }
166
167         public Object JavaDoc __tojava__(Class JavaDoc cls) throws IOException {
168             if (OutputStream.class.isAssignableFrom(cls))
169                 return ostream;
170             return null;
171         }
172     }
173
174     private static class IOStreamWrapper extends InputStreamWrapper {
175         private java.io.OutputStream JavaDoc ostream;
176
177         public IOStreamWrapper(java.io.InputStream JavaDoc istream,
178                                java.io.OutputStream JavaDoc ostream) {
179             super(istream);
180             this.ostream = ostream;
181         }
182
183         public void write(String JavaDoc s) throws java.io.IOException JavaDoc {
184             ostream.write(getBytes(s));
185         }
186
187         public void flush() throws java.io.IOException JavaDoc {
188             ostream.flush();
189         }
190
191         public void close() throws java.io.IOException JavaDoc {
192             ostream.close();
193             istream.close();
194         }
195
196         public Object JavaDoc __tojava__(Class JavaDoc cls) throws IOException {
197             if (OutputStream.class.isAssignableFrom(cls))
198                 return ostream;
199             return super.__tojava__(cls);
200         }
201     }
202
203     private static class WriterWrapper extends FileWrapper {
204         private java.io.Writer JavaDoc writer;
205
206         public WriterWrapper(java.io.Writer JavaDoc s) {
207             writer = s;
208         }
209
210         //private static final int MAX_WRITE = 30000;
211

212         public void write(String JavaDoc s) throws java.io.IOException JavaDoc {
213             writer.write(s);
214         }
215
216         public void flush() throws java.io.IOException JavaDoc {
217             writer.flush();
218         }
219
220         public void close() throws java.io.IOException JavaDoc {
221             writer.close();
222         }
223     }
224
225     private static class RFileWrapper extends FileWrapper {
226         /** The default buffer size, in bytes. */
227         protected static final int defaultBufferSize = 4096;
228
229         /** The underlying java.io.RandomAccessFile. */
230         protected java.io.RandomAccessFile JavaDoc file;
231
232         /** The offset in bytes from the file start, of the next read or
233          * write operation. */

234         protected long filePosition;
235
236         /** The buffer used to load the data. */
237         protected byte buffer[];
238
239         /** The offset in bytes of the start of the buffer, from the start
240          * of the file. */

241         protected long bufferStart;
242
243         /** The offset in bytes of the end of the data in the buffer, from
244          * the start of the file. This can be calculated from
245          * <code>bufferStart + dataSize</code>, but it is cached to speed
246          * up the read( ) method. */

247         protected long dataEnd;
248
249         /** The size of the data stored in the buffer, in bytes. This may be
250          * less than the size of the buffer.*/

251         protected int dataSize;
252
253         /** True if we are at the end of the file. */
254         protected boolean endOfFile;
255
256         /** True if the data in the buffer has been modified. */
257         boolean bufferModified = false;
258
259         public RFileWrapper(java.io.RandomAccessFile JavaDoc file) {
260             this(file, 8092);
261         }
262
263         public RFileWrapper(java.io.RandomAccessFile JavaDoc file, int bufferSize) {
264             this.file = file;
265             bufferStart = 0;
266             dataEnd = 0;
267             dataSize = 0;
268             filePosition = 0;
269             buffer = new byte[bufferSize];
270             endOfFile = false;
271         }
272
273         public String JavaDoc read(int n) throws java.io.IOException JavaDoc {
274             if (n < 0) {
275                 n = (int)(file.length() - filePosition);
276                 if (n < 0)
277                     n = 0;
278             }
279             byte[] buf = new byte[n];
280             n = readBytes(buf, 0, n);
281             if (n < 0)
282                 n = 0;
283             return getString(buf, 0, n);
284         }
285
286
287         private int readBytes( byte b[], int off, int len )
288              throws IOException
289         {
290             // Check for end of file.
291
if( endOfFile )
292                 return -1;
293
294             // See how many bytes are available in the buffer - if none,
295
// seek to the file position to update the buffer and try again.
296
int bytesAvailable = (int)(dataEnd - filePosition);
297             if (bytesAvailable < 1) {
298                 seek(filePosition, 0);
299                 return readBytes( b, off, len );
300             }
301
302             // Copy as much as we can.
303
int copyLength = (bytesAvailable >= len) ? len : bytesAvailable;
304             System.arraycopy(buffer, (int)(filePosition - bufferStart),
305                              b, off, copyLength);
306             filePosition += copyLength;
307
308             // If there is more to copy...
309
if (copyLength < len) {
310                 int extraCopy = len - copyLength;
311
312                 // If the amount remaining is more than a buffer's
313
// length, read it directly from the file.
314
if (extraCopy > buffer.length) {
315                     file.seek(filePosition);
316                     extraCopy = file.read(b, off + copyLength,
317                                           len - copyLength);
318                 } else {
319                     // ...or read a new buffer full, and copy as much
320
// as possible...
321
seek(filePosition, 0);
322                     if (!endOfFile) {
323                         extraCopy = (extraCopy > dataSize) ?
324                                         dataSize : extraCopy;
325                         System.arraycopy(buffer, 0, b, off + copyLength,
326                                          extraCopy);
327                     } else {
328                         extraCopy = -1;
329                     }
330                 }
331
332                 // If we did manage to copy any more, update the file
333
// position and return the amount copied.
334
if (extraCopy > 0) {
335                     filePosition += extraCopy;
336                     return copyLength + extraCopy;
337                 }
338             }
339
340             // Return the amount copied.
341
return copyLength;
342         }
343
344
345         public int read() throws java.io.IOException JavaDoc {
346             // If the file position is within the data, return the byte...
347
if (filePosition < dataEnd) {
348                 return (int)(buffer[(int)(filePosition++ - bufferStart)]
349                                    & 0xff);
350             } else if (endOfFile) {
351                // ...or should we indicate EOF...
352
return -1;
353             } else {
354                 // ...or seek to fill the buffer, and try again.
355
seek(filePosition, 0);
356                 return read();
357             }
358         }
359
360         public int available() throws java.io.IOException JavaDoc {
361             return 1;
362         }
363
364         public void unread(int c) throws java.io.IOException JavaDoc {
365             filePosition--;
366         }
367
368         public void write(String JavaDoc s) throws java.io.IOException JavaDoc {
369             byte[] b = getBytes(s);
370             int len = b.length;
371
372             // If the amount of data is small (less than a full buffer)...
373
if (len < buffer.length) {
374                 // If any of the data fits within the buffer...
375
int spaceInBuffer = 0;
376                 int copyLength = 0;
377                 if (filePosition >= bufferStart)
378                     spaceInBuffer = (int)((bufferStart + buffer.length) -
379                                           filePosition);
380                 if (spaceInBuffer > 0) {
381                     // Copy as much as possible to the buffer.
382
copyLength = (spaceInBuffer > len) ?
383                                        len : spaceInBuffer;
384                     System.arraycopy(b, 0, buffer,
385                                      (int)(filePosition - bufferStart),
386                                      copyLength );
387                     bufferModified = true;
388                     long myDataEnd = filePosition + copyLength;
389                     dataEnd = myDataEnd > dataEnd ? myDataEnd : dataEnd;
390                     dataSize = (int)(dataEnd - bufferStart);
391                     filePosition += copyLength;
392                 }
393
394                 // If there is any data remaining, move to the
395
// new position and copy to the new buffer.
396
if (copyLength < len) {
397                     seek(filePosition, 0);
398                     System.arraycopy(b, copyLength, buffer,
399                                      (int)(filePosition - bufferStart),
400                                      len - copyLength);
401                     bufferModified = true;
402                     long myDataEnd = filePosition + (len - copyLength);
403                     dataEnd = myDataEnd > dataEnd ? myDataEnd : dataEnd;
404                     dataSize = (int)(dataEnd - bufferStart);
405                     filePosition += (len - copyLength);
406                 }
407             } else {
408                 // ...or write a lot of data...
409

410                 // Flush the current buffer, and write this data to the file.
411
if (bufferModified) {
412                     flush( );
413                     bufferStart = dataEnd = dataSize = 0;
414                 }
415                 file.write( b, 0, len );
416                 filePosition += len;
417             }
418         }
419
420         public long tell() throws java.io.IOException JavaDoc {
421             return filePosition;
422         }
423
424         public void seek(long pos, int how) throws java.io.IOException JavaDoc {
425             if (how == 1)
426                 pos += filePosition;
427             else if (how == 2)
428                 pos += file.length();
429             if (pos < 0)
430                 pos = 0;
431
432             // If the seek is into the buffer, just update the file pointer.
433
if (pos >= bufferStart && pos < dataEnd) {
434                 filePosition = pos;
435                 endOfFile = false;
436                 return;
437             }
438
439             // If the current buffer is modified, write it to disk.
440
if (bufferModified)
441                 flush();
442
443             // Move to the position on the disk.
444
file.seek(pos);
445             filePosition = file.getFilePointer();
446             bufferStart = filePosition;
447
448             // Fill the buffer from the disk.
449
dataSize = file.read(buffer);
450             if (dataSize < 0) {
451                 dataSize = 0;
452                 endOfFile = true;
453             } else {
454                 endOfFile = false;
455             }
456
457             // Cache the position of the buffer end.
458
dataEnd = bufferStart + dataSize;
459         }
460
461         public void flush() throws java.io.IOException JavaDoc {
462             file.seek(bufferStart);
463             file.write(buffer, 0, dataSize);
464             bufferModified = false;
465             file.getFD().sync();
466         }
467
468         public void close() throws java.io.IOException JavaDoc {
469             if (writing && bufferModified) {
470                 file.seek(bufferStart);
471                 file.write(buffer, 0, (int)dataSize);
472             }
473
474             file.close();
475         }
476
477         public void truncate(long position) throws java.io.IOException JavaDoc {
478             flush();
479             try {
480                 // file.setLength(position);
481
java.lang.reflect.Method JavaDoc m = file.getClass().getMethod(
482                         "setLength", new Class JavaDoc[] { Long.TYPE });
483                 m.invoke(file, new Object JavaDoc[] { new Long JavaDoc(position) });
484             } catch (NoSuchMethodException JavaDoc exc) {
485                 super.truncate(position);
486             } catch (SecurityException JavaDoc exc) {
487                 super.truncate(position);
488             } catch (IllegalAccessException JavaDoc exc) {
489                 super.truncate(position);
490             } catch (java.lang.reflect.InvocationTargetException JavaDoc exc) {
491                 if (exc.getTargetException() instanceof IOException)
492                     throw (IOException) exc.getTargetException();
493                 super.truncate(position);
494             }
495         }
496
497         public Object JavaDoc __tojava__(Class JavaDoc cls) throws IOException {
498             if (OutputStream.class.isAssignableFrom(cls) && writing)
499                 return new FileOutputStream(file.getFD());
500             else if (InputStream.class.isAssignableFrom(cls) && reading)
501                 return new FileInputStream(file.getFD());
502             return super.__tojava__(cls);
503         }
504
505     }
506
507     private static class TextWrapper extends FileWrapper {
508         private FileWrapper file;
509         private String JavaDoc sep;
510         private boolean sep_is_nl;
511
512         public TextWrapper(FileWrapper file) {
513             this.file = file;
514             sep = System.getProperty("line.separator");
515             sep_is_nl = (sep == "\n");
516         }
517
518         public String JavaDoc read(int n) throws java.io.IOException JavaDoc {
519             String JavaDoc s = this.file.read(n);
520             int index = s.indexOf('\r');
521             if (index < 0)
522                 return s;
523             StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
524             int start = 0;
525             int end = s.length();
526             do {
527                 buf.append(s.substring(start, index));
528                 buf.append('\n');
529                 start = index + 1;
530                 if (start < end && s.charAt(start) == '\n')
531                     start++;
532                 index = s.indexOf('\r', start);
533             } while (index >= 0);
534             buf.append(s.substring(start));
535             if (s.endsWith("\r") && file.available() > 0) {
536                 int c = file.read();
537                 if (c != -1 && c != '\n')
538                     file.unread(c);
539             }
540             return buf.toString();
541         }
542
543         public int read() throws java.io.IOException JavaDoc {
544             int c = file.read();
545             if (c != '\r')
546                 return c;
547             if (file.available() > 0) {
548                 c = file.read();
549                 if (c != -1 && c != '\n')
550                     file.unread(c);
551             }
552             return '\n';
553         }
554
555         public void write(String JavaDoc s) throws java.io.IOException JavaDoc {
556             if (!sep_is_nl) {
557                 int index = s.indexOf('\n');
558                 if (index >= 0) {
559                     StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
560                     int start = 0;
561                     do {
562                         buf.append(s.substring(start, index));
563                         buf.append(sep);
564                         start = index + 1;
565                         index = s.indexOf('\n', start);
566                     } while (index >= 0);
567                     buf.append(s.substring(start));
568                     s = buf.toString();
569                 }
570             }
571             this.file.write(s);
572         }
573
574         public long tell() throws java.io.IOException JavaDoc {
575             return file.tell();
576         }
577
578         public void seek(long pos, int how) throws java.io.IOException JavaDoc {
579             file.seek(pos, how);
580         }
581
582         public void flush() throws java.io.IOException JavaDoc {
583             file.flush();
584         }
585
586         public void close() throws java.io.IOException JavaDoc {
587             file.close();
588         }
589
590         public void truncate(long position) throws java.io.IOException JavaDoc {
591             file.truncate(position);
592         }
593
594         public Object JavaDoc __tojava__(Class JavaDoc cls) throws IOException {
595             return file.__tojava__(cls);
596         }
597     }
598
599     //~ BEGIN GENERATED
600
/* type info */
601
602     public static final String JavaDoc exposed_name="file";
603
604     public static final Class JavaDoc exposed_base=PyObject.class;
605
606     public static void typeSetup(PyObject dict,PyType.Newstyle marker) {
607         dict.__setitem__("mode",new PyGetSetDescr("mode",PyFile.class,"getMode",null));
608         dict.__setitem__("name",new PyGetSetDescr("name",PyFile.class,"getName",null));
609         dict.__setitem__("closed",new PyGetSetDescr("closed",PyFile.class,"getClosed",null));
610         class exposed___cmp__ extends PyBuiltinFunctionNarrow {
611
612             private PyFile self;
613
614             public PyObject getSelf() {
615                 return self;
616             }
617
618             exposed___cmp__(PyFile self,PyBuiltinFunction.Info info) {
619                 super(info);
620                 this.self=self;
621             }
622
623             public PyBuiltinFunction makeBound(PyObject self) {
624                 return new exposed___cmp__((PyFile)self,info);
625             }
626
627             public PyObject __call__(PyObject arg0) {
628                 int ret=self.file___cmp__(arg0);
629                 if (ret==-2) {
630                     throw Py.TypeError("file"+".__cmp__(x,y) requires y to be '"+"file"+"', not a '"+(arg0).getType().fastGetName()+"'");
631                 }
632                 return Py.newInteger(ret);
633             }
634
635             public PyObject inst_call(PyObject gself,PyObject arg0) {
636                 PyFile self=(PyFile)gself;
637                 int ret=self.file___cmp__(arg0);
638                 if (ret==-2) {
639                     throw Py.TypeError("file"+".__cmp__(x,y) requires y to be '"+"file"+"', not a '"+(arg0).getType().fastGetName()+"'");
640                 }
641                 return Py.newInteger(ret);
642             }
643
644         }
645         dict.__setitem__("__cmp__",new PyMethodDescr("__cmp__",PyFile.class,1,1,new exposed___cmp__(null,null)));
646         class exposed___iter__ extends PyBuiltinFunctionNarrow {
647
648             private PyFile self;
649
650             public PyObject getSelf() {
651                 return self;
652             }
653
654             exposed___iter__(PyFile self,PyBuiltinFunction.Info info) {
655                 super(info);
656                 this.self=self;
657             }
658
659             public PyBuiltinFunction makeBound(PyObject self) {
660                 return new exposed___iter__((PyFile)self,info);
661             }
662
663             public PyObject __call__() {
664                 return self.file___iter__();
665             }
666
667             public PyObject inst_call(PyObject gself) {
668                 PyFile self=(PyFile)gself;
669                 return self.file___iter__();
670             }
671
672         }
673         dict.__setitem__("__iter__",new PyMethodDescr("__iter__",PyFile.class,0,0,new exposed___iter__(null,null)));
674         class exposed___iternext__ extends PyBuiltinFunctionNarrow {
675
676             private PyFile self;
677
678             public PyObject getSelf() {
679                 return self;
680             }
681
682             exposed___iternext__(PyFile self,PyBuiltinFunction.Info info) {
683                 super(info);
684                 this.self=self;
685             }
686
687             public PyBuiltinFunction makeBound(PyObject self) {
688                 return new exposed___iternext__((PyFile)self,info);
689             }
690
691             public PyObject __call__() {