StreamSubscription listen 내부에서 file copy 이슈
217
작성한 질문수 1
안녕하세요. 학습내용을 확장하는 중 이슈가 있어서 문의드립니다.
윈도우 OS 타겟으로 개발 중이며,
특정폴더(origin)에 파일이 생성되는 event 발생 시 다른 특정폴더(target)로 파일을 복사하는 로직을 구현했습니다.
이슈는, 용량이 1kb로 작은 파일일 경우 잘 작동하지만, 용량이 몇mb 정도로 큰파일은 아래와 같은 예외가 발생하며 복사가 되지 않습니다.
예외는 다음과 같습니다.
Unhandled Exception: PathAccessException: Cannot copy file to 'C:\0.st\target\10.tdms', path = 'C:\0.st\origin\10.tdms' (OS Error: 다른 프로세스가 파일을 사용 중이기 때문에 프로세스가 액세스 할 수 없습니다.
, errno = 32)
#0 _checkForErrorResponse (dart:io/common.dart:55:9)
#1 File.copy.<anonymous closure> (dart:io/fileimpl.dart:356:7)
<asynchronous suspension>제가 파일을 복사하기 위해 구현한 함수는 아래와 같습니다.
중간에 newOriginFile.copy(copyFilePath); 부분에서 예외가 발생합니다.
참고로 copySync 메서드로 변경해 보았으나 같은 현상이 발생합니다.
복사할 대상 파일을 다른 프로세스에서 열지 않은 상태인데도 위와 같은 예외가 발생하여 디버깅이 안되는 상황입니다.
항상 감사합니다!
void _startEvaluationMode() {
Navigator.pop(context, 'OK');
// 계측 모드 시작
setState(() {
_evaluationMode = true;
});
// origin 경로 불러오기
if (_directoryInfoBox.containsKey(DirectoryType.origin.name)) {
setState(() {
_originDirectory =
Directory(_directoryInfoBox.get(DirectoryType.origin.name)!.path);
});
if (!_originDirectory!.existsSync()) {
// 실제 origin 경로의 폴더가 존재하지 않는 상태
// origin directory 확인하라는 alert dialog 보여주고 evaluation mode 종료
}
// origin 경로 워칭
Stream<FileSystemEvent> originDirFileEvent = _originDirectory!.watch();
print('start evaluation mode');
// _streamListner = originDirFileEvent.listen((event) async {
// if (event.type == 1) {
// print('create event');
// }
// });
_streamListner = originDirFileEvent.listen((event) {
// origin 경로에 새 파일이 생성된 경우 FileSystemCreateEvent type == 1
if (event.type == 1) {
print('created file: ${event.path}');
final newOriginFile = File(event.path);
// 포맷에 맞는 파일 이름 생성
var newOriginFilename = p.basenameWithoutExtension(event.path);
// print('base file name: ${newOriginFilename}');
String testMethodRoadName =
TestMethodRoadInfoManager.getNameById(newOriginFilename);
// 중복되는 이름 확인
// 파일 이름을 _ 로 분리하여 4번째 인덱스 값으로 구분
List<String> existingTestMethodRoadNameList =
_evaluationItem!.evaluationFileInfos!.map((fileInfo) {
return p
.basenameWithoutExtension(fileInfo.evaluationFilePath)
.split('_')
.first;
}).toList();
// print(existingTestMethodRoadNameList);
//
List<String> duplicatedList =
existingTestMethodRoadNameList.where((name) {
return name == testMethodRoadName;
}).toList();
String fileNameWithDuplicateCount = '';
if (duplicatedList.isNotEmpty) {
fileNameWithDuplicateCount =
'${testMethodRoadName}_${duplicatedList.length + 1}';
} else {
fileNameWithDuplicateCount = '${testMethodRoadName}_1';
}
// print('road name: ${testMethodRoadName}');
// var copyFilePath = p.join(_itemDirectory!.path,
// '${_itemFilePrefix}_${fileNameWithDuplicateCount}.tdms');
var copyFilePath = p.join(
_itemDirectory!.path, '${fileNameWithDuplicateCount}.tdms');
print('copy file path: ${copyFilePath}');
// 파일을 eval item 경로로 이름 바꾸어 복사
newOriginFile.copy(copyFilePath);
print('copy finish');
// eval item DB의 evaluationFileInfos 리스트 업데이트
var newEvaluationFileInfo = EvaluationFileInfo(
originFilePath: event.path,
evaluationFilePath: copyFilePath,
activated: true,
);
setState(() {
_evaluationItem!.evaluationFileInfos!.add(newEvaluationFileInfo);
});
// print(
// 'file info length: ${_evaluationItem!.evaluationFileInfos!.length}');
_evaluationItemBox.put(_evaluationItem!.id, _evaluationItem!);
// ui 상 file list, count 업데이트
List<File> files = [];
for (var entity in _itemDirectory!
.listSync(recursive: false, followLinks: false)) {
if (entity is File) {
files.add(entity);
}
}
setState(() {
_files = files;
});
}
});
}
}
답변 1
1
안녕하세요!
의심하시는 것 처럼 파일 크기의 문제가 아닐 가능성이 높습니다. (부가적인 이유일수는 있습니다.)
에러 메세지를 잘 읽어보시면 "다른 프로세스가 파일을 사용 중이기 때문에 프로세스가 액세스 할 수 없습니다."라고 나와있습니다.
말 그대로 이미 열려있는 또는 사용중인 파일을 다시 접근하려고하니 문제가 생기는겁니다.
파일이 큰 경우에만 에러가 난다면 파일의 크기가 작은 경우 동시 접근 문제가 생기기 전에 파일 관련 작업이 끝나기 때문일 수 있습니다.
어찌됐든 모든 IO 관련 작업은 파일 크기와 관련 없이 이미 접근중인 파일은 다시 접근하지 못하도록 코드를 작성하시는게 중요합니다.
감사합니다!
0
파일이 다른곳에서 접근하는 로직은 없었으나, 일단 말씀하신바와 같이 파일이 열려있다는 에러였기때문에, 타겟 파일이 available한 상태가 될때까지 잠시 기다리는 로직을 추가하여 기능 구현은 했습니다. 왜 어디서 리소스를 잡고 있는지 모르겠으나...일단 해결이 되어 다행입니다.
198강 (){onTap(e);}의 이해 돕기
0
29
1
video_call 플러그인 설치후 에러 발생
0
46
1
SDK 안드로이드 설치 질문!
0
60
1
코드팩토리 디스코드 링크 다시 부탁드려요~
0
92
1
Webview를 이용해서 URL 상의 페이지 출력 불가
0
70
1
홈스크린 함수를 함축해서 main.dart에 옮기는 문제
0
55
1
플레이스토어
0
59
1
아고라 엔진 init 함수의 반환타입이 Future<void> 이것의 의미는 무엇인가요?
0
55
1
가이드라인 질문
0
57
0
emulator 에러 환경설정 뭐가 문제 일까요??
0
77
1
emulator 실행 오류
0
93
3
Column을 가로방향 최대 사이즈를 차지하도록 하는 방법에 관련
0
71
1
pubspec.yaml에서 font를 추가하면서 weight 값을 지정하는 것이 의미가 있는 것인지 문의
0
43
1
setState()를 호출하지 않으면 build가 실행 안되는 건가요?
0
53
1
video_call 플러그인 설치시 에러문제
0
64
1
children 안의 if 문에서 { } 못쓰는 이유?
0
48
1
이렇게 오류가 떠요
0
64
1
AppBar 사용했는데
0
61
2
[문제해결] '오늘도 출첵!' 의 171번 강의에서 중요한 문제를 발견했습니다
0
56
1
StatefulWidget 실습 에러가 발생합니다.[해결완료]
0
63
1
Video Player 프로젝트에 대한 추가 질문
0
53
0
Row위젯이나 column위젯의 위치는 누가 정하나요??
0
42
1
geolocator 오류때문에 개발진행이 불가능입니다
0
63
1
API 관련 이슈
0
86
2





