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