filetxt.cpp 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335
  1. // This is a part of the Microsoft Foundation Classes C++ library.
  2. // Copyright (C) 1992-1998 Microsoft Corporation
  3. // All rights reserved.
  4. //
  5. // This source code is only intended as a supplement to the
  6. // Microsoft Foundation Classes Reference and related
  7. // electronic documentation provided with the library.
  8. // See these sources for detailed information regarding the
  9. // Microsoft Foundation Classes product.
  10. #include "stdafx.h"
  11. #include <errno.h>
  12. #include <io.h>
  13. #include <fcntl.h>
  14. #ifdef AFX_CORE1_SEG
  15. #pragma code_seg(AFX_CORE1_SEG)
  16. #endif
  17. #ifdef _DEBUG
  18. #undef THIS_FILE
  19. static char THIS_FILE[] = __FILE__;
  20. #endif
  21. #define new DEBUG_NEW
  22. ////////////////////////////////////////////////////////////////////////////
  23. // CStdioFile implementation
  24. CStdioFile::CStdioFile()
  25. {
  26. m_pStream = NULL;
  27. }
  28. CStdioFile::CStdioFile(FILE* pOpenStream) : CFile(hFileNull)
  29. {
  30. m_pStream = pOpenStream;
  31. m_hFile = (UINT)_get_osfhandle(_fileno(pOpenStream));
  32. ASSERT(!m_bCloseOnDelete);
  33. }
  34. CStdioFile::CStdioFile(LPCTSTR lpszFileName, UINT nOpenFlags)
  35. {
  36. ASSERT(lpszFileName != NULL);
  37. ASSERT(AfxIsValidString(lpszFileName));
  38. CFileException e;
  39. if (!Open(lpszFileName, nOpenFlags, &e))
  40. AfxThrowFileException(e.m_cause, e.m_lOsError, e.m_strFileName);
  41. }
  42. CStdioFile::~CStdioFile()
  43. {
  44. ASSERT_VALID(this);
  45. if (m_pStream != NULL && m_bCloseOnDelete)
  46. Close();
  47. }
  48. BOOL CStdioFile::Open(LPCTSTR lpszFileName, UINT nOpenFlags,
  49. CFileException* pException)
  50. {
  51. ASSERT(pException == NULL || AfxIsValidAddress(pException, sizeof(CFileException)));
  52. ASSERT(lpszFileName != NULL);
  53. ASSERT(AfxIsValidString(lpszFileName));
  54. m_pStream = NULL;
  55. if (!CFile::Open(lpszFileName, (nOpenFlags & ~typeText), pException))
  56. return FALSE;
  57. ASSERT(m_hFile != hFileNull);
  58. ASSERT(m_bCloseOnDelete);
  59. char szMode[4]; // C-runtime open string
  60. int nMode = 0;
  61. // determine read/write mode depending on CFile mode
  62. if (nOpenFlags & modeCreate)
  63. {
  64. if (nOpenFlags & modeNoTruncate)
  65. szMode[nMode++] = 'a';
  66. else
  67. szMode[nMode++] = 'w';
  68. }
  69. else if (nOpenFlags & modeWrite)
  70. szMode[nMode++] = 'a';
  71. else
  72. szMode[nMode++] = 'r';
  73. // add '+' if necessary (when read/write modes mismatched)
  74. if (szMode[0] == 'r' && (nOpenFlags & modeReadWrite) ||
  75. szMode[0] != 'r' && !(nOpenFlags & modeWrite))
  76. {
  77. // current szMode mismatched, need to add '+' to fix
  78. szMode[nMode++] = '+';
  79. }
  80. // will be inverted if not necessary
  81. int nFlags = _O_RDONLY|_O_TEXT;
  82. if (nOpenFlags & (modeWrite|modeReadWrite))
  83. nFlags ^= _O_RDONLY;
  84. if (nOpenFlags & typeBinary)
  85. szMode[nMode++] = 'b', nFlags ^= _O_TEXT;
  86. else
  87. szMode[nMode++] = 't';
  88. szMode[nMode++] = '\0';
  89. // open a C-runtime low-level file handle
  90. int nHandle = _open_osfhandle(m_hFile, nFlags);
  91. // open a C-runtime stream from that handle
  92. if (nHandle != -1)
  93. m_pStream = _fdopen(nHandle, szMode);
  94. if (m_pStream == NULL)
  95. {
  96. // an error somewhere along the way...
  97. if (pException != NULL)
  98. {
  99. pException->m_lOsError = _doserrno;
  100. pException->m_cause = CFileException::OsErrorToException(_doserrno);
  101. }
  102. CFile::Abort(); // close m_hFile
  103. return FALSE;
  104. }
  105. return TRUE;
  106. }
  107. UINT CStdioFile::Read(void* lpBuf, UINT nCount)
  108. {
  109. ASSERT_VALID(this);
  110. ASSERT(m_pStream != NULL);
  111. if (nCount == 0)
  112. return 0; // avoid Win32 "null-read"
  113. ASSERT(AfxIsValidAddress(lpBuf, nCount));
  114. UINT nRead = 0;
  115. if ((nRead = fread(lpBuf, sizeof(BYTE), nCount, m_pStream)) == 0 && !feof(m_pStream))
  116. AfxThrowFileException(CFileException::generic, _doserrno, m_strFileName);
  117. if (ferror(m_pStream))
  118. {
  119. clearerr(m_pStream);
  120. AfxThrowFileException(CFileException::generic, _doserrno, m_strFileName);
  121. }
  122. return nRead;
  123. }
  124. void CStdioFile::Write(const void* lpBuf, UINT nCount)
  125. {
  126. ASSERT_VALID(this);
  127. ASSERT(m_pStream != NULL);
  128. ASSERT(AfxIsValidAddress(lpBuf, nCount, FALSE));
  129. if (fwrite(lpBuf, sizeof(BYTE), nCount, m_pStream) != nCount)
  130. AfxThrowFileException(CFileException::generic, _doserrno, m_strFileName);
  131. }
  132. void CStdioFile::WriteString(LPCTSTR lpsz)
  133. {
  134. ASSERT(lpsz != NULL);
  135. ASSERT(m_pStream != NULL);
  136. if (_fputts(lpsz, m_pStream) == _TEOF)
  137. AfxThrowFileException(CFileException::diskFull, _doserrno, m_strFileName);
  138. }
  139. LPTSTR CStdioFile::ReadString(LPTSTR lpsz, UINT nMax)
  140. {
  141. ASSERT(lpsz != NULL);
  142. ASSERT(AfxIsValidAddress(lpsz, nMax));
  143. ASSERT(m_pStream != NULL);
  144. LPTSTR lpszResult = _fgetts(lpsz, nMax, m_pStream);
  145. if (lpszResult == NULL && !feof(m_pStream))
  146. {
  147. clearerr(m_pStream);
  148. AfxThrowFileException(CFileException::generic, _doserrno, m_strFileName);
  149. }
  150. return lpszResult;
  151. }
  152. BOOL CStdioFile::ReadString(CString& rString)
  153. {
  154. ASSERT_VALID(this);
  155. rString = &afxChNil; // empty string without deallocating
  156. const int nMaxSize = 128;
  157. LPTSTR lpsz = rString.GetBuffer(nMaxSize);
  158. LPTSTR lpszResult;
  159. int nLen = 0;
  160. for (;;)
  161. {
  162. lpszResult = _fgetts(lpsz, nMaxSize+1, m_pStream);
  163. rString.ReleaseBuffer();
  164. // handle error/eof case
  165. if (lpszResult == NULL && !feof(m_pStream))
  166. {
  167. clearerr(m_pStream);
  168. AfxThrowFileException(CFileException::generic, _doserrno,
  169. m_strFileName);
  170. }
  171. // if string is read completely or EOF
  172. if (lpszResult == NULL ||
  173. (nLen = lstrlen(lpsz)) < nMaxSize ||
  174. lpsz[nLen-1] == '\n')
  175. break;
  176. nLen = rString.GetLength();
  177. lpsz = rString.GetBuffer(nMaxSize + nLen) + nLen;
  178. }
  179. // remove '\n' from end of string if present
  180. lpsz = rString.GetBuffer(0);
  181. nLen = rString.GetLength();
  182. if (nLen != 0 && lpsz[nLen-1] == '\n')
  183. rString.GetBufferSetLength(nLen-1);
  184. return lpszResult != NULL;
  185. }
  186. LONG CStdioFile::Seek(LONG lOff, UINT nFrom)
  187. {
  188. ASSERT_VALID(this);
  189. ASSERT(nFrom == begin || nFrom == end || nFrom == current);
  190. ASSERT(m_pStream != NULL);
  191. if (fseek(m_pStream, lOff, nFrom) != 0)
  192. AfxThrowFileException(CFileException::badSeek, _doserrno,
  193. m_strFileName);
  194. long pos = ftell(m_pStream);
  195. return pos;
  196. }
  197. DWORD CStdioFile::GetPosition() const
  198. {
  199. ASSERT_VALID(this);
  200. ASSERT(m_pStream != NULL);
  201. long pos = ftell(m_pStream);
  202. if (pos == -1)
  203. AfxThrowFileException(CFileException::invalidFile, _doserrno,
  204. m_strFileName);
  205. return pos;
  206. }
  207. void CStdioFile::Flush()
  208. {
  209. ASSERT_VALID(this);
  210. if (m_pStream != NULL && fflush(m_pStream) != 0)
  211. AfxThrowFileException(CFileException::diskFull, _doserrno,
  212. m_strFileName);
  213. }
  214. void CStdioFile::Close()
  215. {
  216. ASSERT_VALID(this);
  217. ASSERT(m_pStream != NULL);
  218. int nErr = 0;
  219. if (m_pStream != NULL)
  220. nErr = fclose(m_pStream);
  221. m_hFile = (UINT) hFileNull;
  222. m_bCloseOnDelete = FALSE;
  223. m_pStream = NULL;
  224. if (nErr != 0)
  225. AfxThrowFileException(CFileException::diskFull, _doserrno,
  226. m_strFileName);
  227. }
  228. void CStdioFile::Abort()
  229. {
  230. ASSERT_VALID(this);
  231. if (m_pStream != NULL && m_bCloseOnDelete)
  232. fclose(m_pStream); // close but ignore errors
  233. m_hFile = (UINT) hFileNull;
  234. m_pStream = NULL;
  235. m_bCloseOnDelete = FALSE;
  236. }
  237. CFile* CStdioFile::Duplicate() const
  238. {
  239. ASSERT_VALID(this);
  240. ASSERT(m_pStream != NULL);
  241. AfxThrowNotSupportedException();
  242. return NULL;
  243. }
  244. void CStdioFile::LockRange(DWORD /* dwPos */, DWORD /* dwCount */)
  245. {
  246. ASSERT_VALID(this);
  247. ASSERT(m_pStream != NULL);
  248. AfxThrowNotSupportedException();
  249. }
  250. void CStdioFile::UnlockRange(DWORD /* dwPos */, DWORD /* dwCount */)
  251. {
  252. ASSERT_VALID(this);
  253. ASSERT(m_pStream != NULL);
  254. AfxThrowNotSupportedException();
  255. }
  256. #ifdef _DEBUG
  257. void CStdioFile::Dump(CDumpContext& dc) const
  258. {
  259. CFile::Dump(dc);
  260. dc << "m_pStream = " << (void*)m_pStream;
  261. dc << "\n";
  262. }
  263. #endif
  264. #ifdef AFX_INIT_SEG
  265. #pragma code_seg(AFX_INIT_SEG)
  266. #endif
  267. IMPLEMENT_DYNAMIC(CStdioFile, CFile)
  268. /////////////////////////////////////////////////////////////////////////////