File.cs 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632
  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. // Copyright (C) 2004, 2006 Novell, Inc (http://www.novell.com)
  14. //
  15. // Permission is hereby granted, free of charge, to any person obtaining
  16. // a copy of this software and associated documentation files (the
  17. // "Software"), to deal in the Software without restriction, including
  18. // without limitation the rights to use, copy, modify, merge, publish,
  19. // distribute, sublicense, and/or sell copies of the Software, and to
  20. // permit persons to whom the Software is furnished to do so, subject to
  21. // the following conditions:
  22. //
  23. // The above copyright notice and this permission notice shall be
  24. // included in all copies or substantial portions of the Software.
  25. //
  26. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  27. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  28. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  29. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  30. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  31. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  32. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  33. //
  34. using System;
  35. using System.Text;
  36. #if NET_2_0
  37. using System.Collections.Generic;
  38. using System.Runtime.InteropServices;
  39. using System.Security.AccessControl;
  40. #endif
  41. namespace System.IO
  42. {
  43. /// <summary>
  44. ///
  45. /// </summary>
  46. #if NET_2_0
  47. [ComVisible (true)]
  48. #endif
  49. public
  50. #if NET_2_0
  51. static
  52. #else
  53. sealed
  54. #endif
  55. class File
  56. {
  57. #if !NET_2_0
  58. private File () {}
  59. #endif
  60. #if NET_2_0
  61. public static void AppendAllText (string path, string contents)
  62. {
  63. using (TextWriter w = new StreamWriter (path, true)) {
  64. w.Write (contents);
  65. }
  66. }
  67. public static void AppendAllText (string path, string contents, Encoding encoding)
  68. {
  69. using (TextWriter w = new StreamWriter (path, true, encoding)) {
  70. w.Write (contents);
  71. }
  72. }
  73. #endif
  74. public static StreamWriter AppendText (string path)
  75. {
  76. return new StreamWriter (path, true);
  77. }
  78. public static void Copy (string sourceFilename, string destFilename)
  79. {
  80. Copy (sourceFilename, destFilename, false);
  81. }
  82. public static void Copy (string src, string dest, bool overwrite)
  83. {
  84. if (src == null)
  85. throw new ArgumentNullException ("src");
  86. if (dest == null)
  87. throw new ArgumentNullException ("dest");
  88. if (src.Trim () == "" || src.IndexOfAny (Path.InvalidPathChars) != -1)
  89. throw new ArgumentException (Locale.GetText ("src is null"));
  90. if (dest.Trim () == "" || dest.IndexOfAny (Path.InvalidPathChars) != -1)
  91. throw new ArgumentException (Locale.GetText ("dest is empty or contains invalid characters"));
  92. if (!Exists (src))
  93. throw new FileNotFoundException (Locale.GetText ("{0} does not exist", src), src);
  94. if ((GetAttributes(src) & FileAttributes.Directory) == FileAttributes.Directory){
  95. throw new ArgumentException(Locale.GetText ("{0} is a directory", src));
  96. }
  97. if (Exists (dest)) {
  98. if ((GetAttributes(dest) & FileAttributes.Directory) == FileAttributes.Directory){
  99. throw new ArgumentException (Locale.GetText ("{0} is a directory", dest));
  100. }
  101. if (!overwrite)
  102. throw new IOException (Locale.GetText ("{0} already exists", dest));
  103. }
  104. string DirName = Path.GetDirectoryName(dest);
  105. if (DirName != String.Empty && !Directory.Exists (DirName))
  106. throw new DirectoryNotFoundException (Locale.GetText ("Destination directory not found: {0}",DirName));
  107. MonoIOError error;
  108. if (!MonoIO.CopyFile (src, dest, overwrite, out error)){
  109. string p = Locale.GetText ("{0}\" or \"{1}", src, dest);
  110. throw MonoIO.GetException (p, error);
  111. }
  112. }
  113. public static FileStream Create (string path)
  114. {
  115. return(Create (path, 8192, FileOptions.None, null));
  116. }
  117. public static FileStream Create (string path, int buffersize)
  118. {
  119. return(Create (path, buffersize, FileOptions.None,
  120. null));
  121. }
  122. #if NET_2_0
  123. [MonoTODO ("options not implemented")]
  124. public static FileStream Create (string path, int bufferSize,
  125. FileOptions options)
  126. {
  127. return(Create (path, bufferSize, options, null));
  128. }
  129. [MonoTODO ("options and fileSecurity not implemented")]
  130. public static FileStream Create (string path, int bufferSize,
  131. FileOptions options,
  132. FileSecurity fileSecurity)
  133. #else
  134. private static FileStream Create (string path, int bufferSize,
  135. FileOptions options,
  136. object fileSecurity)
  137. #endif
  138. {
  139. if (null == path)
  140. throw new ArgumentNullException ("path");
  141. if (String.Empty == path.Trim() || path.IndexOfAny(Path.InvalidPathChars) >= 0)
  142. throw new ArgumentException (Locale.GetText ("path is invalid"));
  143. string DirName = Path.GetDirectoryName(path);
  144. if (DirName != String.Empty && !Directory.Exists (DirName))
  145. throw new DirectoryNotFoundException (Locale.GetText ("Destination directory not found: {0}", DirName));
  146. if (Exists(path)){
  147. if ((GetAttributes(path) & FileAttributes.ReadOnly) == FileAttributes.ReadOnly){
  148. throw new UnauthorizedAccessException (Locale.GetText ("{0} is read-only", path));
  149. }
  150. }
  151. return new FileStream (path, FileMode.Create, FileAccess.ReadWrite,
  152. FileShare.None, bufferSize);
  153. }
  154. public static StreamWriter CreateText(string path)
  155. {
  156. return new StreamWriter (path, false);
  157. }
  158. public static void Delete (string path)
  159. {
  160. if (null == path)
  161. throw new ArgumentNullException("path");
  162. if (String.Empty == path.Trim() || path.IndexOfAny(Path.InvalidPathChars) >= 0)
  163. throw new ArgumentException("path");
  164. if (Directory.Exists (path))
  165. throw new UnauthorizedAccessException(Locale.GetText ("{0} is a directory", path));
  166. string DirName = Path.GetDirectoryName(path);
  167. if (DirName != String.Empty && !Directory.Exists (DirName))
  168. throw new DirectoryNotFoundException (Locale.GetText ("Destination directory not found: {0}", DirName));
  169. MonoIOError error;
  170. if (!MonoIO.DeleteFile (path, out error)){
  171. if (error != MonoIOError.ERROR_FILE_NOT_FOUND)
  172. throw MonoIO.GetException (path, error);
  173. }
  174. }
  175. public static bool Exists (string path)
  176. {
  177. // For security reasons no exceptions are
  178. // thrown, only false is returned if there is
  179. // any problem with the path or permissions.
  180. // Minimizes what information can be
  181. // discovered by using this method.
  182. if (null == path || String.Empty == path.Trim()
  183. || path.IndexOfAny(Path.InvalidPathChars) >= 0) {
  184. return false;
  185. }
  186. MonoIOError error;
  187. return MonoIO.ExistsFile (path, out error);
  188. }
  189. #if NET_2_0
  190. public static FileSecurity GetAccessControl (string path)
  191. {
  192. throw new NotImplementedException ();
  193. }
  194. public static FileSecurity GetAccessControl (string path, AccessControlSections includeSections)
  195. {
  196. throw new NotImplementedException ();
  197. }
  198. #endif
  199. public static FileAttributes GetAttributes (string path)
  200. {
  201. if (null == path) {
  202. throw new ArgumentNullException("path");
  203. }
  204. if (String.Empty == path.Trim()) {
  205. throw new ArgumentException (Locale.GetText ("Path is empty"));
  206. }
  207. if (path.IndexOfAny(Path.InvalidPathChars) >= 0) {
  208. throw new ArgumentException(Locale.GetText ("Path contains invalid chars"));
  209. }
  210. MonoIOError error;
  211. FileAttributes attrs;
  212. attrs = MonoIO.GetFileAttributes (path, out error);
  213. if (error != MonoIOError.ERROR_SUCCESS) {
  214. throw MonoIO.GetException (path, error);
  215. }
  216. return(attrs);
  217. }
  218. public static DateTime GetCreationTime (string path)
  219. {
  220. MonoIOStat stat;
  221. MonoIOError error;
  222. CheckPathExceptions (path);
  223. if (!MonoIO.GetFileStat (path, out stat, out error)) {
  224. #if NET_2_0
  225. if (error == MonoIOError.ERROR_PATH_NOT_FOUND || error == MonoIOError.ERROR_FILE_NOT_FOUND)
  226. return _defaultLocalFileTime;
  227. else
  228. throw new IOException (path);
  229. #else
  230. throw new IOException (path);
  231. #endif
  232. }
  233. return DateTime.FromFileTime (stat.CreationTime);
  234. }
  235. public static DateTime GetCreationTimeUtc (string path)
  236. {
  237. return GetCreationTime (path).ToUniversalTime ();
  238. }
  239. public static DateTime GetLastAccessTime (string path)
  240. {
  241. MonoIOStat stat;
  242. MonoIOError error;
  243. CheckPathExceptions (path);
  244. if (!MonoIO.GetFileStat (path, out stat, out error)) {
  245. #if NET_2_0
  246. if (error == MonoIOError.ERROR_PATH_NOT_FOUND || error == MonoIOError.ERROR_FILE_NOT_FOUND)
  247. return _defaultLocalFileTime;
  248. else
  249. throw new IOException (path);
  250. #else
  251. throw new IOException (path);
  252. #endif
  253. }
  254. return DateTime.FromFileTime (stat.LastAccessTime);
  255. }
  256. public static DateTime GetLastAccessTimeUtc (string path)
  257. {
  258. return GetLastAccessTime (path).ToUniversalTime ();
  259. }
  260. public static DateTime GetLastWriteTime (string path)
  261. {
  262. MonoIOStat stat;
  263. MonoIOError error;
  264. CheckPathExceptions (path);
  265. if (!MonoIO.GetFileStat (path, out stat, out error)) {
  266. #if NET_2_0
  267. if (error == MonoIOError.ERROR_PATH_NOT_FOUND || error == MonoIOError.ERROR_FILE_NOT_FOUND)
  268. return _defaultLocalFileTime;
  269. else
  270. throw new IOException (path);
  271. #else
  272. throw new IOException (path);
  273. #endif
  274. }
  275. return DateTime.FromFileTime (stat.LastWriteTime);
  276. }
  277. public static DateTime GetLastWriteTimeUtc (string path)
  278. {
  279. return GetLastWriteTime (path).ToUniversalTime ();
  280. }
  281. public static void Move (string src, string dest)
  282. {
  283. MonoIOError error;
  284. if (src == null)
  285. throw new ArgumentNullException ("src");
  286. if (dest == null)
  287. throw new ArgumentNullException ("dest");
  288. if (src.Trim () == "" || src.IndexOfAny (Path.InvalidPathChars) != -1)
  289. throw new ArgumentException ("src");
  290. if (dest.Trim () == "" || dest.IndexOfAny (Path.InvalidPathChars) != -1)
  291. throw new ArgumentException ("dest");
  292. if (!MonoIO.Exists (src, out error))
  293. throw new FileNotFoundException (Locale.GetText ("{0} does not exist", src), src);
  294. if (MonoIO.ExistsDirectory (dest, out error))
  295. throw new IOException (Locale.GetText ("{0} is a directory", dest));
  296. // Don't check for this error here to allow the runtime to check if src and dest
  297. // are equal. Comparing src and dest is not enough.
  298. //if (MonoIO.Exists (dest, out error))
  299. // throw new IOException (Locale.GetText ("{0} already exists", dest));
  300. string DirName;
  301. DirName = Path.GetDirectoryName(src);
  302. if (DirName != String.Empty && !Directory.Exists (DirName))
  303. throw new DirectoryNotFoundException(Locale.GetText ("Source directory not found: {0}", DirName));
  304. DirName = Path.GetDirectoryName(dest);
  305. if (DirName != String.Empty && !Directory.Exists (DirName))
  306. throw new DirectoryNotFoundException(Locale.GetText ("Destination directory not found: {0}", DirName));
  307. if (!MonoIO.MoveFile (src, dest, out error)) {
  308. if (error == MonoIOError.ERROR_ALREADY_EXISTS)
  309. throw MonoIO.GetException (dest, error);
  310. throw MonoIO.GetException (error);
  311. }
  312. }
  313. public static FileStream Open (string path, FileMode mode)
  314. {
  315. return new FileStream (path, mode, mode == FileMode.Append ? FileAccess.Write : FileAccess.ReadWrite, FileShare.None);
  316. }
  317. public static FileStream Open (string path, FileMode mode, FileAccess access)
  318. {
  319. return new FileStream (path, mode, access, FileShare.None);
  320. }
  321. public static FileStream Open (string path, FileMode mode, FileAccess access,
  322. FileShare share)
  323. {
  324. return new FileStream (path, mode, access, share);
  325. }
  326. public static FileStream OpenRead (string path)
  327. {
  328. return new FileStream (path, FileMode.Open, FileAccess.Read, FileShare.Read);
  329. }
  330. public static StreamReader OpenText (string path)
  331. {
  332. return new StreamReader (path);
  333. }
  334. public static FileStream OpenWrite (string path)
  335. {
  336. return new FileStream(path, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None);
  337. }
  338. #if NET_2_0
  339. public static void Replace (string sourceFileName,
  340. string destinationFileName,
  341. string destinationBackupFileName)
  342. {
  343. throw new NotImplementedException ();
  344. }
  345. public static void Replace (string sourceFileName,
  346. string destinationFileName,
  347. string destinationBackupFileName,
  348. bool ignoreMetadataErrors)
  349. {
  350. throw new NotImplementedException ();
  351. }
  352. public static void SetAccessControl (string path,
  353. FileSecurity fileSecurity)
  354. {
  355. throw new NotImplementedException ();
  356. }
  357. #endif
  358. public static void SetAttributes (string path,
  359. FileAttributes attributes)
  360. {
  361. MonoIOError error;
  362. CheckPathExceptions (path);
  363. if (!MonoIO.SetFileAttributes (path, attributes,
  364. out error)) {
  365. throw MonoIO.GetException (path, error);
  366. }
  367. }
  368. public static void SetCreationTime (string path,
  369. DateTime creation_time)
  370. {
  371. MonoIOError error;
  372. CheckPathExceptions (path);
  373. if (!MonoIO.Exists (path, out error))
  374. throw MonoIO.GetException (path, error);
  375. if (!MonoIO.SetCreationTime (path, creation_time, out error)) {
  376. throw MonoIO.GetException (path, error);
  377. }
  378. }
  379. public static void SetCreationTimeUtc (string path,
  380. DateTime creation_time)
  381. {
  382. SetCreationTime (path, creation_time.ToLocalTime ());
  383. }
  384. public static void SetLastAccessTime (string path,DateTime last_access_time)
  385. {
  386. MonoIOError error;
  387. CheckPathExceptions (path);
  388. if (!MonoIO.Exists (path, out error))
  389. throw MonoIO.GetException (path, error);
  390. if (!MonoIO.SetLastAccessTime (path, last_access_time, out error)) {
  391. throw MonoIO.GetException (path, error);
  392. }
  393. }
  394. public static void SetLastAccessTimeUtc (string path,DateTime last_access_time)
  395. {
  396. SetLastAccessTime (path, last_access_time.ToLocalTime ());
  397. }
  398. public static void SetLastWriteTime (string path,
  399. DateTime last_write_time)
  400. {
  401. MonoIOError error;
  402. CheckPathExceptions (path);
  403. if (!MonoIO.Exists (path, out error))
  404. throw MonoIO.GetException (path, error);
  405. if (!MonoIO.SetLastWriteTime (path, last_write_time, out error)) {
  406. throw MonoIO.GetException (path, error);
  407. }
  408. }
  409. public static void SetLastWriteTimeUtc (string path,
  410. DateTime last_write_time)
  411. {
  412. SetLastWriteTime (path, last_write_time.ToLocalTime ());
  413. }
  414. #region Private
  415. private static void CheckPathExceptions (string path)
  416. {
  417. if (path == null)
  418. throw new System.ArgumentNullException("path");
  419. if (path == "")
  420. throw new System.ArgumentException(Locale.GetText ("Path is empty"));
  421. if (path.Trim().Length == 0)
  422. throw new ArgumentException (Locale.GetText ("Path is empty"));
  423. if (path.IndexOfAny (Path.InvalidPathChars) != -1)
  424. throw new ArgumentException (Locale.GetText ("Path contains invalid chars"));
  425. }
  426. #endregion
  427. #if NET_2_0
  428. static File() {
  429. _defaultLocalFileTime = new DateTime (1601, 1, 1);
  430. _defaultLocalFileTime = _defaultLocalFileTime.ToLocalTime ();
  431. }
  432. //
  433. // The documentation for this method is most likely wrong, it
  434. // talks about doing a "binary read", but the remarks say
  435. // that this "detects the encoding".
  436. //
  437. // This can not detect and do anything useful with the encoding
  438. // since the result is a byte [] not a char [].
  439. //
  440. public static byte [] ReadAllBytes (string path)
  441. {
  442. using (FileStream s = Open (path, FileMode.Open, FileAccess.Read, FileShare.Read)){
  443. long size = s.Length;
  444. //
  445. // Is this worth supporting?
  446. //
  447. if (size > Int32.MaxValue)
  448. throw new ArgumentException ("Reading more than 4gigs with this call is not supported");
  449. byte [] result = new byte [s.Length];
  450. s.Read (result, 0, (int) size);
  451. return result;
  452. }
  453. }
  454. public static string [] ReadAllLines (string path)
  455. {
  456. using (StreamReader reader = File.OpenText (path)) {
  457. return ReadAllLines (reader);
  458. }
  459. }
  460. public static string [] ReadAllLines (string path, Encoding encoding)
  461. {
  462. using (StreamReader reader = new StreamReader (path, encoding)) {
  463. return ReadAllLines (reader);
  464. }
  465. }
  466. static string [] ReadAllLines (StreamReader reader)
  467. {
  468. List<string> list = new List<string> ();
  469. while (!reader.EndOfStream)
  470. list.Add (reader.ReadLine ());
  471. return list.ToArray ();
  472. }
  473. public static string ReadAllText (string path)
  474. {
  475. return ReadAllText (path, Encoding.UTF8Unmarked);
  476. }
  477. public static string ReadAllText (string path, Encoding enc)
  478. {
  479. using (StreamReader sr = new StreamReader (path, enc)) {
  480. return sr.ReadToEnd ();
  481. }
  482. }
  483. public static void WriteAllBytes (string path, byte [] data)
  484. {
  485. using (Stream stream = File.Create (path)) {
  486. stream.Write (data, 0, data.Length);
  487. }
  488. }
  489. public static void WriteAllLines (string path, string [] lines)
  490. {
  491. using (StreamWriter writer = new StreamWriter (path)) {
  492. WriteAllLines (writer, lines);
  493. }
  494. }
  495. public static void WriteAllLines (string path, string [] lines, Encoding encoding)
  496. {
  497. using (StreamWriter writer = new StreamWriter (path, false, encoding)) {
  498. WriteAllLines (writer, lines);
  499. }
  500. }
  501. static void WriteAllLines (StreamWriter writer, string [] lines)
  502. {
  503. foreach (string line in lines)
  504. writer.WriteLine (line);
  505. }
  506. public static void WriteAllText (string path, string contents)
  507. {
  508. WriteAllText (path, contents, Encoding.UTF8Unmarked);
  509. }
  510. public static void WriteAllText (string path, string contents, Encoding enc)
  511. {
  512. using (StreamWriter sw = new StreamWriter (path, false, enc)) {
  513. sw.Write (contents);
  514. }
  515. }
  516. private static readonly DateTime _defaultLocalFileTime;
  517. [MonoLimitation ("File encryption isn't supported (even on NTFS).")]
  518. public static void Encrypt (string path)
  519. {
  520. // MS.NET support this only on NTFS file systems, i.e. it's a file-system (not a framework) feature.
  521. // otherwise it throws a NotSupportedException (or a PlatformNotSupportedException on older OS).
  522. // we throw the same (instead of a NotImplementedException) because most code should already be
  523. // handling this exception to work properly.
  524. throw new NotSupportedException (Locale.GetText ("File encryption isn't supported on any file system."));
  525. }
  526. [MonoLimitation ("File encryption isn't supported (even on NTFS).")]
  527. public static void Decrypt (string path)
  528. {
  529. // MS.NET support this only on NTFS file systems, i.e. it's a file-system (not a framework) feature.
  530. // otherwise it throws a NotSupportedException (or a PlatformNotSupportedException on older OS).
  531. // we throw the same (instead of a NotImplementedException) because most code should already be
  532. // handling this exception to work properly.
  533. throw new NotSupportedException (Locale.GetText ("File encryption isn't supported on any file system."));
  534. }
  535. #endif
  536. }
  537. }