File.cs 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497
  1. //
  2. // System.IO.FIle.cs
  3. //
  4. //
  5. // Authors:
  6. // Miguel de Icaza ([email protected])
  7. // Jim Richardson ([email protected])
  8. // Dan Lewis ([email protected])
  9. // Ville Palo ([email protected])
  10. //
  11. // Copyright 2002 Ximian, Inc. http://www.ximian.com
  12. // Copyright (C) 2001 Moonlight Enterprises, All Rights Reserved
  13. //
  14. //
  15. // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
  16. //
  17. // Permission is hereby granted, free of charge, to any person obtaining
  18. // a copy of this software and associated documentation files (the
  19. // "Software"), to deal in the Software without restriction, including
  20. // without limitation the rights to use, copy, modify, merge, publish,
  21. // distribute, sublicense, and/or sell copies of the Software, and to
  22. // permit persons to whom the Software is furnished to do so, subject to
  23. // the following conditions:
  24. //
  25. // The above copyright notice and this permission notice shall be
  26. // included in all copies or substantial portions of the Software.
  27. //
  28. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  29. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  30. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  31. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  32. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  33. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  34. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  35. //
  36. using System;
  37. using System.Text;
  38. namespace System.IO
  39. {
  40. /// <summary>
  41. ///
  42. /// </summary>
  43. public
  44. #if NET_2_0
  45. static
  46. #else
  47. sealed
  48. #endif
  49. class File
  50. {
  51. #if !NET_2_0
  52. private File () {}
  53. #endif
  54. public static StreamWriter AppendText (string path)
  55. {
  56. return new StreamWriter (path, true);
  57. }
  58. [MonoTODO("Security Permision Checks")]
  59. public static void Copy (string sourceFilename, string destFilename)
  60. {
  61. Copy (sourceFilename, destFilename, false);
  62. }
  63. public static void Copy (string src, string dest, bool overwrite)
  64. {
  65. if (src == null)
  66. throw new ArgumentNullException ("src");
  67. if (dest == null)
  68. throw new ArgumentNullException ("dest");
  69. if (src.Trim () == "" || src.IndexOfAny (Path.InvalidPathChars) != -1)
  70. throw new ArgumentException (Locale.GetText ("src is null"));
  71. if (dest.Trim () == "" || dest.IndexOfAny (Path.InvalidPathChars) != -1)
  72. throw new ArgumentException (Locale.GetText ("dest is empty or contains invalid characters"));
  73. if (!Exists (src))
  74. throw new FileNotFoundException (Locale.GetText ("{0} does not exist", src), src);
  75. if ((GetAttributes(src) & FileAttributes.Directory) == FileAttributes.Directory){
  76. throw new ArgumentException(Locale.GetText ("{0} is a directory", src));
  77. }
  78. if (Exists (dest)) {
  79. if ((GetAttributes(dest) & FileAttributes.Directory) == FileAttributes.Directory){
  80. throw new ArgumentException (Locale.GetText ("{0} is a directory", dest));
  81. }
  82. if (!overwrite)
  83. throw new IOException (Locale.GetText ("{0} already exists", dest));
  84. }
  85. string DirName = Path.GetDirectoryName(dest);
  86. if (DirName != String.Empty && !Directory.Exists (DirName))
  87. throw new DirectoryNotFoundException (Locale.GetText ("Destination directory not found: {0}",DirName));
  88. MonoIOError error;
  89. if (!MonoIO.CopyFile (src, dest, overwrite, out error)){
  90. string p = Locale.GetText ("{0}\" or \"{1}", src, dest);
  91. throw MonoIO.GetException (p, error);
  92. }
  93. }
  94. public static FileStream Create (string path)
  95. {
  96. return Create (path, 8192);
  97. }
  98. public static FileStream Create (string path, int buffersize)
  99. {
  100. if (null == path)
  101. throw new ArgumentNullException ("path");
  102. if (String.Empty == path.Trim() || path.IndexOfAny(Path.InvalidPathChars) >= 0)
  103. throw new ArgumentException (Locale.GetText ("path is invalid"));
  104. string DirName = Path.GetDirectoryName(path);
  105. if (DirName != String.Empty && !Directory.Exists (DirName))
  106. throw new DirectoryNotFoundException (Locale.GetText ("Destination directory not found: {0}", DirName));
  107. if (Exists(path)){
  108. if ((GetAttributes(path) & FileAttributes.ReadOnly) == FileAttributes.ReadOnly){
  109. throw new UnauthorizedAccessException (Locale.GetText ("{0} is read-only", path));
  110. }
  111. }
  112. return new FileStream (path, FileMode.Create, FileAccess.ReadWrite,
  113. FileShare.None, buffersize);
  114. }
  115. public static StreamWriter CreateText(string path)
  116. {
  117. return new StreamWriter (path, false);
  118. }
  119. public static void Delete (string path)
  120. {
  121. if (null == path)
  122. throw new ArgumentNullException("path");
  123. if (String.Empty == path.Trim() || path.IndexOfAny(Path.InvalidPathChars) >= 0)
  124. throw new ArgumentException("path");
  125. if (Directory.Exists (path))
  126. throw new UnauthorizedAccessException(Locale.GetText ("{0} is a directory", path));
  127. string DirName = Path.GetDirectoryName(path);
  128. if (DirName != String.Empty && !Directory.Exists (DirName))
  129. throw new DirectoryNotFoundException (Locale.GetText ("Destination directory not found: {0}", DirName));
  130. MonoIOError error;
  131. if (!MonoIO.DeleteFile (path, out error)){
  132. Exception e = MonoIO.GetException (path, error);
  133. if (! (e is FileNotFoundException))
  134. throw e;
  135. }
  136. }
  137. public static bool Exists (string path)
  138. {
  139. // For security reasons no exceptions are
  140. // thrown, only false is returned if there is
  141. // any problem with the path or permissions.
  142. // Minimizes what information can be
  143. // discovered by using this method.
  144. if (null == path || String.Empty == path.Trim()
  145. || path.IndexOfAny(Path.InvalidPathChars) >= 0) {
  146. return false;
  147. }
  148. MonoIOError error;
  149. bool exists;
  150. exists = MonoIO.ExistsFile (path, out error);
  151. if (error != MonoIOError.ERROR_SUCCESS &&
  152. error != MonoIOError.ERROR_FILE_NOT_FOUND &&
  153. error != MonoIOError.ERROR_PATH_NOT_FOUND &&
  154. error != MonoIOError.ERROR_INVALID_NAME) {
  155. throw MonoIO.GetException (path, error);
  156. }
  157. return(exists);
  158. }
  159. public static FileAttributes GetAttributes (string path)
  160. {
  161. if (null == path) {
  162. throw new ArgumentNullException("path");
  163. }
  164. if (String.Empty == path.Trim()) {
  165. throw new ArgumentException (Locale.GetText ("Path is empty"));
  166. }
  167. if (path.IndexOfAny(Path.InvalidPathChars) >= 0) {
  168. throw new ArgumentException(Locale.GetText ("Path contains invalid chars"));
  169. }
  170. MonoIOError error;
  171. FileAttributes attrs;
  172. attrs = MonoIO.GetFileAttributes (path, out error);
  173. if (error != MonoIOError.ERROR_SUCCESS) {
  174. throw MonoIO.GetException (path, error);
  175. }
  176. return(attrs);
  177. }
  178. public static DateTime GetCreationTime (string path)
  179. {
  180. MonoIOStat stat;
  181. MonoIOError error;
  182. CheckPathExceptions (path);
  183. if (!MonoIO.GetFileStat (path, out stat, out error)) {
  184. #if NET_2_0
  185. if (error == MonoIOError.ERROR_PATH_NOT_FOUND || error == MonoIOError.ERROR_FILE_NOT_FOUND)
  186. return _defaultLocalFileTime;
  187. else
  188. throw new IOException (path);
  189. #else
  190. throw new IOException (path);
  191. #endif
  192. }
  193. return DateTime.FromFileTime (stat.CreationTime);
  194. }
  195. public static DateTime GetCreationTimeUtc (string path)
  196. {
  197. return GetCreationTime (path).ToUniversalTime ();
  198. }
  199. public static DateTime GetLastAccessTime (string path)
  200. {
  201. MonoIOStat stat;
  202. MonoIOError error;
  203. CheckPathExceptions (path);
  204. if (!MonoIO.GetFileStat (path, out stat, out error)) {
  205. #if NET_2_0
  206. if (error == MonoIOError.ERROR_PATH_NOT_FOUND || error == MonoIOError.ERROR_FILE_NOT_FOUND)
  207. return _defaultLocalFileTime;
  208. else
  209. throw new IOException (path);
  210. #else
  211. throw new IOException (path);
  212. #endif
  213. }
  214. return DateTime.FromFileTime (stat.LastAccessTime);
  215. }
  216. public static DateTime GetLastAccessTimeUtc (string path)
  217. {
  218. return GetLastAccessTime (path).ToUniversalTime ();
  219. }
  220. public static DateTime GetLastWriteTime (string path)
  221. {
  222. MonoIOStat stat;
  223. MonoIOError error;
  224. CheckPathExceptions (path);
  225. if (!MonoIO.GetFileStat (path, out stat, out error)) {
  226. #if NET_2_0
  227. if (error == MonoIOError.ERROR_PATH_NOT_FOUND || error == MonoIOError.ERROR_FILE_NOT_FOUND)
  228. return _defaultLocalFileTime;
  229. else
  230. throw new IOException (path);
  231. #else
  232. throw new IOException (path);
  233. #endif
  234. }
  235. return DateTime.FromFileTime (stat.LastWriteTime);
  236. }
  237. public static DateTime GetLastWriteTimeUtc (string path)
  238. {
  239. return GetLastWriteTime (path).ToUniversalTime ();
  240. }
  241. public static void Move (string src, string dest)
  242. {
  243. MonoIOError error;
  244. if (src == null)
  245. throw new ArgumentNullException ("src");
  246. if (dest == null)
  247. throw new ArgumentNullException ("dest");
  248. if (src.Trim () == "" || src.IndexOfAny (Path.InvalidPathChars) != -1)
  249. throw new ArgumentException ("src");
  250. if (dest.Trim () == "" || dest.IndexOfAny (Path.InvalidPathChars) != -1)
  251. throw new ArgumentException ("dest");
  252. if (!MonoIO.Exists (src, out error))
  253. throw new FileNotFoundException (Locale.GetText ("{0} does not exist", src), src);
  254. if (MonoIO.ExistsDirectory (dest, out error))
  255. throw new IOException (Locale.GetText ("{0} is a directory", dest));
  256. // Don't check for this error here to allow the runtime to check if src and dest
  257. // are equal. Comparing src and dest is not enough.
  258. //if (MonoIO.Exists (dest, out error))
  259. // throw new IOException (Locale.GetText ("{0} already exists", dest));
  260. string DirName;
  261. DirName = Path.GetDirectoryName(src);
  262. if (DirName != String.Empty && !Directory.Exists (DirName))
  263. throw new DirectoryNotFoundException(Locale.GetText ("Source directory not found: {0}", DirName));
  264. DirName = Path.GetDirectoryName(dest);
  265. if (DirName != String.Empty && !Directory.Exists (DirName))
  266. throw new DirectoryNotFoundException(Locale.GetText ("Destination directory not found: {0}", DirName));
  267. if (!MonoIO.MoveFile (src, dest, out error)) {
  268. if (error == MonoIOError.ERROR_ALREADY_EXISTS)
  269. throw MonoIO.GetException (dest, error);
  270. throw MonoIO.GetException (error);
  271. }
  272. }
  273. public static FileStream Open (string path, FileMode mode)
  274. {
  275. return new FileStream (path, mode, mode == FileMode.Append ? FileAccess.Write : FileAccess.ReadWrite, FileShare.None);
  276. }
  277. public static FileStream Open (string path, FileMode mode, FileAccess access)
  278. {
  279. return new FileStream (path, mode, access, FileShare.None);
  280. }
  281. public static FileStream Open (string path, FileMode mode, FileAccess access,
  282. FileShare share)
  283. {
  284. return new FileStream (path, mode, access, share);
  285. }
  286. public static FileStream OpenRead (string path)
  287. {
  288. return new FileStream (path, FileMode.Open, FileAccess.Read, FileShare.Read);
  289. }
  290. public static StreamReader OpenText (string path)
  291. {
  292. return new StreamReader (path);
  293. }
  294. public static FileStream OpenWrite (string path)
  295. {
  296. return new FileStream(path, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None);
  297. }
  298. public static void SetAttributes (string path,
  299. FileAttributes attributes)
  300. {
  301. MonoIOError error;
  302. CheckPathExceptions (path);
  303. if (!MonoIO.SetFileAttributes (path, attributes,
  304. out error)) {
  305. throw MonoIO.GetException (path, error);
  306. }
  307. }
  308. public static void SetCreationTime (string path,
  309. DateTime creation_time)
  310. {
  311. MonoIOError error;
  312. CheckPathExceptions (path);
  313. if (!MonoIO.Exists (path, out error))
  314. throw MonoIO.GetException (path, error);
  315. if (!MonoIO.SetCreationTime (path, creation_time, out error)) {
  316. throw MonoIO.GetException (path, error);
  317. }
  318. }
  319. public static void SetCreationTimeUtc (string path,
  320. DateTime creation_time)
  321. {
  322. SetCreationTime (path, creation_time.ToLocalTime ());
  323. }
  324. public static void SetLastAccessTime (string path,DateTime last_access_time)
  325. {
  326. MonoIOError error;
  327. CheckPathExceptions (path);
  328. if (!MonoIO.Exists (path, out error))
  329. throw MonoIO.GetException (path, error);
  330. if (!MonoIO.SetLastAccessTime (path, last_access_time, out error)) {
  331. throw MonoIO.GetException (path, error);
  332. }
  333. }
  334. public static void SetLastAccessTimeUtc (string path,DateTime last_access_time)
  335. {
  336. SetLastAccessTime (path, last_access_time.ToLocalTime ());
  337. }
  338. public static void SetLastWriteTime (string path,
  339. DateTime last_write_time)
  340. {
  341. MonoIOError error;
  342. CheckPathExceptions (path);
  343. if (!MonoIO.Exists (path, out error))
  344. throw MonoIO.GetException (path, error);
  345. if (!MonoIO.SetLastWriteTime (path, last_write_time, out error)) {
  346. throw MonoIO.GetException (path, error);
  347. }
  348. }
  349. public static void SetLastWriteTimeUtc (string path,
  350. DateTime last_write_time)
  351. {
  352. SetLastWriteTime (path, last_write_time.ToLocalTime ());
  353. }
  354. #region Private
  355. private static void CheckPathExceptions (string path)
  356. {
  357. if (path == null)
  358. throw new System.ArgumentNullException("path");
  359. if (path == "")
  360. throw new System.ArgumentException(Locale.GetText ("Path is empty"));
  361. if (path.Trim().Length == 0)
  362. throw new ArgumentException (Locale.GetText ("Path is empty"));
  363. if (path.IndexOfAny (Path.InvalidPathChars) != -1)
  364. throw new ArgumentException (Locale.GetText ("Path contains invalid chars"));
  365. }
  366. #endregion
  367. #if NET_2_0
  368. static File() {
  369. _defaultLocalFileTime = new DateTime (1601, 1, 1);
  370. _defaultLocalFileTime = _defaultLocalFileTime.ToLocalTime ();
  371. }
  372. //
  373. // The documentation for this method is most likely wrong, it
  374. // talks about doing a "binary read", but the remarks say
  375. // that this "detects the encoding".
  376. //
  377. // This can not detect and do anything useful with the encoding
  378. // since the result is a byte [] not a char [].
  379. //
  380. public static byte [] ReadAllBytes (string path)
  381. {
  382. using (FileStream s = Open (path, FileMode.Open, FileAccess.Read, FileShare.Read)){
  383. long size = s.Length;
  384. //
  385. // Is this worth supporting?
  386. //
  387. if (size > Int32.MaxValue)
  388. throw new ArgumentException ("Reading more than 4gigs with this call is not supported");
  389. byte [] result = new byte [s.Length];
  390. s.Read (result, 0, (int) size);
  391. return result;
  392. }
  393. }
  394. public static string ReadAllText (string path)
  395. {
  396. return ReadAllText (path, Encoding.UTF8Unmarked);
  397. }
  398. public static string ReadAllText (string path, Encoding enc)
  399. {
  400. using (StreamReader sr = new StreamReader (path, enc)) {
  401. return sr.ReadToEnd ();
  402. }
  403. }
  404. public static void WriteAllText (string path, string contents)
  405. {
  406. WriteAllText (path, contents, Encoding.UTF8Unmarked);
  407. }
  408. public static void WriteAllText (string path, string contents, Encoding enc)
  409. {
  410. using (StreamWriter sw = new StreamWriter (path, false, enc)) {
  411. sw.Write (contents);
  412. }
  413. }
  414. private static readonly DateTime _defaultLocalFileTime;
  415. #endif
  416. }
  417. }