58

How to handle file name in System.IO classes in a cross-platform manner to make it work on Windows and Linux?

For example, I write this code that works perfectly on Windows, however it doesn't create a file on Ubuntu Linux:

var tempFilename = $@"..\Data\uploads\{filename}";
using (FileStream fs = System.IO.File.Create(tempFilename))
{
    file.CopyTo(fs);
    fs.Flush();                    
}
stakx - no longer contributing
  • 83,039
  • 20
  • 168
  • 268
Roman Kolesnikov
  • 11,777
  • 11
  • 44
  • 67

9 Answers9

63

You can also use Path.DirectorySeparatorChar as below:

 Console.WriteLine("..{0}Data{0}uploads{0}{{filename}}", Path.DirectorySeparatorChar);

Reference: MSDN

onemorecupofcoffee
  • 2,237
  • 1
  • 15
  • 21
58

Windows using Backslash. Linux using Slash. Path.Combine set the right symbol :
Path.Combine Method - MSDN

  • Is there any kind of automatic path conversion similar to Qt that uses slash exclusively and converts them to backslash on windows? – Roman Kolesnikov Jul 03 '16 at 10:39
  • 4
    @Rem Do you need to convert them? Windows generally supports slashes too. – svick Jul 03 '16 at 10:59
  • As svick says, slashes can be used as path separators on Windows (only command.com and cmd.exe interpret slashes as something else) @Rem – Paul Stelian Jul 03 '16 at 11:46
  • Automatic conversion ? How about detecting the OS, if Linux then String.Replace("\","/") and if windows then String.Replace("/","\") –  Jul 03 '16 at 11:46
  • 2
    May be detecting endians, or smth else))) I would write in C++ if i needed to deal with such a things in C#! – Roman Kolesnikov Jul 03 '16 at 11:55
  • 3
    Worth noting that if combining two paths on Linux, this method won't "correct" any existing backslashes in either of the paths. It assumes the arguments given are correct for the OS, and just inserts the correct directory separater as needed for the OS. – benmccallum Oct 10 '19 at 11:45
14

Lots of good answers. I would just like to add that one can avoid having to specify the directory separator character by using Path.Combine

Example with the file relatively located at ".\..\toto\app.config":

Path.Combine("..", "toto", "app.config");

Unfortunately, Path.Combine does not resolve a relative path to an absolute Path in .Net Core. Path.GetFullPath is here for that:

Path.GetFullPath(Path.Combine("..", "toto", "app.config"))
Vilmir
  • 1,135
  • 14
  • 13
  • I was not sure Path.GetFullPath would work out of Windows, but it does on macos. I will update my answer – Vilmir Jul 21 '19 at 11:59
5

You can simply use slashes. Relative paths will work identically, and absolute paths can only be relative to the root of the main drive (as absolute paths starting with "c:" are not portable)

Paul Stelian
  • 1,381
  • 9
  • 27
4

The original post is over a year old but I still ran into this issue. It seems to me like the use of dots in relative paths is also an issue.

A path like

".\\input\\mydata.csv" 

worked well on windows but not on unix. When changing the dot-notation for current directory to:

Path.GetFullPath(Directory.GetCurrentDirectory())

I had more success.

user3042674
  • 187
  • 1
  • 7
2

Of course forward slashes work fine - except when they don't. It is an older problem, but certainly LoadLibrary actually bit me in this regard. Please see https://stackoverflow.com/a/34708551/1318024 which discusses this. Even though we do expect Windows to handle path separators gracefully (which we do not expect for *nix!) it is best to use the path separator appropriate for the platform.

user1318024
  • 342
  • 2
  • 6
  • I did in fact notice in ReactOS that the slashes are translated in the userspace functions and maybe some don't do the translation. Huh. – Paul Stelian Aug 07 '20 at 15:11
2

I do development on windows and linux so relative path settings in json config are not always correct for the platform. Path.Combine doesn't help if you have a path separator in the config path. Using a Replace does the trick tho. Eg:

var root = "c:\\bob";
var dir = "somepath/fred";
var path = Path.Combine(root, dir);  // = c:\bob\somepath/fred

path.Replace('/', Path.DirectorySeparatorChar); // = c:\fred\somepath\fred on windows
Jonesie
  • 6,997
  • 10
  • 48
  • 66
0

you can use this simple function:

private string get_platform_compatible_path(string path)
{
   return path.Replace('\\', Path.DirectorySeparatorChar).Replace('/', Path.DirectorySeparatorChar);
}
Ramil Shavaleev
  • 364
  • 3
  • 12
-1

There are also problem with file name cases in linux. For instance if you have file name like Index.js and used in your code like index.js vice versa, you are having a problem too

Ozan BAYRAM
  • 2,780
  • 1
  • 28
  • 35