CHashtag

[C#] 다른 프로세스가 읽을 수 있게 파일 열기 (FileAccess, FileShare) 본문

C#

[C#] 다른 프로세스가 읽을 수 있게 파일 열기 (FileAccess, FileShare)

HyoSeong 2021. 2. 26. 01:25
반응형

안녕하세요.

 

오늘은 파일을 점유하되(Write), 다른 프로세스가 해당 파일을 읽을(Read) 수 있는 방법에 대해 알아보도록 하겠습니다.

 

 

File.Open


File.Open 함수는 최대 4개의 인자(Parameter)를 받도록 되어있습니다.

 

https://docs.microsoft.com/ko-kr/dotnet/api/system.io.file.open?view=net-5.0#System_IO_File_Open_System_String_System_IO_FileMode_System_IO_FileAccess_System_IO_FileShare_

 

 

우선 인자에 대해 간략하게 설명해드리고, 해당 인자들을 혼합하여 파일을 여는 방법에 대하여 설명해 드리겠습니다.

 

 

Arguments


 

path

  • 말 그대로 Open 할 파일의 경로입니다.

 

fileMode

  • Path의 파일을 가지고 할 행동을 나타냅니다.
    • FileMode enum은 아래와 같습니다. [관련 링크]
      • CreateNew
        • 파일을 새로 만들지만, 이미 있으면 에러가 납니다.
      • Create
        • path에 파일을 새로 만들고, 해당 경로에 파일이 이미 존재한다면 덮어 씌웁니다.
        • 파일이 존재하지 않는다면 CreateNew 하고, 파일이 존재한다면 Truncate 합니다.
      • Open
        • 파일을 엽니다. 해당 경로에 파일이 존재하지 않는다면 에러가 납니다.
      • OpenOrCreate
        • 파일이 존재하면 파일을 열고, 파일이 존재하지 않으면 CreateNew 합니다.
      • Truncate
        • 파일을 엽니다. 대신 열고 내용을 모두 지웁니다.
      • Append
        • 파일을 열고 파일의 끝까지 검색하거나 새 파일을 만듭니다.

 

 access

  • 내가(본인 프로세스) 이 파일을 열 때에 지정할 권한을 의미합니다.
  • FileAccess enum은 아래와 같습니다. [관련 링크]
    • Read
      • 파일을 읽을 수 있습니다.
    • ReadWrite
      • 파일을 읽고 쓸 수 있습니다.
    • Write
      • 파일에 쓸 수 있습니다.
    • ReadWrite
      • 파일을 읽고 쓸 수 있습니다. (주로 이 옵션을 사용합니다.)

 

share

  • 다른 프로세스(스레드)가 파일을 열 때 가질 수 있는 권한을 지정합니다.
    • FileShare enum은 아래와 같습니다. [관련 링크]
      • None
        • 다른 프로세스가 해당 파일에 접근할 수 없습니다. (내 작업이 끝나야 접근이 가능합니다.)
      • Read
        • 다른 프로세스가 파일을 읽을 수 있습니다.
      • Write
        • 다른 프로세스가 파일을 쓸 수 있습니다.
      • ReadWrite
        • 다른 프로세스가 파일을 읽고 쓸 수 있습니다.
      • Delete
        • 다른 프로세스가 파일을 지울 수 있습니다.
      • Inheritable
        • 자식 프로세스가 파일 핸들을 상속받을 수 있습니다.

 

Example


// Case 1. 두 프로세스 모두 열기
using (var stream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.None))
{
    // Error
    using (var stream2 = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.None))
    {
    
    }
}

// Case 2. 두 프로세스 모두 열기, FileShare.Read추가
using (var stream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read))
{
    // Good
    using (var stream2 = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read))
    {
    
    }
}

// Case 3. 한 프로세스는 쓰고, 한 프로세스는 읽기
using (var stream = new FileStream(path, FileMode.Open, FileAccess.Write, FileShare.Read))
{
    // Error
    using (var stream2 = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read))
    {
    
    }
}

// Case 4. 한 프로세스는 쓰고, 한 프로세스는 읽기
using (var stream = new FileStream(path, FileMode.Open, FileAccess.Write, FileShare.Read))
{
    // Good
    using (var stream2 = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Write))
    {
    
    }
}

 

 

위 4가지 Case에서 3번과 4번이 이해가 잘 가지 않으실 겁니다. (제가 그랬거든요..)

 

분명히 FileAccess.Write와 FileShare.Read를 하면 stream2에서 파일을 읽을 수 있어야 할 텐데요..

 

아래 링크에 따르면, FileShare은 처음 파일을 열 때에만 지정되는 것이 아닌, 두 번째에 파일을 여는 stream2도 FileShare를 지정해 주어야 합니다.

 

또한 FileShare를 지정해 줄 때 첫 번째 stream이 이미 Write를 사용하여 파일을 열고 있기 때문에 stream2에서 FileShare.Write를 지정해 주어야 오류가 나지 않는 것입니다.

 

(stream에서의 FileAccess가 stream2의 FileShare에 속해 있어야 하는 것입니다.)

 

https://stackoverflow.com/questions/16544099/file-sharing-not-working-as-expected

 

File sharing not working as expected

I have a file sharing issue where my process is trying to read a log file whilst it is currently still open by NLog. In diagnosing the issue, I found something surprising. The following fails: usi...

stackoverflow.com

 

 

감사합니다.

반응형