ไฟล์ถูกใช้โดยกระบวนการอื่นหลังจากใช้ File.Create ()


118

ฉันกำลังพยายามตรวจสอบว่ามีไฟล์อยู่ที่รันไทม์หรือไม่หากไม่มีให้สร้างขึ้น อย่างไรก็ตามฉันได้รับข้อผิดพลาดนี้เมื่อพยายามเขียนถึง:

กระบวนการไม่สามารถเข้าถึงไฟล์ 'myfile.ext' ได้เนื่องจากถูกใช้โดยกระบวนการอื่น

string filePath = string.Format(@"{0}\M{1}.dat", ConfigurationManager.AppSettings["DirectoryPath"], costCentre); 
if (!File.Exists(filePath)) 
{ 
    File.Create(filePath); 
} 

using (StreamWriter sw = File.AppendText(filePath)) 
{ 
    //write my text 
}

มีแนวคิดในการแก้ไขอย่างไร

คำตอบ:


112

File.Createวิธีการสร้างไฟล์และเปิดFileStreamที่ไฟล์ ดังนั้นไฟล์ของคุณจึงเปิดอยู่แล้ว คุณไม่ต้องการไฟล์จริงๆสร้างวิธีการเลย:

string filePath = @"c:\somefilename.txt";
using (StreamWriter sw = new StreamWriter(filePath, true))
{
    //write to the file
}

บูลีนในตัวStreamWriterสร้างจะทำให้เนื้อหาถูกต่อท้ายหากมีไฟล์อยู่


ฉันลองใช้รหัสด้านบน แต่ฉันได้รับข้อผิดพลาดเดียวกันเมื่อสร้างไฟล์และเมื่อพยายามเขียนลงในไฟล์แสดงว่าไฟล์ถูกใช้โดยกระบวนการอื่น
Anmol Rathod

@AnmolRathod ไปชัวร์ว่าไม่ได้ใช้File.Create()วิธี! ตัวอย่างด้านบนสร้างไฟล์แล้ว!
Daniel Eisenreich

138
    File.Create(FilePath).Close();
    File.WriteAllText(FileText);

ฉันต้องการอัปเดตคำตอบนี้เพื่อบอกว่านี่ไม่ใช่วิธีที่มีประสิทธิภาพสูงสุดในการเขียนข้อความทั้งหมด คุณควรใช้รหัสนี้เฉพาะในกรณีที่คุณต้องการบางอย่างที่รวดเร็วและสกปรก

ฉันเป็นโปรแกรมเมอร์อายุน้อยเมื่อฉันตอบคำถามนี้และในตอนนั้นฉันก็คิดว่าฉันเป็นอัจฉริยะที่คิดคำตอบนี้


4
ฉันชอบที่คำตอบอื่น ๆ ทั้งหมดซับซ้อนเกินไป ผู้คนไม่ทราบว่ามีคำตอบที่ง่ายกว่าสำหรับทุกปัญหา
Carsen Daniel Yates

14
ข้อเสียของรหัสนี้คือเปิดไฟล์สองครั้งโดยไม่จำเป็น นอกจากนี้ไม่จำเป็นต้องตรวจสอบว่ามีไฟล์อยู่หรือไม่เนื่องจากตัวสร้าง FileStream จะสร้างให้คุณโดยอัตโนมัติหากไม่มีอยู่เว้นแต่คุณจะบอกอย่างชัดเจนว่าไม่ทำเช่นนั้น
reirab

2
@reirab นี่เป็นญาติกันหมด ฉันต้องการตรวจสอบว่ามีไฟล์อยู่หรือไม่และถ้าเป็นเช่นนั้นให้ลบและสร้างใหม่อีกครั้งดังนั้นคำตอบนี้จึงเป็นที่ต้องการในกรณีของฉัน
makoshichi

1
@SO แล้วคุณมีปัญหาที่แตกต่างจาก OP เพียงแค่ปัญหาที่เกี่ยวข้อง นอกจากนี้ในกรณีของคุณคุณยังสามารถใช้ไฟล์FileStream(string, FileMode)สร้างและส่งผ่านFileMode.Createซึ่งจะเขียนทับไฟล์ที่มีอยู่ ยังไม่จำเป็นต้องเปิดไฟล์สองครั้ง นอกจากนี้คำตอบนี้ได้รับการแก้ไขหลังจากที่ฉันโพสต์ความคิดเห็นเดิมของฉัน
reirab

2
ประเด็นของคำตอบนี้คือการแสดงให้เห็นว่าคุณสามารถเพิ่ม.Close()ส่วนท้ายได้ดังนั้นจึงใช้ได้ในทุกกรณี ฉันไม่ไว้ใจระบบของการใช้FileStreamสำหรับทุกอย่างเพราะผมไม่ต้องการข้อยกเว้นที่จะเกิดขึ้นบนFileMode.Createว่าไฟล์ที่มีอยู่แล้ว - FileMode.Openโดยเฉพาะอย่างยิ่งเมื่อฉันต้องการล้างเนื้อหาและไม่ผนวกกับพวกเขาผ่าน ถึงฉัน,FileStreamจะใช้งานได้จริงหลังจากกำจัดไฟล์ที่เป็นปัญหาแล้วจึงเขียนลงในไฟล์นั้น เนื่องจากFile.Createเปิดทิ้งไว้และล็อกดูเหมือนว่าการเพิ่ม.Close()เข้าไปเป็นวิธีเดียวที่แท้จริงในการจัดการกับสถานการณ์และ SO ของฉัน
vapcguy

25

เมื่อสร้างไฟล์ข้อความคุณสามารถใช้รหัสต่อไปนี้:

System.IO.File.WriteAllText("c:\test.txt", "all of your content here");

ใช้รหัสจากความคิดเห็นของคุณ ไฟล์ (สตรีม) ที่คุณสร้างจะต้องถูกปิด File.Create ส่งคืนไฟล์สตรีมไปยังไฟล์ที่เพิ่งสร้าง:

string filePath = "filepath here";
if (!System.IO.File.Exists(filePath))
{
    System.IO.FileStream f = System.IO.File.Create(filePath);
    f.Close();
}
using (System.IO.StreamWriter sw = System.IO.File.AppendText(filePath))
{ 
    //write my text 
}

ฉันดูเหมือนจะไม่มีตัวเลือกที่ใกล้เคียง นี่คือรหัส: string filePath = string.Format (@ "{0} \ M {1} .dat", ConfigurationManager.AppSettings ["DirectoryPath"], costCentre); ถ้า (! File.Exists (filePath)) {File.Create (filePath); } โดยใช้ (StreamWriter sw = File.AppendText (filePath)) {// write my text}
Brett

File.CreateผลตอบแทนFileStreamและที่มีClose()
Null Head

15
FileStream fs= File.Create(ConfigurationManager.AppSettings["file"]);
fs.Close();

7
ยินดีต้อนรับสู่ Stackoverflow อย่างน้อยคุณควรเขียนคำอธิบายสั้น ๆ เพื่ออธิบายคำตอบ / วิธีแก้ปัญหาของคุณ
Paresh Mayani

9

File.Create ส่งคืน FileStream คุณต้องปิดเมื่อคุณเขียนลงไฟล์:

using (FileStream fs = File.Create(path, 1024)) 
        {
            Byte[] info = new UTF8Encoding(true).GetBytes("This is some text in the file.");
            // Add some information to the file.
            fs.Write(info, 0, info.Length);
        }

คุณสามารถใช้เพื่อปิดไฟล์โดยอัตโนมัติ


แม้ว่า OP จะพยายามเปิดไฟล์StreamWriterที่สามารถอนุมานได้จากการใช้File.AppendText.
binki

8

ฉันอัปเดตคำถามของคุณด้วยข้อมูลโค้ด หลังจากการเยื้องอย่างถูกต้องมันจะชัดเจนทันทีว่าปัญหาคืออะไร: คุณใช้File.Create()แต่อย่าปิดสิ่งFileStreamที่ส่งคืน

การทำแบบนั้นไม่จำเป็นStreamWriterอนุญาตให้ต่อท้ายไฟล์ที่มีอยู่แล้วและสร้างไฟล์ใหม่ได้หากยังไม่มี แบบนี้:

  string filePath = string.Format(@"{0}\M{1}.dat", ConfigurationManager.AppSettings["DirectoryPath"], costCentre); 
  using (StreamWriter sw = new StreamWriter(filePath, true)) {
    //write my text 
  }

ซึ่งใช้ตัวสร้างนี้StreamWriter .


1

คำถามนี้ได้รับคำตอบแล้ว แต่นี่คือวิธีแก้ปัญหาในโลกแห่งความเป็นจริงที่ตรวจสอบว่ามีไดเร็กทอรีอยู่หรือไม่และเพิ่มตัวเลขต่อท้ายหากไฟล์ข้อความมีอยู่ ฉันใช้สิ่งนี้ในการสร้างไฟล์บันทึกประจำวันบนบริการ Windows ที่ฉันเขียน ฉันหวังว่านี่จะช่วยใครบางคนได้

// How to create a log file with a sortable date and add numbering to it if it already exists.
public void CreateLogFile()
{
    // filePath usually comes from the App.config file. I've written the value explicitly here for demo purposes.
    var filePath = "C:\\Logs";

    // Append a backslash if one is not present at the end of the file path.
    if (!filePath.EndsWith("\\"))
    {
        filePath += "\\";
    }

    // Create the path if it doesn't exist.
    if (!Directory.Exists(filePath))
    {
        Directory.CreateDirectory(filePath);
    }

    // Create the file name with a calendar sortable date on the end.
    var now = DateTime.Now;
    filePath += string.Format("Daily Log [{0}-{1}-{2}].txt", now.Year, now.Month, now.Day);

    // Check if the file that is about to be created already exists. If so, append a number to the end.
    if (File.Exists(filePath))
    {
        var counter = 1;
        filePath = filePath.Replace(".txt", " (" + counter + ").txt");
        while (File.Exists(filePath))
        {
            filePath = filePath.Replace("(" + counter + ").txt", "(" + (counter + 1) + ").txt");
            counter++;
        }
    }

    // Note that after the file is created, the file stream is still open. It needs to be closed
    // once it is created if other methods need to access it.
    using (var file = File.Create(filePath))
    {
        file.Close();
    }
}

1

ฉันรู้ว่านี่เป็นคำถามเก่า แต่ฉันแค่อยากจะโยนคำถามนี้ออกไปที่คุณยังสามารถใช้ได้File.Create("filename")"เพียงแค่เพิ่ม.Dispose()เข้าไป

File.Create("filename").Dispose();

วิธีนี้จะสร้างและปิดไฟล์สำหรับกระบวนการถัดไปเพื่อใช้งาน


1
File.Create(FilePath).Close();จากคำตอบข้างต้นthis.Dispose(true); GC.SuppressFinalize((object) this);ในการนำไปใช้งาน
Ghukas

1

ฉันคิดว่าฉันรู้เหตุผลของข้อยกเว้นนี้ คุณอาจเรียกใช้ข้อมูลโค้ดนี้ในหลายเธรด


สำหรับฉันคือปัญหาที่ฉันเขียนล็อกไฟล์ด้วยวิธี asyncron (ในเธรดอื่น: Task.Run () โดยไม่ต้องรอ (ตามวัตถุประสงค์) และทำให้เกิดการเข้าถึงไฟล์เดียวกันแบบมัลติเธรด
Bence Végert

-1

ลองสิ่งนี้: มันใช้งานได้ในทุกกรณีหากไม่มีไฟล์อยู่ไฟล์จะสร้างขึ้นแล้วเขียนลงในนั้น และหากมีอยู่แล้วจะไม่มีปัญหาเปิดขึ้นและเขียนถึงมัน:

using (FileStream fs= new FileStream(@"File.txt",FileMode.Create,FileAccess.ReadWrite))
{ 
     fs.close();
}
using (StreamWriter sw = new StreamWriter(@"File.txt")) 
 { 
    sw.WriteLine("bla bla bla"); 
    sw.Close(); 
 } 

1
การใช้จะปิดไฟล์โดยเรียก Dispose ในไฟล์ตัวอย่างของคุณถูกปิดสองครั้ง
Valentine Zakharenko
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.