我喜欢用System.IO.File.WriteAllBytes()
来使事情简单。但是,这种方法似乎并不是万能的。在我的本地系统上写,它工作得很好。
但是当我使用System.IO.File.WriteAllBytes()
在Windows共享上写入时,它会产生一个空文件并出现异常:
System.UnauthorizedAccessException: Access to the path '/var/windowsshare/file.bin' is denied.
---> System.IO.IOException: Permission denied
如果我在https://github.com/dotnet/runtime/blob/c72b54243ade2e1118ab24476220a2eba6057466/src/libraries/System.IO.FileSystem/src/System/IO/File.cs#L421查看源代码我发现下面的代码在工作:
using (FileStream fs = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read))
{
fs.Write(bytes, 0, bytes.Length);
}
如果我改变代码并使用FileShare.None
而不是FileShare.Read
,它可以工作。所以我有一个变通办法,我必须记住System.IO.File.WriteAllBytes()
不是防水的(它是正确的吗?)。
不幸的是,我的分析最后得出了几个相关的问题:
如果目标路径是可配置的,那么最佳实践是什么?开发人员是否必须避免system . io . file . writeallbytes(),或者系统管理员是否必须找到另一种方式来挂载共享?filesshare . read有什么问题?当System.IO.File.WriteAllBytes()正在写入时,Windows共享更改权限/锁定吗?挂载Windows共享有什么技巧吗?
更新1
WriteAllBytes ():
// WriteAllBytes() Throws System.UnauthorizedAccessException
System.IO.File.WriteAllBytes("/var/windowsshare/file.bin", bytes);
创建和移动c#
// Create local and move + optional overwrite works!
var tmp = Path.GetTempFileName(); // local file
System.IO.File.WriteAllBytes(tmp, bytes); // write local
System.IO.File.Move(tmp, "/var/windowsshare/file.bin", true); // optional overwrite
ls:
# ls -l /var/windowsshare/file.bin
-rw-rw-rw-. 1 apache apache 20 Feb 9 11:43 /var/windowsshare/file.bin
# ls -Z /var/windowsshare/file.bin
system_u:object_r:cifs_t:s0 /var/windowsshare/file.bin
山……
# mount -l
//1.2.3.4/windowsshare on /var/windowsshare type cifs (rw,relatime,vers=3.1.1,cache=strict,username=luke,domain=dom,uid=48,forceuid,gid=48,forcegid,addr=1.2.3.4,file_mode=0666,dir_mode=0777,soft,nounix,nodfs,nouser_xattr,mapposix,noperm,rsize=4194304,wsize=4194304,bsize=1048576,echo_interval=60,actimeo=1,_netdev)
# stat -f -c %T /var/windowsshare/file.bin
smb2
下面的线程(https://github.com/dotnet/runtime/issues/42790)在Github上帮助我。最后,我用nobrl
选项重新挂载了我的CIFS共享。
在线程中,他们也得出了使用FileShare.None
工作的结论,但根本原因似乎是我们正在使用的CIFS服务器不支持字节范围锁。
我不确定这意味着什么,但在我的情况下,不需要多次写入文件,也不应该有两个进程试图写入同一个文件。