You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何避免C#代码中的System.IO.IOException异常?

如何避免操作Users.txt时抛出System.IO.IOException?

我看了你这段操作Users.txt的C#代码,出现System.IO.IOException大概率是因为文件资源没有正确释放或者读写操作的时机冲突导致的。先把你提供的代码片段整理出来(注意代码有截断):

public static void Main() 
{ 
    string username = "", password, chkusername; 
    bool vald, chk; 
    vald = false; 
    string choice = "Y"; 
    while (choice == "Y") 
    { 
        FileStream fs = new FileStream("Users.txt", FileMode.Append, FileAccess.Write, FileShare.Read); 
        StreamWriter sw = new StreamWriter(fs); 
        Console.WriteLine("Enter Username : "); 
        var Createnew = File.ReadAllLines("Users.txt"); 
        chkusername = Console.ReadLine(); 
        foreach(string Dummies in Createnew) 
        { 
            string[] userline = Dummies.Split('#'); 
            if(userline[0]... // 代码截断
        }
        // 缺少资源释放的代码
    }
}

问题根源分析

  1. 读写时机冲突:你在循环一开始就打开了文件的写入流,但之后又调用File.ReadAllLines读取同一个文件。即便设置了FileShare.Read,当前进程持有写入句柄时,后续的读操作仍可能因为文件锁定触发异常。
  2. 资源未释放:你没有手动关闭FileStreamStreamWriter,也没使用自动释放机制,导致文件句柄一直被占用。下一次循环尝试打开文件时,就会抛出“文件正由另一进程使用”的IOException。

解决方案

方案1:用using语句自动管理资源

FileStreamStreamWriter都实现了IDisposable接口,用using包裹它们,会在代码块结束时自动关闭并释放文件资源,彻底避免句柄泄漏。同时调整操作顺序,先完成用户名检查再打开写入流:

public static void Main() 
{ 
    string username = "", password, chkusername; 
    bool isUsernameExists;
    string choice = "Y"; 
    
    while (choice.Equals("Y", StringComparison.OrdinalIgnoreCase)) 
    { 
        Console.WriteLine("Enter Username : "); 
        chkusername = Console.ReadLine()?.Trim() ?? "";
        isUsernameExists = false;

        // 先读取文件检查用户名是否存在
        if (File.Exists("Users.txt"))
        {
            var allUsers = File.ReadAllLines("Users.txt"); 
            foreach(string userLine in allUsers) 
            { 
                string[] userData = userLine.Split('#'); 
                // 防止格式错误的行导致索引越界
                if(userData.Length > 0 && userData[0].Trim() == chkusername)
                {
                    isUsernameExists = true;
                    break;
                }
            }
        }

        if(isUsernameExists)
        {
            Console.WriteLine("Username already exists!");
        }
        else
        {
            Console.WriteLine("Enter Password : ");
            password = Console.ReadLine()?.Trim() ?? "";
            
            // 用using自动释放写入资源
            using (FileStream fs = new FileStream("Users.txt", FileMode.Append, FileAccess.Write, FileShare.Read))
            using (StreamWriter sw = new StreamWriter(fs))
            {
                sw.WriteLine($"{chkusername}#{password}");
                Console.WriteLine("User created successfully!");
            }
        }

        Console.WriteLine("Do you want to create another user? (Y/N)");
        choice = Console.ReadLine()?.Trim().ToUpper() ?? "N";
    }
}

方案2:用File.AppendAllText简化操作

如果你只是需要追加写入文本,完全可以用File.AppendAllText静态方法,它会自动处理文件的打开、写入和关闭,代码更简洁:

// 替换方案1中的写入代码块
if(!isUsernameExists)
{
    Console.WriteLine("Enter Password : ");
    password = Console.ReadLine()?.Trim() ?? "";
    File.AppendAllText("Users.txt", $"{chkusername}#{password}{Environment.NewLine}");
    Console.WriteLine("User created successfully!");
}

额外注意事项

  • StringComparison.OrdinalIgnoreCase比较字符串,避免用户输入小写"y"时退出循环的问题。
  • 读取文件前先判断File.Exists,避免第一次运行时文件不存在导致的异常。
  • 分割用户行后检查数组长度,防止空行或格式错误的行触发IndexOutOfRangeException

内容的提问来源于stack exchange,提问作者Dodofold

火山引擎 最新活动