Root/
Source at commit 1322 created 12 years 8 months ago. By meklort, Add doxygen to utils folder | |
---|---|
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 | }␊ |
551 |