问题是:在Windows上取一个相对文件夹结构,把它打包成一个JSON文件,然后在linux发行版上复制它,比如Ubuntu 20.04,使用。net 5。
这是我的(非常简化的)方法:
using System.IO;
using System.Collections.Generic;
using Newtonsoft.Json;
using Internal;
public class FileData
{
public string Path { get; set; }
public string FileName { get; set; }
}
public static void Main(string[] args)
{
var rootPath = Path.GetFullPath(@"C:/tempFolder");
var files = Directory.GetFiles(rootPath, "*.*", SearchOption.AllDirectories);
List<FileData> fileData = new List<FileData>();
foreach (var file in files)
{
fileData.Add(new FileData
{
FileName = Path.GetFileName(file),
Path = Path.GetRelativePath(rootPath, Path.GetDirectoryName(file))
});
}
Console.WriteLine(JsonConvert.SerializeObject(fileData));
}
现在输出类似
的内容[
{
"Path":"InnerFolder\Subfolder",
"FileName":"TestFile.txt"
}
]
将JSON写入文件并将其传输到linux,并沿着以下行执行:
var rootPath = Path.GetFullPath("/home/user/tempFolder2/");
var fileData = JsonConvert.DeserializeObject<List<FileData>>(dataReadFromFile);
foreach(var file in fileData)
{
var path = Path.Combine(rootPath, file.Path, file.FileName);
//...proceed to create file and path
}
问题是,这里的路径返回/home/user/tempFolder2/InnerFolderSubfolder/TestFile
,因为反斜杠在linux中是一个有效的路径字符,并且它不会被path . combine .
解析。我想这里有两个选项:
- 以某种方式强制窗口使用AltPathSeparatorChar ('/')
- 走穷人的路,把所有的"\"如果系统不是WinNT32,则在相对路径中出现''。
现在我非常不喜欢第二个选项,以防路径是使用linux生成的,并且反斜杠确实是反斜杠。我更希望所有的输出文件都有一个标准的"路径"格式。变量,但我不能为我的生活弄清楚,如何强制路径命名空间使用正斜杠路径,而不是反斜杠在Windows。
是否有一种方法可以使用Path api来实现这一点,或者我必须去if(OS)…路吗?
编辑:在与@Olivier Rogier进行了简短的讨论后,我决定更新这个问题,以防有人知道一个集成的解决方案。
归根结底:
var relativePath = Path.GetRelativePath("./folder", "./folder/sf1/sf2");
返回"sf1 sf2"在Windows "sf1/sf2"在Linux中。因此,如果程序员没有额外的代码,如果代码在两个不同的系统上运行,那么这行代码是不确定的。
运行像这里这样的简单示例
//WRITER
var relativePath = Path.GetRelativePath("./folder", "./folder/sf1/sf2");
File.WriteAllText("transferFile", relativePath);
//READER, on another OS
var relativePath = File.ReadAllText("transferFile");
var combinedPath = Path.Combine("./folder", relativePath);
在两个环境中不会产生相同的结果。
1: Writer: WIN, Reader: WIN写入器输出:sf1\sf2阅读器中的合并路径:文件夹\sf1\sf2Dir创建结果:文件夹-sf1-sf2
2: Writer: LNX, Reader: WIN写入输出:sf1/sf2阅读器中的合并路径:文件夹\sf1\sf2Dir创建结果:文件夹-sf1-sf2
3: Writer: WIN, Reader: LNX写入器输出:sf1\sf2阅读器中的合并路径:文件夹/sf1\sf2/Dir创建结果:文件夹-sf1\sf2
另一个例子是使用Linux目录路径
<>之前的文件夹-sf1stillavalidfoldernameWriter: LNX, Reader: WIN写入输出:sf1stillavalidfoldername阅读器中的合并路径:文件夹\sf1\stillavalidfolde\rnameDir创建结果:文件夹-sf1-stillavalidfolde-rname
到目前为止,唯一可行的解决方案是类似于
//WRITER
var relativePath = Path.GetRelativePath("./folder", "./folder/sf1/sf2");
File.WriteAllLines("transferFile", relativePath.Split(Path.DirectorySeparatorChar));
//READER, on another OS
var relativePaths = File.ReadAllLines("transferFile");
var combinedPath = Path.Combine("./folder", relativePaths);
这当然意味着要更新所有的序列化器、序列化代码等等,所以他们在任何路径被序列化的地方使用分割/连接方法,并且降低了人类的可读性。
可以期望至少对Path命名空间方法进行重载,其中可以指定目录分隔字符(强制使用Path。GetFullPath和Path。组合方法以始终使用相同的格式),一个RelativePath类,其中这是在内部处理的,或者可能是另一种我没有想到的方法。
重申一下,是否有一种方法可以提取、存储和读取字符串中的相对路径名,而不是在Windows和Linux上读取和写入,而无需将字符串路径转换为目录数组?
要独立于操作系统,我会使用路径将相对路径保存为JSON中的数组。DirectorySeparatorChar属性:
// Example: notepad.exe relative to C:
var pathParts = Path.GetRelativePath(@"C:", Path.GetDirectoryName(@"C:WindowsSystem32notepad.exe"))
.Split(Path.DirectorySeparatorChar);
与路径。组合你可以恢复你的操作系统依赖部分:
var restoredPath = Path.Combine(pathParts);