사용 절이이 스트림을 닫을까요?
-
22-08-2019 - |
문제
나는 분명히 나 자신을 나쁜 코딩 습관으로 일했다. 다음은 내가 작성한 코드의 예입니다.
using(StreamReader sr = new StreamReader(File.Open("somefile.txt", FileMode.Open)))
{
//read file
}
File.Move("somefile.txt", "somefile.bak"); //can't move, get exception that I the file is open
나는 그렇게 생각했다 using
조항은 명시 적으로 호출됩니다 Close()
그리고 Dispose()
에 StreamReader
그 FileStream
폐쇄 될 것입니다.
내가 가진 문제를 해결할 수있는 유일한 방법은 위의 블록을 이것으로 바꾸는 것입니다.
using(FileStream fs = File.Open("somefile.txt", FileMode.Open))
{
using(StreamReader sr = new StreamReader(fs))
{
//read file
}
}
File.Move("somefile.txt", "somefile.bak"); // can move file with no errors
닫아야합니다 StreamReader
첫 번째 블록에서 처분함으로써 기본을 닫습니다. FileStream
? 아니면 내가 착각 했습니까?
편집하다
나는 우리가 이것의 맨 아래로 갈 수 있는지 확인하기 위해 실제 범죄 코드 블록을 게시하기로 결정했습니다. 나는 지금 궁금합니다.
나는 내가 문제가 있다고 생각했다 using
절, 그래서 나는 모든 것을 확장했지만 매번 복사 할 수는 없습니다. 이 메소드 호출에서 파일을 생성하므로 파일에 핸들이 열려 있다고 생각하지 않습니다. 또한 문자열이 다시 돌아 왔음을 확인했습니다 Path.Combine
전화가 정확합니다.
private static void GenerateFiles(List<Credit> credits)
{
Account i;
string creditFile = Path.Combine(Settings.CreditLocalPath, DateTime.Now.ToString("MMddyy-hhmmss") + ".credits");
StreamWriter creditsFile = new StreamWriter(File.Open(creditFile, FileMode.Create));
creditsFile.WriteLine("code\inc");
foreach (Credit c in credits)
{
if (DataAccessLayer.AccountExists(i))
{
string tpsAuth = DataAccessLayer.GetAuthCode(i.Pin);
creditsFile.WriteLine(String.Format("{0}{1}\t{2:0.00}", i.AuthCode, i.Pin, c.CreditAmount));
}
else
{
c.Error = true;
c.ErrorMessage = "NO ACCOUNT";
}
DataAccessLayer.AddCredit(c);
}
creditsFile.Close();
creditsFile.Dispose();
string dest = Path.Combine(Settings.CreditArchivePath, Path.GetFileName(creditFile));
File.Move(creditFile,dest);
//File.Delete(errorFile);
}
해결책
예, StreamReader.Dispose
기본 스트림을 닫습니다 (모든 공개적으로 하나를 만드는 방법). 그러나 더 좋은 대안이 있습니다.
using (TextReader reader = File.OpenText("file.txt"))
{
}
이것은 Windows에 대한 힌트와 함께 기본 스트림을 엽니 다한다는 추가 이점이 있습니다.
다음은 첫 번째 버전이 저를 위해 작동하는 테스트 앱입니다. 나는 그것이 특히 무엇이든 증거라고 말하려고하지는 않지만 그것이 당신에게 얼마나 잘 작동하는지 알고 싶습니다.
using System;
using System.IO;
class Program
{
public static void Main(string[] args)
{
for (int i=0; i < 1000; i++)
{
using(StreamReader sr = new StreamReader
(File.Open("somefile.txt", FileMode.Open)))
{
Console.WriteLine(sr.ReadLine());
}
File.Move("somefile.txt", "somefile.bak");
File.Move("somefile.bak", "somefile.txt");
}
}
}
그것이 효과가 있다면, 그것은 당신이 읽는 동안하는 일과 관련이 있다는 것을 암시합니다 ...
그리고 이제 편집 된 질문 코드의 단축 버전이 있습니다. 네트워크 공유에서도 다시 잘 작동합니다. 내가 바꾸 었다는 점에 유의하십시오 FileMode.Create
에게 FileMode.CreateNew
- 그렇지 않으면 ~할 수 있었다 여전히 기존 파일의 손잡이가있는 앱이었습니다. 이것이 당신을 위해 효과가 있습니까?
using System;
using System.IO;
public class Test
{
static void Main()
{
StreamWriter creditsFile = new StreamWriter(File.Open("test.txt",
FileMode.CreateNew));
creditsFile.WriteLine("code\\inc");
creditsFile.Close();
creditsFile.Dispose();
File.Move("test.txt", "test2.txt");
}
}
다른 팁
참고 - 사용 블록을 자체 블록에 중첩 할 필요는 없습니다.
using(FileStream fs = File.Open("somefile.txt", FileMode.Open))
using(StreamReader sr = new StreamReader(fs))
{
//read file
}
이 경우 폐기 순서는 여전히 중첩 블록과 동일합니다 (즉, Streamreader는이 경우 필사자 전에 여전히 폐기합니다).
나는 사용하려고 노력할 것이다 FileInfo.Open()
그리고 FileInfo.MoveTo()
대신에 File.Open()
그리고 File.Move(
). 당신은 또한 사용하려고 노력할 수 있습니다 FileInfo.OpenText()
. 그러나 이것들은 단지 제안입니다.
다른 것이 somefile.txt에 잠금 장치가있을 가능성이 있습니까?
로컬 (파일)에서 간단한 확인 CMD 라인
net files
다른 것에 자물쇠가 있으면 단서를 줄 수 있습니다.
또는 당신은 같은 것을 얻을 수 있습니다 필라몬 자세한 내용을 보려면 앱이 제대로 공개되는지 확인하십시오.
이것은 코딩 문제가 아닌 것 같아서 Syadmin 모자를 착용하고 몇 가지 제안을 제공 할 것입니다.
- 파일이 생성 된대로 파일을 스캔하는 클라이언트 또는 서버의 바이러스 스캐너.
- 창 기회주의 잠금 네트워크 공유에 문제를 해결하는 습관이 있습니다. 플랫 파일 데이터베이스가있는 여러 읽기/쓰기 클라이언트의 문제라는 사실을 알지만 캐싱 확실히 당신의 문제를 설명 할 수 있습니다.
- 창 파일 열기 캐시. 이것이 Win2K에서 여전히 문제인지 아닌지 확실하지 않지만 Filemon이 당신에게 말할 것입니다.
편집 : 서버 시스템에서 ACT에서 잡을 수 있다면 Sysinternal의 손잡이가 열린 내용을 알려줍니다.