【问题标题】:What's the least invasive way to read a locked file in C# (perhaps in unsafe mode)?在 C# 中读取锁定文件的侵入性最小的方法是什么(可能在不安全模式下)?
【发布时间】:2010-08-24 20:14:35
【问题描述】:

我需要读取一个可能被锁定的 Windows 文件,但我不想创建任何会阻止其他进程写入文件的类型的锁。

另外,即使文件被锁定为独占使用,我也想看看里面有什么。

虽然这不是我的确切用例,但请考虑如何在 SQL/Exchange 日志或数据库文件正在使用和挂载时读取它。我不想造成损坏,但我仍然想查看文件的内部并阅读它。

【问题讨论】:

    标签: c# file locking


    【解决方案1】:

    不用复制文件也可以,见this文章:

    诀窍是使用 FileShare.ReadWrite(来自文章):

    private void LoadFile()
    {
        try
        {
            using(FileStream fileStream = new FileStream(
                "logs/myapp.log",
                FileMode.Open,
                FileAccess.Read,
                FileShare.ReadWrite))
            {
                using(StreamReader streamReader = new StreamReader(fileStream))
                {
                    this.textBoxLogs.Text = streamReader.ReadToEnd();
                }
            }
        }
        catch(Exception ex)
        {
            MessageBox.Show("Error loading log file: " + ex.Message);
        }
    } 
    

    【讨论】:

    【解决方案2】:

    接受的答案不正确。如果文件确实被锁定,则不能只更改文件共享。如果也使用此文件共享选项设置了锁定,这将起作用,但这并不意味着是这种情况。事实上,您可以通过打开不带FileShare.ReadWrite 的文件而不是尝试使用ReadWrite 的标志打开它来非常轻松地测试@CaffGeek 解决方案。您会发现该文件正在被另一个进程使用。

    代码:

    string content;
    var filePath = "e:\\test.txt";
    
    //Lock Exclusively the file
    var r = File.Open(filePath, FileMode.Open, FileAccess.Write, FileShare.Write);
    
    //CaffGeek solution
    using (FileStream fileStream = new FileStream(
            filePath,
            FileMode.Open,
            FileAccess.Read,
            FileShare.ReadWrite))
    {
        using (StreamReader streamReader = new StreamReader(fileStream))
        {
            content = streamReader.ReadToEnd();
        }
    }
    

    如您所见,它崩溃了。此结果与任何FileStream 方法(如File.Open)相同。它会使您在打开阶段为 FileShare 输入的内容崩溃。

    //OPEN FOR WRITE with exclusive
    var r = File.Open(filePath, FileMode.Open, FileAccess.Write, FileShare.Write);
    
    
    //OPEN FOR READ with file share that allow read and write
    var x = File.Open(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); //Crash
    

    复制文件也不是一种选择。您可以通过独占打开文件并尝试在 Windows 资源管理器中复制文件或通过代码自行尝试:

    var filePath = "e:\\test.txt";
    var filePathCopy = "e:\\test.txt.bck";
    
    //Lock the file
    var r = File.Open(filePath, FileMode.Open, FileAccess.Write, FileShare.Write);
    
    File.Copy(filePath, filePathCopy);
    var x = File.Open(filePathCopy, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
    using (var reader = new StreamReader(x))
    {
        content = reader.ReadToEnd();
    }
    
    r.Close();
    File.Delete(filePathCopy);
    

    当您点击File.Copy 行时,此代码会崩溃。异常与之前相同:文件正在被另一个进程使用。

    如果你想读取文件,或者如果你有锁定文件的文件的源代码,你需要杀死拥有文件锁定的进程,以将这个文件更改为使用FileShare.ReadWrite 而不仅仅是@ 987654330@.

    【讨论】:

    • 那或者我可以使用备份,VSS APIs
    • 我实际上已经成功复制了文件,但是在复制时遇到了锁定问题(某些状态正在被复制?)
    【解决方案3】:

    即使文件被锁定,您也可以创建一个副本并阅读它。

    或者可能是 FileStream 上的 StreamReader,具体取决于 SQL 如何打开文件?

    new FileStream("c:\myfile.ext", FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
    

    【讨论】:

    • 这可以工作...但是数据库很大。也许我需要知道 Copy 是如何工作的,因为我想要那种访问权限。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-29
    • 2016-11-20
    • 2013-10-24
    • 1970-01-01
    • 2015-08-06
    相关资源
    最近更新 更多