DCL 4.0
Loading...
Searching...
No Matches
File Class Reference

#include <File.h>

Inheritance diagram for File:
Object PollAble SerialPort Socket SSLSocket

Public Types

enum  Whence { BEGIN , CURRENT , END }

Public Member Functions

virtual String toString () const
virtual ~File ()
 File (const String &_path, int _oflags=READONLY, int _mode=0666) __DCL_THROWS1(IOException *)
void open (const String &_path, int _oflags=READONLY, int _mode=0666) __DCL_THROWS1(IOException *)
 File (HandleType _handle, int _ohints, bool _closeOnClose) __DCL_THROWS1(IOException *)
void open (HandleType _handle, int _ohints, bool _closeOnClose) __DCL_THROWS1(IOException *)
virtual void sync () __DCL_THROWS1(IOException *)
virtual void close () __DCL_THROWS1(IOException *)
virtual size_t available () const __DCL_THROWS1(IOException *)
virtual size_t read (void *_buf, size_t _n) __DCL_THROWS1(IOException *)
virtual size_t write (const void *_buf, size_t _n) __DCL_THROWS1(IOException *)
off_t seek (off_t _offset, int _whence) __DCL_THROWS1(IOException *)
off_t size () const __DCL_THROWS1(IOException *)
DateTime mtime () const __DCL_THROWS1(IOException *)
bool time (time_t *_atime, time_t *_mtime, time_t *_ctime) const
HandleType handle () const
const String & path () const
Public Member Functions inherited from Object
virtual void destroy ()
String className () const
bool isInstanceOf (const std::type_info &typeinfo) const
virtual const std::type_info & typeInfo () const

Static Public Member Functions

static FileopenTempFile (const String &_dirname, const String &_prefix, unsigned int _mode=0666) __DCL_THROWS1(IOException *)

Protected Member Functions

 File ()
 File (HandleType _handle, const String &_path)
Protected Member Functions inherited from Object
virtual ~Object ()
 Object ()

Protected Attributes

String __path
HandleType __handle
bool __closeOnClose

Detailed Description

운영체제 파일을 추상화 한다.

이 클래스의 목적은 서로다른 운영체제에서 파일 접근을 위한 표준 접근방법을 제공하는 것으로, 기본 모델은 UNIX의 것을 따른다.

Definition at line 37 of file File.h.

Member Enumeration Documentation

◆ Whence

Enumerator
BEGIN 
CURRENT 
END 

Definition at line 203 of file File.h.

204 {
205 BEGIN, // SEEK_SET
206 CURRENT, // SEEK_CUR
207 END // SEEK_END
208 };
@ CURRENT
Definition File.h:206
@ END
Definition File.h:207
@ BEGIN
Definition File.h:205

Constructor & Destructor Documentation

◆ File() [1/4]

File::File ( )
protected

Definition at line 59 of file File.cpp.

60{
62 __closeOnClose = true;
63#if __DCL_WINDOWS
64 __fileType = UNKNOWN;
65 __readEvent = NULL;
66 __writeEvent = NULL;
67#endif
68}
#define NULL
Definition Config.h:340
#define INVALID_HANDLE_VALUE
Definition Dir.cpp:31
HandleType __handle
Definition File.h:251
bool __closeOnClose
Definition File.h:252

◆ File() [2/4]

File::File ( HandleType _handle,
const String & _path )
protected

열려진 파일핸들을 사용하여 객체를 구성한다.

이것은 openTempFile(const String&,const String&,int) 사용한다.

Definition at line 258 of file File.cpp.

259{
260 __handle = _handle;
261 __path = _path;
262 __closeOnClose = true;
263}
String __path
Definition File.h:250

◆ ~File()

virtual File::~File ( )
virtual

객체의 파괴를 수행한다. close하지 않았으면 close()하며 예외가 발생하면 무시한다.

◆ File() [3/4]

File::File ( const String & _path,
int _oflags = READONLY,
int _mode = 0666 )

주어진 경로의 파일을 열고 객체를 구성한다.

파일의 종류는 일반파일(Regular File), 시리얼 포트(COM#N, /dev/ttyS#N, /dev/ttyUSBS#N), Windows에서 콘솔(COM), 명명된 파이프(Named Pipe)이다.

Parameters
_pathWindows에서 COM#N이 사용되면 큐 버퍼는 2048로 설정된다.
_oflagsWindows CON은 READONLY, WRITEONLY만 사용된다. Windows에서 NONBLOCK을 사용하면 FILE_FLAG_OVERRLAPPED가 적용되고, read, write를 위한 이벤트를 생성한다.
_modeWindows에서는 무시되고, UNIX에서 umask가 적용된다.

Definition at line 70 of file File.cpp.

72{
74 open(_path, _oflags, _mode);
75}
void open(const String &_path, int _oflags=READONLY, int _mode=0666) __DCL_THROWS1(IOException *)
Definition File.cpp:77

◆ File() [4/4]

File::File ( HandleType _handle,
int _ohints,
bool _closeOnClose )

열려진 파일핸들을 사용하여 객체를 구성한다.

See also
File::OpenFlags
Parameters
_handleUNIX에서 open, pipe등의 시스템콜 리턴값, Windows에서는 CreateFile, CreatePipe 등의 리턴값이다.
_ohintsWindows에서 _handle의 생성 플래그에 FILE_FLAG_OVERLAPPED가 사용되었거나, ioctlsock FIONBIO의 사용으로 NONBLOCK 으로 설정된 핸들에 대하여 사용된다. READONLY, WRITEONLY, READWRITE와 NONBLOCK이 조합된다. UNIX에서는 무시된다.
_closeOnCloseclose()에서 _handle을 닫을지 여부를 지정한다.

Definition at line 265 of file File.cpp.

267{
269 open(_handle, _ohints, _closeOnClose);
270}

Member Function Documentation

◆ available()

size_t File::available ( ) const
virtual

Non-Block으로 읽혀질 수 있는 바이트의 수를 리턴한다.

UNIX에서 ioctl FIONREAD를 사용한다. WINDOWS에서는 일반파일, (Named) Pipe, 시리얼포트(COM#N), 콘솔 및 소켓에 대하여 구현되어 있고, 그 외에는 항상 0을 리턴한다.

Definition at line 401 of file File.cpp.

403{
405
406#if __DCL_WINDOWS
407 size_t nbytes = 0;
408 switch (__fileType) {
409 case REGULAR: {
410 LARGE_INTEGER fileSize;
411 if (GetFileSizeEx(__handle, &fileSize)) {
412 LARGE_INTEGER distanceToMove;
413 LARGE_INTEGER newFilePointer;
414 distanceToMove.QuadPart = 0;
415 if (SetFilePointerEx(__handle, distanceToMove, &newFilePointer, FILE_CURRENT))
416 nbytes = (size_t)(fileSize.QuadPart - newFilePointer.QuadPart);
417 }
418 break;
419 }
420 case PIPE: {
421 DWORD dwTotalBytesAvail;
422 if (PeekNamedPipe(__handle, NULL, 0, NULL, &dwTotalBytesAvail, NULL))
423 nbytes = (size_t)dwTotalBytesAvail;
424 break;
425 }
426 case CONSOLE: {
427 INPUT_RECORD buf[200]; // 200 * (sizeof(INPUT_RECORD) == 20) 4000
428 DWORD dwEvents = 0;
429 if (PeekConsoleInput(__handle, buf, __countof(buf, INPUT_RECORD), &dwEvents)) {
430 size_t n = 0;
431 for (int i = 0; i < __countof(buf, INPUT_RECORD); i++) {
432 if (buf[i].EventType == KEY_EVENT) {
433 KEY_EVENT_RECORD& ev = buf[i].Event.KeyEvent;
434 if (ev.bKeyDown && ev.uChar.AsciiChar != 0) {
435 if (ev.uChar.AsciiChar == 13) {
436 nbytes = n + 2; // ReadFile에서 \r\n으로 변환되어 읽힌다.
437 break;
438 }
439 n += ev.wRepeatCount;
440 }
441 }
442 }
443 // NONBLOCK
444 if (nbytes == 0 && __readEvent)
445 nbytes = n;
446 }
447 break;
448 }
449 case COMM: {
450 DWORD dwErrors;
451 COMSTAT stat;
452 if (ClearCommError(__handle, &dwErrors, &stat))
453 nbytes = (size_t)stat.cbInQue;
454 break;
455 }
456#if 0
457 // 이 부분은 Socket 클래스에서 override한다.
458 case SOCKET: {
459 u_long n = 0;
460 if (ioctlsocket((::SOCKET)__handle, FIONREAD, &n))
461 throw new IOException(__path, WSAGetLastError());
462 nbytes = (size_t)n;
463 break;
464 }
465#endif
466 }
467 return nbytes;
468#else
469 // x64 nbytes를 off_t(long long int)로 하면 안된다.
470 unsigned int nbytes = 0;
471 ioctl(__handle, FIONREAD, &nbytes);
472 return (size_t)nbytes;
473#endif
474}
#define __countof(array, type)
Definition Config.h:365
#define __DCL_ASSERT_HANDLE(expr)
Definition Object.h:383
ByteBuffer * buf
void CharsetConvertException *size_t n
Definition SQLField.cpp:253
#define ioctlsocket(s, cmd, argp)
Definition Socket.cpp:40

◆ close()

void File::close ( )
virtual

파일을 닫는다.

Reimplemented in SSLSocket.

Definition at line 363 of file File.cpp.

366{
368
369#if __DCL_WINDOWS
370 if (__fileType == COMM)
371 PurgeComm(__handle, PURGE_RXABORT | PURGE_RXCLEAR
372 | PURGE_TXABORT | PURGE_TXCLEAR);
373 __fileType = UNKNOWN;
374 if (__readEvent) {
375 CloseHandle(__readEvent);
376 __readEvent = NULL;
377 }
378 if (__writeEvent) {
379 CloseHandle(__writeEvent);
380 __writeEvent = NULL;
381 }
382#endif
383
384 if (!__closeOnClose)
385 return;
386
387 HandleType handle = __handle;
388 String path = __path;
390 __path.clear();
391
392#if __DCL_WINDOWS
393 if (!CloseHandle(handle))
394 throw new IOException(path, GetLastError());
395#else
396 if (::close(handle))
397 throw(new IOException(path, errno));
398#endif
399}
HandleType handle() const
Definition File.h:242
virtual void close() __DCL_THROWS1(IOException *)
Definition File.cpp:363
const String & path() const
Definition File.h:247

◆ handle()

HandleType File::handle ( ) const
inline

파일의 핸들값을 리턴한다. (File::HandleType)-1 이면 닫혀진 상태이다.

Definition at line 242 of file File.h.

242{ return __handle; }

◆ mtime()

DateTime File::mtime ( ) const

파일 최종 수정된 시간을 얻는다.

Definition at line 659 of file File.cpp.

661{
662 time_t mtime;
663 if (!time((time_t * )NULL, &mtime, (time_t * )NULL)) {
664#if __DCL_WINDOWS
665 throw new IOException(__path, GetLastError());
666#else
667 throw (new IOException(__path, errno));
668#endif
669 }
670 return DateTime(mtime);
671}
bool time(time_t *_atime, time_t *_mtime, time_t *_ctime) const
Definition File.cpp:673
DateTime mtime() const __DCL_THROWS1(IOException *)
Definition File.cpp:659

◆ open() [1/2]

void File::open ( const String & _path,
int _oflags = READONLY,
int _mode = 0666 )

이미 열린 파일은 닫고, 파일을 새로 연다.

See also
File(const String& _path, int _oflags, int _mode)

Definition at line 77 of file File.cpp.

79{
81 close();
82
83 __closeOnClose = true;
84#if __DCL_WINDOWS
85 __fileType = UNKNOWN;
86 __readEvent = NULL;
87 __writeEvent = NULL;
88
89 FileType fileType = UNKNOWN;
90 // Console, COMM 을 검사한다.
91 HANDLE handle = CreateFileW(_path, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
93 DWORD dw;
94 DCB dcb;
95 if (GetNamedPipeInfo(handle, NULL, NULL, NULL, NULL))
96 fileType = PIPE;
97 else if (GetConsoleMode(handle, &dw))
98 fileType = CONSOLE;
99 else if (GetCommState(handle, &dcb))
100 fileType = COMM;
101 CloseHandle(handle);
103 }
104
105 DWORD dwDesiredAccess = GENERIC_READ;
106 DWORD dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
107 SECURITY_ATTRIBUTES securityAttributes = { sizeof(SECURITY_ATTRIBUTES), NULL, TRUE };
108 DWORD dwCreationDisposition = OPEN_EXISTING;
109 DWORD dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL;
110
111 switch (_oflags & (READONLY | WRITEONLY | READWRITE)) {
112 default:
113 // _oflags == 0 이면 READONLY 인 것으로 간주한다.
114 case READONLY:
115 dwDesiredAccess = GENERIC_READ;
116 break;
117 case WRITEONLY:
118 if (_oflags & APPEND)
119 dwDesiredAccess = GENERIC_READ | GENERIC_WRITE;
120 else
121 dwDesiredAccess = GENERIC_WRITE;
122 break;
123 case READWRITE:
124 dwDesiredAccess = GENERIC_READ | GENERIC_WRITE;
125 break;
126 }
127
128 if (_oflags & EXCLUSIVE) {
129 dwShareMode = 0;
130 }
131
132 switch (_oflags & (CREATE | EXCLUSIVE | TRUNCATE)) {
133 default:
134 case EXCLUSIVE:
135 dwCreationDisposition = OPEN_EXISTING;
136 break;
137 case CREATE:
138 case CREATE | TRUNCATE:
139 dwCreationDisposition = OPEN_ALWAYS;
140 break;
141 case CREATE | EXCLUSIVE:
142 case CREATE | EXCLUSIVE | TRUNCATE:
143 dwCreationDisposition = CREATE_NEW;
144 break;
145 case TRUNCATE:
146 case TRUNCATE | EXCLUSIVE:
147 dwCreationDisposition = TRUNCATE_EXISTING;
148 break;
149 }
150
151 if (_oflags & NONBLOCK)
152 dwFlagsAndAttributes |= FILE_FLAG_OVERLAPPED;
153
154 if (_oflags & SYNC)
155 dwFlagsAndAttributes |= FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH;
156
157 if (fileType == CONSOLE || fileType == PIPE) {
158
159 handle = CreateFileW(_path, dwDesiredAccess, dwShareMode, &securityAttributes,
160 OPEN_EXISTING, dwFlagsAndAttributes, NULL);
161 }
162 else if (fileType == COMM) {
163 handle = CreateFileW(_path, dwDesiredAccess, dwShareMode, &securityAttributes,
164 OPEN_EXISTING, dwFlagsAndAttributes, NULL);
165 }
166 else {
167 // UNKNOWN, maybe REGULAR
168 switch (dwDesiredAccess & (GENERIC_READ | GENERIC_WRITE)) {
169 case GENERIC_READ:
170 dwFlagsAndAttributes |= FILE_FLAG_SEQUENTIAL_SCAN;
171 break;
172 case GENERIC_READ | GENERIC_WRITE:
173 dwFlagsAndAttributes |= FILE_FLAG_RANDOM_ACCESS;
174 break;
175 }
176
177 if ((_oflags & TRUNCATE) && ((dwDesiredAccess & GENERIC_WRITE) == GENERIC_WRITE))
178 handle = CreateFileW(_path, dwDesiredAccess, dwShareMode,
179 &securityAttributes, TRUNCATE_EXISTING, dwFlagsAndAttributes, NULL);
180
182 handle = CreateFileW(_path, dwDesiredAccess, dwShareMode,
183 &securityAttributes, dwCreationDisposition, dwFlagsAndAttributes, NULL);
184
186 && (_oflags & APPEND) && ((dwDesiredAccess & GENERIC_READ) == GENERIC_READ)) {
187 fileType = REGULAR;
188 if (SetFilePointer(handle, 0, NULL, FILE_END) == INVALID_SET_FILE_POINTER) {
189 DWORD dwSaveError = GetLastError();
190 CloseHandle(handle);
192 SetLastError(dwSaveError);
193 }
194 }
195 }
196
197 // _oflags에 NONBLOCK이 있으면 read, write Overrlapped Io 하도록 Event 객체를 생성한다.
198 HANDLE readEvent = NULL, writeEvent = NULL;
199 if (handle != INVALID_HANDLE_VALUE && _oflags & NONBLOCK) {
200 __DCL_ASSERT(dwFlagsAndAttributes & FILE_FLAG_OVERLAPPED);
201 if (_oflags & (WRITEONLY | READWRITE))
202 writeEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
203
204 // _oflags == 0 이면 READONLY 인 것으로 간주한다.
205 if (_oflags & (READONLY | READWRITE) || writeEvent == NULL)
206 readEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
207
208 if (readEvent == NULL && writeEvent == NULL) {
209 DWORD dwSaveError = GetLastError();
210 if (readEvent)
211 CloseHandle(readEvent);
212 if (writeEvent)
213 CloseHandle(writeEvent);
214
215 CloseHandle(handle);
217 SetLastError(dwSaveError);
218 }
219 }
220
222 throw new IOException(_path, GetLastError());
223
224 __fileType = fileType;
225 __readEvent = readEvent;
226 __writeEvent = writeEvent;
227#else
228 int oflags = 0;
229 if (_oflags & READONLY)
230 oflags |= O_RDONLY;
231 if (_oflags & WRITEONLY)
232 oflags |= O_WRONLY;
233 if (_oflags & READWRITE)
234 oflags |= O_RDWR;
235 if (_oflags & CREATE)
236 oflags |= O_CREAT;
237 if (_oflags & EXCLUSIVE)
238 oflags |= O_EXCL;
239 if (_oflags & NOCTTY)
240 oflags |= O_NOCTTY;
241 if (_oflags & APPEND)
242 oflags |= O_APPEND;
243 if (_oflags & TRUNCATE)
244 oflags |= O_TRUNC;
245 if (_oflags & NONBLOCK)
246 oflags |= O_NONBLOCK;
247 if (_oflags & SYNC)
248 oflags |= O_SYNC;
249
250 int handle = __open(_path, oflags, _mode);
251 if (handle == -1)
252 throw new IOException(_path, errno);
253#endif
255 __path = _path;
256}
DCLCAPI int __open(const String &_path, int _oflags,...)
Definition _fcntl.cpp:23
#define TRUE
#define FALSE
#define __DCL_ASSERT(expr)
Definition Object.h:371

◆ open() [2/2]

void File::open ( HandleType _handle,
int _ohints,
bool _closeOnClose )

이미 열려진 파일핸들을 사용하여 객체를 구성한다.

See also
File(HandleType _handle, int _ohints, bool _closeOnClose

Definition at line 272 of file File.cpp.

274{
276 close();
277
278#if __DCL_WINDOWS
279 __fileType = UNKNOWN;
280 __readEvent = NULL;
281 __writeEvent = NULL;
282
283 StringBuilder path;
284 FileType fileType = UNKNOWN;
285
286 wchar_t nameInfo[PATH_MAX + 1 + 4] = { L'\0' };
287 DWORD dwConsoleMode;
288 DCB dcb;
289 if (GetFileInformationByHandleEx(_handle, FileNameInfo, nameInfo, sizeof(nameInfo))) {
290 fileType = REGULAR;
291 path.assign(((FILE_NAME_INFO*)nameInfo)->FileName);
292 }
293 else if (GetNamedPipeInfo(_handle, NULL, NULL, NULL, NULL)) {
294 path.format(__T("(pipe: %d)"), _handle);
295 fileType = PIPE;
296 }
297 else if (GetConsoleMode(_handle, &dwConsoleMode)) {
298 path = __T("CON");
299 fileType = CONSOLE;
300 }
301 else if (GetCommState(_handle, &dcb)) {
302 path = __T("COM#N");
303 fileType = COMM;
304 }
305 else {
306 path.format(__T("(HANDLE: %p)"), _handle);
307 throw new IOException(path, ERROR_INVALID_HANDLE);
308 }
309
310 HANDLE readEvent = NULL, writeEvent = NULL;
311 if (_ohints & NONBLOCK) {
312 if (_ohints & (WRITEONLY | READWRITE))
313 writeEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
314
315 // _oflags == 0 이면 READONLY 인 것으로 간주한다.
316 if (_ohints & (READONLY | READWRITE) || writeEvent == NULL)
317 readEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
318
319 if (readEvent == NULL && writeEvent == NULL) {
320 DWORD dwSaveError = GetLastError();
321 if (readEvent)
322 CloseHandle(readEvent);
323 if (writeEvent)
324 CloseHandle(writeEvent);
325
326 throw new IOException(path, dwSaveError);
327 }
328 }
329
330 __path = path.toString();
331 __fileType = fileType;
332 __readEvent = readEvent;
333 __writeEvent = writeEvent;
334#else
335 if (isatty(_handle)) {
336 if (__ttyname(_handle, __path) != 0)
337 throw new IOException(className(), errno);
338 }
339 else
340 __path = String::format(__T("(fd: %d)"), _handle);
341#endif
342
343 __handle = _handle;
344 __closeOnClose = _closeOnClose;
345}
DCLCAPI int __ttyname(int fd, String &_r)
Definition _unistd.cpp:57
#define __T(str)
Definition Object.h:44
String className() const
Definition Object.cpp:163

◆ openTempFile()

File * File::openTempFile ( const String & _dirname,
const String & _prefix,
unsigned int _mode = 0666 )
static

Definition at line 721 of file File.cpp.

726{
727 File* r = NULL;
728
729 StringBuilder sbTemplate;
730 if (!_dirname.isEmpty()) {
731 sbTemplate = _dirname;
732 if (!_dirname.endsWith(L"/")) {
733 sbTemplate += L"/";
734 }
735 }
736
737 if (!_prefix.isEmpty()) {
738 sbTemplate += _prefix;
739 }
740 else {
741 sbTemplate += L"dcl";
742 }
743
744 sbTemplate += L"XXXXXX";
745
746#if __DCL_WINDOWS
747 if (::_wmktemp((wchar_t*)sbTemplate.data())) {
748 r = new File(sbTemplate, READWRITE | CREATE | EXCLUSIVE, _mode);
749 }
750 else {
751 throw new IOException(sbTemplate, EINVAL);
752 }
753#else
754 ByteString bsbTemplate = UTF8Encoder::encode(sbTemplate.toString());
755 int handle = ::mkstemp((char*)bsbTemplate.data());
756 if (handle == -1) {
757 throw new IOException(sbTemplate, errno);
758 }
759
760 struct stat st;
761 if (::fstat(handle, &st)) {
762 throw new IOException(sbTemplate, errno);
763 }
764
765 if (st.st_mode != _mode) {
766 if (::fchmod(handle, _mode)) {
767 throw new IOException(sbTemplate, errno);
768 }
769 }
770
771 r = new File(handle, UTF8Decoder::decode(bsbTemplate));
772#endif
773 return r;
774}
ByteString r
File()
Definition File.cpp:59

◆ path()

const String & File::path ( ) const
inline

열려진 파일의 경로를 리턴한다.

Definition at line 247 of file File.h.

247{ return __path; }

◆ read()

size_t File::read ( void * _buf,
size_t _n )
virtual

파일을 읽는다. 오픈 플래그에 NONBLOCK이 사용되면 0을 리턴할 수 있다. UNIX는 O_NONBLOCK이, Windows는 FILE_FLAG_OVERLAPPED가 사용된다. UNIX에서 리턴값이 0이면 errno가 EAGAIN 일 수 있다.

Parameters
_buf버퍼
_n버퍼의 크기, 버퍼의 바이트 수
Returns
읽혀진 바이트의 수이다. 0이면 EOF를 의미한다.

Definition at line 476 of file File.cpp.

478{
480 __DCL_ASSERT_PARAM(_buf != NULL);
481
482#if __DCL_WINDOWS
483 DWORD n = 0;
484 if (__readEvent) {
485 // NONBLOCK, Overrapped Read
486 OVERLAPPED ov;
487 ZeroMemory(&ov, sizeof(ov)); // cf. memset(&ov, 0, sizeof(ov));
488 ov.hEvent = __readEvent;
489 if (ReadFile(__handle, _buf, (DWORD)_n, &n, &ov)) {
490 // GetOverlappedResult가 성공하면 이벤트는 Set 된다.
491 SetEvent(ov.hEvent);
492
493 // 다른 스레드에서 WriteFile을 호출했을 경우 n == 0일 수 있다.
494 return n;
495 }
496 if (GetLastError() == ERROR_IO_PENDING) {
497 // 읽기가 진행중이다. 마칠때까지 기다린 후 결과를 확인한다.
498 switch (WaitForSingleObject(ov.hEvent, INFINITE)) {
499 case WAIT_OBJECT_0:
500 if (GetOverlappedResult(__handle, &ov, &n, FALSE))
501 return n;
502 break;
503 case WAIT_TIMEOUT: // 이것은 결코 도달하지 않는다. INFINITE
504 CancelIo(__handle);
505 SetLastError(ERROR_TIMEOUT);
506 break;
507 default:
508 __DCL_ASSERT(false);
509 }
510 }
511 // ERROR!
512 throw new IOException(__path, GetLastError());
513 }
514 else {
515 // __readEvent == NULL, Blocked Read
516 if (!ReadFile(__handle, _buf, (DWORD)_n, &n, NULL))
517 throw new IOException(__path, GetLastError());
518 }
519 return n;
520#else
521 ssize_t n = 0;
522 while ((n = ::read(__handle, _buf, _n)) == -1) {
523 // errno가 EAGAIN or EWOULDBLOCK인 경우
524 // fd가 O_NONBLOCK으로 열렸고, 읽기가 차단되었다.
525 // EAGAIN이면 0바이트를 읽었고, 읽기를 다시 시도한다.
526 // 그 외에는 오류이다.
527 if (!(errno == EAGAIN || errno == EWOULDBLOCK)) {
528 throw new IOException(__path, errno);
529 }
530 }
531 return n;
532#endif
533}
#define __DCL_ASSERT_PARAM(expr)
Definition Object.h:384
#define INFINITE
Definition Thread.h:17
virtual size_t read(void *_buf, size_t _n) __DCL_THROWS1(IOException *)
Definition File.cpp:476

◆ seek()

File::off_t File::seek ( off_t _offset,
int _whence )

파일의 읽기/쓰기 변위(offset)를 재설정한다.

Parameters
_offset변위
_whenceBEGIN, CURRENT, END
Returns
파일의 시작을 기준으로 새로운 변위를 리턴한다.

Definition at line 590 of file File.cpp.

592{
594
595#if __DCL_WINDOWS
596 DWORD dwMoveMethod = FILE_BEGIN;
597 switch (_whence) {
598 case BEGIN:
599 dwMoveMethod = FILE_BEGIN;
600 break;
601 case CURRENT:
602 dwMoveMethod = FILE_CURRENT;
603 break;
604 case END:
605 dwMoveMethod = FILE_END;
606 break;
607 default:
608 __DCL_ASSERT(false);
609 }
610 LARGE_INTEGER distanceToMove;
611 LARGE_INTEGER newFilePointer;
612 distanceToMove.QuadPart = _offset;
613 if (!SetFilePointerEx(__handle, distanceToMove, &newFilePointer, dwMoveMethod))
614 throw new IOException(__path, GetLastError());
615 return newFilePointer.QuadPart;
616#else
617 int whence = 0;
618 switch (_whence) {
619 case BEGIN :
620 whence = SEEK_SET;
621 break;
622 case CURRENT :
623 whence = SEEK_CUR;
624 break;
625 case END :
626 whence = SEEK_END;
627 break;
628 default :
629 __DCL_ASSERT(false);
630 }
631
632 off_t r = lseek(__handle, _offset, whence);
633 if (r == (off_t)-1)
634 throw (new IOException(__path, errno));
635 return r;
636#endif
637}

◆ size()

File::off_t File::size ( ) const

파일의 크기를 구한다.

Definition at line 639 of file File.cpp.

641{
643
644#if __DCL_WINDOWS
645 LARGE_INTEGER fileSize;
646 if (!GetFileSizeEx(__handle, &fileSize))
647 throw new IOException(__path, GetLastError());
648 return fileSize.QuadPart;
649#else
650 struct stat st;
651 int r = fstat(__handle, &st);
652 if (r == -1)
653 throw (new IOException(__path, errno));
654
655 return st.st_size;
656#endif
657}

◆ sync()

void File::sync ( )
virtual

장치와 동기화 한다. UNIX fsync, Windows FlushFileBuffers

Definition at line 347 of file File.cpp.

349{
351
352#if __DCL_WINDOWS
353 if (!FlushFileBuffers(__handle))
354 // 콘솔과 같이 버러링을 하지 않는 장치
355 throw new IOException(__path, GetLastError());
356#else
357 if (fsync(__handle) == -1)
358 // EINVAL, EBADF, EROFS, EIO
359 throw new IOException(__path, errno);
360#endif
361}

◆ time()

bool File::time ( time_t * _atime,
time_t * _mtime,
time_t * _ctime ) const

Definition at line 673 of file File.cpp.

674{
676
677#if __DCL_WINDOWS
678 FILETIME atime;
679 FILETIME mtime;
680 FILETIME ctime;
681 if (!GetFileTime(__handle, &atime, &mtime, &ctime)) {
682 return false;
683 }
684
685 ULARGE_INTEGER n;
686 if (_atime) {
687 n.HighPart = atime.dwHighDateTime;
688 n.LowPart = atime.dwLowDateTime;
689 *_atime = n.QuadPart;
690 }
691 if (_mtime) {
692 n.HighPart = mtime.dwHighDateTime;
693 n.LowPart = mtime.dwLowDateTime;
694 *_mtime = n.QuadPart;
695 }
696 if (_ctime) {
697 n.HighPart = ctime.dwHighDateTime;
698 n.LowPart = ctime.dwLowDateTime;
699 *_ctime = n.QuadPart;
700 }
701#else
702 struct stat sb;
703 int r = fstat(__handle, &sb);
704 if (r == -1) {
705 return false;
706 }
707 if (_atime) {
708 *_atime = sb.st_atime;
709 }
710 if (_mtime) {
711 *_mtime = sb.st_mtime;
712 }
713 if (_ctime) {
714 *_ctime = sb.st_ctime;
715 }
716#endif
717 return true;
718}

◆ toString()

virtual String File::toString ( ) const
virtual

Reimplemented from Object.

◆ write()

size_t File::write ( const void * _buf,
size_t _n )
virtual

파일에 데이터를 쓴다. 오픈 플래그에 NONBLOCK이 사용되면 오류 없이 0을 리턴할 수 있다. UNIX는 O_NONBLOCK이, Windows는 FILE_FLAG_OVERLAPPED가 사용된다. UNIX에서 리턴값이 0이면 errno가 EAGAIN 일 수 있다. 0을 리턴하는 것은 read, write를 호출한 스레드가 서로 달라서, 서로 겹쳐지기 때문으로 볼 수 있다. 0을 리턴하면 write하지 않았기 때문에 다시 시도해야 한다.

Parameters
_buf버퍼
_n버퍼의 크기, 버퍼의 바이트 수
Returns
쓰여진 바이트의 수이다. 0이면 다시 시도하라.

Definition at line 535 of file File.cpp.

537{
539 __DCL_ASSERT_PARAM(_buf != NULL);
540
541#if __DCL_WINDOWS
542 DWORD n = 0;
543 if (__writeEvent) {
544 // NONBLOCK, Overrapped Write
545 OVERLAPPED ov;
546 ZeroMemory(&ov, sizeof(ov)); // cf. memset(&ov, 0, sizeof(ov));
547 ov.hEvent = __writeEvent;
548 if (WriteFile(__handle, _buf, (DWORD)_n, &n, &ov)) {
549 // GetOverlappedResult가 성공하면 이벤트는 Set 된다.
550 SetEvent(ov.hEvent);
551 // 다른 스레드에서 ReadFile을 호출했을 경우 n == 0일 수 있다.
552 return n;
553 }
554 if (GetLastError() == ERROR_IO_PENDING) {
555 // 쓰기가 진행중이다. 마칠때까지 기다린 후 결과를 확인한다.
556 switch (WaitForSingleObject(ov.hEvent, INFINITE)) {
557 case WAIT_OBJECT_0:
558 if (GetOverlappedResult(__handle, &ov, &n, FALSE))
559 return n;
560 break;
561 case WAIT_TIMEOUT: // 이것은 결코 도달하지 않는다. INFINITE
562 CancelIo(__handle);
563 SetLastError(ERROR_TIMEOUT);
564 default:
565 __DCL_ASSERT(false);
566 }
567 }
568 // ERROR!
569 throw new IOException(__path, GetLastError());
570 }
571 else {
572 // __writeEvent == NULL, Blocked Write
573 if (!WriteFile(__handle, _buf, (DWORD)_n, &n, NULL))
574 throw new IOException(__path, GetLastError());
575 }
576 return n;
577#else
578 ssize_t n = ::write(__handle, _buf, _n);
579 if (n == -1) {
580 // 파일이 nonblocking으로 표시되었고 오퍼레이션이 블록되었다.
581 if (errno == EAGAIN || errno == EWOULDBLOCK)
582 return 0;
583 else
584 throw new IOException(__path, errno);
585 }
586 return n;
587#endif
588}
virtual size_t write(const void *_buf, size_t _n) __DCL_THROWS1(IOException *)
Definition File.cpp:535

Member Data Documentation

◆ __closeOnClose

bool File::__closeOnClose
protected

Definition at line 252 of file File.h.

◆ __handle

HandleType File::__handle
protected

Definition at line 251 of file File.h.

◆ __path

String File::__path
protected

Definition at line 250 of file File.h.


The documentation for this class was generated from the following files: