특정 안드로이드 기기에서 System.IO.Compression의 ZipFile.ExtractToDirectory 메소드를 이용해 Zip 파일을 압축 해재할때 Invalid parameter 오류가 뜨는 문제를 해결 방법이다.
오류 로그는 다음과 같다.
System.IO.IOException: Invalid parameter
at System.IO.File.SetLastWriteTime (System.String path, System.DateTime lastWriteTime) [0x0002a] in :0
at System.IO.Compression.ZipFileExtensions.ExtractToFile (System.IO.Compression.ZipArchiveEntry source, System.String destinationFileName, System.Boolean overwrite) [0x00067] in <8d4e08735b1842d0842f236ab3e206a3>:0
at System.IO.Compression.ZipFileExtensions.ExtractToDirectory (System.IO.Compression.ZipArchive source, System.String destinationDirectoryName, System.Boolean overwrite) [0x0009d] in <8d4e08735b1842d0842f236ab3e206a3>:0
at System.IO.Compression.ZipFile.ExtractToDirectory (System.String sourceArchiveFileName, System.String destinationDirectoryName, System.Text.Encoding entryNameEncoding, System.Boolean overwrite) [0x00017] in <8d4e08735b1842d0842f236ab3e206a3>:0
at System.IO.Compression.ZipFile.ExtractToDirectory (System.String sourceArchiveFileName, System.String destinationDirectoryName, System.Text.Encoding entryNameEncoding) [0x00000] in <8d4e08735b1842d0842f236ab3e206a3>:0
at System.IO.Compression.ZipFile.ExtractToDirectory (System.String sourceArchiveFileName, System.String destinationDirectoryName) [0x00000] in <8d4e08735b1842d0842f236ab3e206a3>:0
우선 이 오류를 해결하는데 결정적인 역할을 한 Git Issue 페이지를 링크로 남긴다.
https://github.com/xamarin/xamarin-android/issues/2005
해결법
이 오류는 FUSE 파일 시스템을 사용하는 특정 안드로이드 기기에서만 발생한다.
따라서 IOS, window에서는 발생하지 않고,
Android Oreo (Android 8.0) 이상의 버전에서는 FUSE 파일 시스템을 사용하지 않으므로 발생하지 않는다.
해결법은 ExtractToDirectory 메소드를 try-catch 문으로 묶어 IOException이 발생하면
System.IO.File.SetLastWriteTime (System.String path, System.DateTime lastWriteTime)
메소드를 호출하지 않고 압축을 풀어야한다.
아래 코드를 첨부한다.
try
{
ZipFile.ExtractToDirectory(bundlePath + FilePath, path);
}
catch (IOException e)
{
Console.WriteLine(e);
using (var source = ZipFile.Open(bundlePath + FilePath, ZipArchiveMode.Read, null))
{
string fullName = Directory.CreateDirectory(path).FullName;
int length = fullName.Length;
if (length != 0 && (int) fullName[length - 1] != (int) Path.DirectorySeparatorChar)
fullName += Path.DirectorySeparatorChar.ToString();
foreach (ZipArchiveEntry entry in source.Entries)
{
string fullPath = Path.GetFullPath(Path.Combine(fullName, entry.FullName));
if (!fullPath.StartsWith(fullName, StringComparison.OrdinalIgnoreCase))
throw new IOException("IO_ExtractingResultsInOutside");
if (Path.GetFileName(fullPath).Length == 0)
{
if (entry.Length != 0L)
throw new IOException("IO_DirectoryNameWithData");
Directory.CreateDirectory(fullPath);
}
else
{
Directory.CreateDirectory(Path.GetDirectoryName(fullPath));
FileMode mode = FileMode.Create;
using (var destination = (Stream) File.Open(fullPath, mode, FileAccess.Write, FileShare.None))
{
using (var stream = entry.Open())
stream.CopyTo(destination);
}
}
}
}
}
'메모장 > C#' 카테고리의 다른 글
[C#] 코드의 문서화를 도와주는 Doxygen (2) | 2022.11.25 |
---|---|
C#의 자동 구현 프로퍼티 (Auto-Implemented Properties, 자동 구현 속성) (0) | 2020.07.09 |
[C#] 자꾸 까먹는 C# 디렉토리 구분자 가져오기 (0) | 2020.02.20 |
C# params, ref와 in, out 매개 변수 한정자 (0) | 2019.10.29 |