|
1 /**************************************************************************** |
|
2 ** |
|
3 ** |
|
4 ** Implementation of QFile class |
|
5 ** |
|
6 ** Created : 930812 |
|
7 ** |
|
8 ** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. |
|
9 ** |
|
10 ** This file is part of the tools module of the Qt GUI Toolkit. |
|
11 ** |
|
12 ** This file may be distributed under the terms of the Q Public License |
|
13 ** as defined by Trolltech AS of Norway and appearing in the file |
|
14 ** LICENSE.QPL included in the packaging of this file. |
|
15 ** |
|
16 ** This file may be distributed and/or modified under the terms of the |
|
17 ** GNU General Public License version 2 as published by the Free Software |
|
18 ** Foundation and appearing in the file LICENSE.GPL included in the |
|
19 ** packaging of this file. |
|
20 ** |
|
21 ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition |
|
22 ** licenses may use this file in accordance with the Qt Commercial License |
|
23 ** Agreement provided with the Software. |
|
24 ** |
|
25 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE |
|
26 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. |
|
27 ** |
|
28 ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for |
|
29 ** information about Qt Commercial License Agreements. |
|
30 ** See http://www.trolltech.com/qpl/ for QPL licensing information. |
|
31 ** See http://www.trolltech.com/gpl/ for GPL licensing information. |
|
32 ** |
|
33 ** Contact info@trolltech.com if any conditions of this licensing are |
|
34 ** not clear to you. |
|
35 ** |
|
36 **********************************************************************/ |
|
37 |
|
38 #include "qglobal.h" |
|
39 #if defined(_OS_WIN32_) |
|
40 #ifdef UNICODE |
|
41 #ifndef _UNICODE |
|
42 #define _UNICODE |
|
43 #endif |
|
44 #endif |
|
45 #endif |
|
46 |
|
47 #include "qfile.h" |
|
48 #include "qfiledefs_p.h" |
|
49 |
|
50 extern bool qt_file_access( const QString& fn, int t ); |
|
51 |
|
52 // NOT REVISED |
|
53 /*! |
|
54 \class QFile qfile.h |
|
55 \brief The QFile class is an I/O device that operates on files. |
|
56 |
|
57 \ingroup io |
|
58 |
|
59 QFile is an I/O device for reading and writing binary and text files. A |
|
60 QFile may be used by itself (readBlock and writeBlock) or by more |
|
61 conveniently using QDataStream or QTextStream. |
|
62 |
|
63 Here is a code fragment that uses QTextStream to read a text |
|
64 file line by line. It prints each line with a line number. |
|
65 \code |
|
66 QFile f("file.txt"); |
|
67 if ( f.open(IO_ReadOnly) ) { // file opened successfully |
|
68 QTextStream t( &f ); // use a text stream |
|
69 QString s; |
|
70 int n = 1; |
|
71 while ( !t.eof() ) { // until end of file... |
|
72 s = t.readLine(); // line of text excluding '\n' |
|
73 printf( "%3d: %s\n", n++, (const char *)s ); |
|
74 } |
|
75 f.close(); |
|
76 } |
|
77 \endcode |
|
78 |
|
79 The QFileInfo class holds detailed information about a file, such as |
|
80 access permissions, file dates and file types. |
|
81 |
|
82 The QDir class manages directories and lists of file names. |
|
83 |
|
84 \sa QDataStream, QTextStream |
|
85 */ |
|
86 |
|
87 |
|
88 /*! |
|
89 Constructs a QFile with no name. |
|
90 */ |
|
91 |
|
92 QFile::QFile() |
|
93 { |
|
94 init(); |
|
95 } |
|
96 |
|
97 /*! |
|
98 Constructs a QFile with a file name \e name. |
|
99 \sa setName() |
|
100 */ |
|
101 |
|
102 QFile::QFile( const QString &name ) |
|
103 : fn(name) |
|
104 { |
|
105 init(); |
|
106 } |
|
107 |
|
108 |
|
109 /*! |
|
110 Destructs a QFile. Calls close(). |
|
111 */ |
|
112 |
|
113 QFile::~QFile() |
|
114 { |
|
115 close(); |
|
116 } |
|
117 |
|
118 |
|
119 /*! |
|
120 \internal |
|
121 Initialize internal data. |
|
122 */ |
|
123 |
|
124 void QFile::init() |
|
125 { |
|
126 setFlags( IO_Direct ); |
|
127 setStatus( IO_Ok ); |
|
128 fh = 0; |
|
129 fd = 0; |
|
130 length = 0; |
|
131 ioIndex = 0; |
|
132 ext_f = FALSE; // not an external file handle |
|
133 } |
|
134 |
|
135 |
|
136 /*! |
|
137 \fn QString QFile::name() const |
|
138 Returns the name set by setName(). |
|
139 \sa setName(), QFileInfo::fileName() |
|
140 */ |
|
141 |
|
142 /*! |
|
143 Sets the name of the file. The name can include an absolute directory |
|
144 path or it can be a name or a path relative to the current directory. |
|
145 |
|
146 Do not call this function if the file has already been opened. |
|
147 |
|
148 Note that if the name is relative QFile does not associate it with the |
|
149 current directory. If you change directory before calling open(), open |
|
150 uses the new current directory. |
|
151 |
|
152 Example: |
|
153 \code |
|
154 QFile f; |
|
155 QDir::setCurrent( "/tmp" ); |
|
156 f.setName( "readme.txt" ); |
|
157 QDir::setCurrent( "/home" ); |
|
158 f.open( IO_ReadOnly ); // opens "/home/readme.txt" under UNIX |
|
159 \endcode |
|
160 |
|
161 Also note that the directory separator '/' works for all operating |
|
162 systems supported by Qt. |
|
163 |
|
164 \sa name(), QFileInfo, QDir |
|
165 */ |
|
166 |
|
167 void QFile::setName( const QString &name ) |
|
168 { |
|
169 if ( isOpen() ) { |
|
170 #if defined(CHECK_STATE) |
|
171 qWarning( "QFile::setName: File is open" ); |
|
172 #endif |
|
173 close(); |
|
174 } |
|
175 fn = name; |
|
176 } |
|
177 |
|
178 /*! |
|
179 Returns TRUE if this file exists, otherwise FALSE. |
|
180 \sa name() |
|
181 */ |
|
182 |
|
183 bool QFile::exists() const |
|
184 { |
|
185 return qt_file_access( fn, F_OK ); |
|
186 } |
|
187 |
|
188 /*! |
|
189 Returns TRUE if the file given by \e fileName exists, otherwise FALSE. |
|
190 */ |
|
191 |
|
192 bool QFile::exists( const QString &fileName ) |
|
193 { |
|
194 return qt_file_access( fileName, F_OK ); |
|
195 } |
|
196 |
|
197 |
|
198 /*! |
|
199 Removes the file specified by the file name currently set. |
|
200 Returns TRUE if successful, otherwise FALSE. |
|
201 |
|
202 The file is closed before it is removed. |
|
203 */ |
|
204 |
|
205 bool QFile::remove() |
|
206 { |
|
207 close(); |
|
208 return remove( fn ); |
|
209 } |
|
210 |
|
211 #if defined(_OS_MAC_) || defined(_OS_MSDOS_) || defined(_OS_WIN32_) || defined(_OS_OS2_) || defined(_OS_CYGWIN_) |
|
212 # define HAS_TEXT_FILEMODE // has translate/text filemode |
|
213 #endif |
|
214 #if defined(O_NONBLOCK) |
|
215 # define HAS_ASYNC_FILEMODE |
|
216 # define OPEN_ASYNC O_NONBLOCK |
|
217 #elif defined(O_NDELAY) |
|
218 # define HAS_ASYNC_FILEMODE |
|
219 # define OPEN_ASYNC O_NDELAY |
|
220 #endif |
|
221 |
|
222 /*! |
|
223 Flushes the file buffer to the disk. |
|
224 |
|
225 close() also flushes the file buffer. |
|
226 */ |
|
227 |
|
228 void QFile::flush() |
|
229 { |
|
230 if ( isOpen() && fh ) // can only flush open/buffered |
|
231 fflush( fh ); // file |
|
232 } |
|
233 |
|
234 /*! |
|
235 Returns TRUE if the end of file has been reached, otherwise FALSE. |
|
236 \sa size() |
|
237 */ |
|
238 |
|
239 bool QFile::atEnd() const |
|
240 { |
|
241 if ( !isOpen() ) { |
|
242 #if defined(CHECK_STATE) |
|
243 qWarning( "QFile::atEnd: File is not open" ); |
|
244 #endif |
|
245 return FALSE; |
|
246 } |
|
247 if ( isDirectAccess() && !isTranslated() ) { |
|
248 if ( at() < length ) |
|
249 return FALSE; |
|
250 } |
|
251 return QIODevice::atEnd(); |
|
252 } |
|
253 |
|
254 /*! |
|
255 Reads a line of text. |
|
256 |
|
257 Reads bytes from the file until end-of-line is reached, or up to \a |
|
258 maxlen bytes, and returns the number of bytes read, or -1 in case of |
|
259 error. The terminating newline is not stripped. |
|
260 |
|
261 This function is efficient only for buffered files. Avoid |
|
262 readLine() for files that have been opened with the \c IO_Raw |
|
263 flag. |
|
264 |
|
265 \sa readBlock(), QTextStream::readLine() |
|
266 */ |
|
267 |
|
268 int QFile::readLine( char *p, uint maxlen ) |
|
269 { |
|
270 if ( maxlen == 0 ) // application bug? |
|
271 return 0; |
|
272 #if defined(CHECK_STATE) |
|
273 CHECK_PTR( p ); |
|
274 if ( !isOpen() ) { // file not open |
|
275 qWarning( "QFile::readLine: File not open" ); |
|
276 return -1; |
|
277 } |
|
278 if ( !isReadable() ) { // reading not permitted |
|
279 qWarning( "QFile::readLine: Read operation not permitted" ); |
|
280 return -1; |
|
281 } |
|
282 #endif |
|
283 int nread; // number of bytes read |
|
284 if ( isRaw() ) { // raw file |
|
285 nread = QIODevice::readLine( p, maxlen ); |
|
286 } else { // buffered file |
|
287 p = fgets( p, maxlen, fh ); |
|
288 if ( p ) { |
|
289 nread = qstrlen( p ); |
|
290 ioIndex += nread; |
|
291 } else { |
|
292 nread = -1; |
|
293 setStatus(IO_ReadError); |
|
294 } |
|
295 } |
|
296 return nread; |
|
297 } |
|
298 |
|
299 |
|
300 /*! |
|
301 Reads a line of text. |
|
302 |
|
303 Reads bytes from the file until end-of-line is reached, or up to \a |
|
304 maxlen bytes, and returns the number of bytes read, or -1 in case of |
|
305 error. The terminating newline is not stripped. |
|
306 |
|
307 This function is efficient only for buffered files. Avoid |
|
308 readLine() for files that have been opened with the \c IO_Raw |
|
309 flag. |
|
310 |
|
311 Note that the string is read as plain Latin1 bytes, not Unicode. |
|
312 |
|
313 \sa readBlock(), QTextStream::readLine() |
|
314 */ |
|
315 |
|
316 int QFile::readLine( QString& s, uint maxlen ) |
|
317 { |
|
318 QByteArray ba(maxlen); |
|
319 int l = readLine(ba.data(),maxlen); |
|
320 if ( l >= 0 ) { |
|
321 ba.truncate(l); |
|
322 s = QString(ba); |
|
323 } |
|
324 return l; |
|
325 } |
|
326 |
|
327 |
|
328 /*! |
|
329 Reads a single byte/character from the file. |
|
330 |
|
331 Returns the byte/character read, or -1 if the end of the file has been |
|
332 reached. |
|
333 |
|
334 \sa putch(), ungetch() |
|
335 */ |
|
336 |
|
337 int QFile::getch() |
|
338 { |
|
339 #if defined(CHECK_STATE) |
|
340 if ( !isOpen() ) { // file not open |
|
341 qWarning( "QFile::getch: File not open" ); |
|
342 return EOF; |
|
343 } |
|
344 if ( !isReadable() ) { // reading not permitted |
|
345 qWarning( "QFile::getch: Read operation not permitted" ); |
|
346 return EOF; |
|
347 } |
|
348 #endif |
|
349 |
|
350 int ch; |
|
351 |
|
352 if ( !ungetchBuffer.isEmpty() ) { |
|
353 int len = ungetchBuffer.length(); |
|
354 ch = ungetchBuffer[ len-1 ]; |
|
355 ungetchBuffer.truncate( len - 1 ); |
|
356 return ch; |
|
357 } |
|
358 |
|
359 if ( isRaw() ) { // raw file (inefficient) |
|
360 char buf[1]; |
|
361 ch = readBlock( buf, 1 ) == 1 ? buf[0] : EOF; |
|
362 } else { // buffered file |
|
363 if ( (ch = getc( fh )) != EOF ) |
|
364 ioIndex++; |
|
365 else |
|
366 setStatus(IO_ReadError); |
|
367 } |
|
368 return ch; |
|
369 } |
|
370 |
|
371 /*! |
|
372 \fn int QFile::writeBlock( const QByteArray& data ) |
|
373 \reimp |
|
374 \internal |
|
375 Should be removed in 3.0 |
|
376 */ |
|
377 |
|
378 /*! |
|
379 Writes the character \e ch to the file. |
|
380 |
|
381 Returns \e ch, or -1 if some error occurred. |
|
382 |
|
383 \sa getch(), ungetch() |
|
384 */ |
|
385 |
|
386 int QFile::putch( int ch ) |
|
387 { |
|
388 #if defined(CHECK_STATE) |
|
389 if ( !isOpen() ) { // file not open |
|
390 qWarning( "QFile::putch: File not open" ); |
|
391 return EOF; |
|
392 } |
|
393 if ( !isWritable() ) { // writing not permitted |
|
394 qWarning( "QFile::putch: Write operation not permitted" ); |
|
395 return EOF; |
|
396 } |
|
397 #endif |
|
398 if ( isRaw() ) { // raw file (inefficient) |
|
399 char buf[1]; |
|
400 buf[0] = ch; |
|
401 ch = writeBlock( buf, 1 ) == 1 ? ch : EOF; |
|
402 } else { // buffered file |
|
403 if ( (ch = putc( ch, fh )) != EOF ) { |
|
404 ioIndex++; |
|
405 if ( ioIndex > length ) // update file length |
|
406 length = ioIndex; |
|
407 } else { |
|
408 setStatus(IO_WriteError); |
|
409 } |
|
410 } |
|
411 return ch; |
|
412 } |
|
413 |
|
414 /*! |
|
415 Puts the character \e ch back into the file and decrements the index if it |
|
416 is not zero. |
|
417 |
|
418 This function is normally called to "undo" a getch() operation. |
|
419 |
|
420 Returns \e ch, or -1 if some error occurred. |
|
421 |
|
422 \sa getch(), putch() |
|
423 */ |
|
424 |
|
425 int QFile::ungetch( int ch ) |
|
426 { |
|
427 #if defined(CHECK_STATE) |
|
428 if ( !isOpen() ) { // file not open |
|
429 qWarning( "QFile::ungetch: File not open" ); |
|
430 return EOF; |
|
431 } |
|
432 if ( !isReadable() ) { // reading not permitted |
|
433 qWarning( "QFile::ungetch: Read operation not permitted" ); |
|
434 return EOF; |
|
435 } |
|
436 #endif |
|
437 if ( ch == EOF ) // cannot unget EOF |
|
438 return ch; |
|
439 |
|
440 if ( isSequentialAccess() && !fh) { |
|
441 // pipe or similar => we cannot ungetch, so do it manually |
|
442 ungetchBuffer +=ch; |
|
443 return ch; |
|
444 } |
|
445 |
|
446 if ( isRaw() ) { // raw file (very inefficient) |
|
447 char buf[1]; |
|
448 at( ioIndex-1 ); |
|
449 buf[0] = ch; |
|
450 if ( writeBlock(buf, 1) == 1 ) |
|
451 at ( ioIndex-1 ); |
|
452 else |
|
453 ch = EOF; |
|
454 } else { // buffered file |
|
455 if ( (ch = ungetc(ch, fh)) != EOF ) |
|
456 ioIndex--; |
|
457 else |
|
458 setStatus( IO_ReadError ); |
|
459 } |
|
460 return ch; |
|
461 } |
|
462 |
|
463 |
|
464 static QCString locale_encoder( const QString &fileName ) |
|
465 { |
|
466 return fileName.local8Bit(); |
|
467 } |
|
468 |
|
469 |
|
470 static QFile::EncoderFn encoder = locale_encoder; |
|
471 |
|
472 /*! |
|
473 When you use QFile, QFileInfo, and QDir to access the filesystem |
|
474 with Qt, you can use Unicode filenames. On Unix, these filenames |
|
475 are converted to an 8-bit encoding. If you want to do your own |
|
476 file I/O on Unix, you should convert the filename using this |
|
477 function. On Windows NT, Unicode filenames are supported directly |
|
478 in the filesystem and this function should be avoided. On Windows 95, |
|
479 non-Latin1 locales are not supported at this time. |
|
480 |
|
481 By default, this function converts to the local 8-bit encoding |
|
482 determined by the user's locale. This is sufficient for |
|
483 filenames that the user chooses. Filenames hard-coded into the |
|
484 application should only use 7-bit ASCII filename characters. |
|
485 |
|
486 The conversion scheme can be changed using setEncodingFunction(). |
|
487 This might be useful if you wish to give the user an option to |
|
488 store in filenames in UTF-8, etc., but beware that such filenames |
|
489 would probably then be unrecognizable when seen by other programs. |
|
490 |
|
491 \sa decodeName() |
|
492 */ |
|
493 |
|
494 QCString QFile::encodeName( const QString &fileName ) |
|
495 { |
|
496 return (*encoder)(fileName); |
|
497 } |
|
498 |
|
499 /*! |
|
500 \enum QFile::EncoderFn |
|
501 |
|
502 This is used by QFile::setEncodingFunction(). |
|
503 */ |
|
504 |
|
505 /*! |
|
506 Sets the function for encoding Unicode filenames. |
|
507 The default encodes in the locale-specific 8-bit encoding. |
|
508 |
|
509 \sa encodeName() |
|
510 */ |
|
511 void QFile::setEncodingFunction( EncoderFn f ) |
|
512 { |
|
513 encoder = f; |
|
514 } |
|
515 |
|
516 static |
|
517 QString locale_decoder( const QCString &localFileName ) |
|
518 { |
|
519 return QString::fromLocal8Bit(localFileName); |
|
520 } |
|
521 |
|
522 static QFile::DecoderFn decoder = locale_decoder; |
|
523 |
|
524 /*! |
|
525 This does the reverse of QFile::encodeName(). |
|
526 |
|
527 \sa setDecodingFunction() |
|
528 */ |
|
529 QString QFile::decodeName( const QCString &localFileName ) |
|
530 { |
|
531 return (*decoder)(localFileName); |
|
532 } |
|
533 |
|
534 /*! |
|
535 \enum QFile::DecoderFn |
|
536 |
|
537 This is used by QFile::setDecodingFunction(). |
|
538 */ |
|
539 |
|
540 /*! |
|
541 Sets the function for decoding 8-bit filenames. |
|
542 The default uses the locale-specific 8-bit encoding. |
|
543 |
|
544 \sa encodeName(), decodeName() |
|
545 */ |
|
546 |
|
547 void QFile::setDecodingFunction( DecoderFn f ) |
|
548 { |
|
549 decoder = f; |
|
550 } |