파일을 byte []로 변환하는 안정적인 방법


84

웹에서 다음 코드를 찾았습니다.

private byte [] StreamFile(string filename)
{
   FileStream fs = new FileStream(filename, FileMode.Open,FileAccess.Read);

   // Create a byte array of file stream length
   byte[] ImageData = new byte[fs.Length];

   //Read block of bytes from stream into the byte array
   fs.Read(ImageData,0,System.Convert.ToInt32(fs.Length));

   //Close the File Stream
   fs.Close();
   return ImageData; //return the byte data
}

C #에서 파일을 byte []로 변환하는 데 사용할 수있을만큼 신뢰할 수 있습니까? 아니면 더 좋은 방법이 있습니까?


3
실제로 호출 fs.Close()되었는지 확인하려면 나머지 코드를 포함하는 try-finally 문의 finally-part에 넣어야 합니다 Close.
Joren

답변:


219
byte[] bytes = System.IO.File.ReadAllBytes(filename);

그게 트릭을해야합니다. ReadAllBytes는 파일을 열고 내용을 새 바이트 배열로 읽은 다음 닫습니다. 해당 방법에 대한 MSDN 페이지 는 다음과 같습니다 .


이로 인해 파일 잠금이 발생합니까?
JL.

내 말은-byte []가 채워지면 파일이 여전히 잠겨 있지 않습니까?
JL.

3
아니요, 그렇지 않습니다. 바이트 배열이 채워지면 파일이 닫힙니다.
Erik Forbes

4
작은 이 가진 문제는 당신이 (등 5백메가바이트 또는 1GB의 말) 큰 파일이있는 경우 그것은 당신의 바이트 배열에 대한 그 많은 메모리를 할당 할 것입니다. 따라서 때때로 .Read (..)를 반복하고 천천히 꺼내는 것이 좋습니다. 물론 그 모든 것은 파일 크기에 따라 다릅니다. :)
Joshua

3
파일이 다른 프로세스에서 열리면 실패합니다. OP 방법은 FileShare.ReadWriteafterFile.Read
Motes

28
byte[] bytes = File.ReadAllBytes(filename) 

또는 ...

var bytes = File.ReadAllBytes(filename) 

13
정말? 이 경우 'var'는 완벽하게 허용됩니다. 반환 유형은 메서드 이름에 명확하게 명시되어 있습니다.
Erik Forbes

4
원래 사용하는 일 var. 가능한 한 많이 사용해야한다는 것이 저의 개인적인 의견입니다 (그리고 다른 많은 사람들의 의견). :)이 문제는 사실 이전에이 사이트에서 여러 번 논의되었습니다.
Noldorin

8
또한 var 사용에 대한 +1 ... @silky, 새로운 언어 기능이 도입 될 때 모든 사람이 자유롭게 의견을 가질 수 있다고 생각하지만, 귀하의 의견에 맞지 않기 때문에 답변에 반대 투표를하는 것은 아닙니다. 이 포럼에 대한 내용입니다. 그것은 확실히 JL의 질문과 거의 관련이 없습니다.
Charles Bretana

6
비추천 할 때 개인적인 선호 이상의 것을 고려해야한다고 생각합니다. 이것은 유무에 관계없이 완벽하게 유효한 대답 var입니다. 유형을 수동으로 명시 적으로 작성해야하는 프로그래머는 너무 낮은 추상화 수준에서 작업한다고 생각하는 경향이 있습니다. 변수의 정확한 유형이 무엇인지는 중요 하지 않으며 변수의 용도 만 중요합니다 . 파일의 바이트를 저장하면 그게 중요합니다. 목록이든 배열이든 MyCustomContainer이든 상관 없습니다.
jalf

8
그것이 var실제 대답과 전혀 관련이 있었다면 그 사용에 대해 논쟁하는 것이 합리적이었을 것입니다. 그러나 여기서 대답의 중요한 부분은 File.ReadAllBytes(filename). 결과가 변수에 저장되는 방법과 여부는 변수 이름 지정이나 =.
jalf

12

모두가 이미 말한 것을 반복하지 말고 파일 조작을 위해 다음 치트 시트를 잘 보관하십시오.

  1. System.IO.File.ReadAllBytes(filename);
  2. File.Exists(filename)
  3. Path.Combine(folderName, resOfThePath);
  4. Path.GetFullPath(path); // converts a relative path to absolute one
  5. Path.GetExtension(path);

6

이 모든 답변은 .ReadAllBytes(). 비슷한 또 다른 질문이 여기에 제기되었습니다. C #에서 큰 파일을 바이트 배열로 읽는 가장 좋은 방법?

에 관한 게시물 중 하나에 댓글이 작성되었습니다 .ReadAllBytes().

File.ReadAllBytes throws OutOfMemoryException with big files (tested with 630 MB file 
and it failed) – juanjo.arana Mar 13 '13 at 1:31

나에게 더 나은 접근 방식은 다음과 같은 것입니다 BinaryReader.

public static byte[] FileToByteArray(string fileName)
{
    byte[] fileData = null;

    using (FileStream fs = File.OpenRead(fileName)) 
    { 
        var binaryReader = new BinaryReader(fs); 
        fileData = binaryReader.ReadBytes((int)fs.Length); 
    }
    return fileData;
}

하지만 그게 나야 ...

물론,이 모든 것은 byte[]일단 읽어 들인 후 처리 할 메모리가 있다고 가정 하고, File.Exists이 코드를 호출하기 전에 수행 했듯이 계속하기 전에 파일이 있는지 확인 하지 않았습니다 .


1
코드에 오류가 있습니다. 사용중인 using 문에 새 항목이 필요하지 않습니다. (FileStream fs = File.OpenRead (fileName)
JoseR

그다지 오류는 아니지만 (코드가 여전히 컴파일 될 것이라고 생각합니다) 모두 똑같이 제거했습니다. 잘 잡았습니다.
vapcguy

3

일반 버전으로 충분 해 보입니다. 충분히 구체적인 경우 필요에 맞게 수정할 수 있습니다.

또한 파일이 존재하지 않거나 읽을 수없는 것과 같은 예외 및 오류 조건을 테스트합니다.

다음을 수행하여 공간을 절약 할 수도 있습니다.

 byte[] bytes = System.IO.File.ReadAllBytes(filename);

2

다른 사람들은 기본 제공 File.ReadAllBytes. 기본 제공 방법은 괜찮지 만 위에 게시 한 코드는 두 가지 이유로 취약하다는 점에 주목할 가치가 있습니다.

  1. Stream입니다 IDisposable- 당신이 배치해야FileStream fs = new FileStream(filename, FileMode.Open,FileAccess.Read) 파일이 닫혀 있는지 확인하기 위해 사용 절에 초기화합니다. 이렇게하지 않으면 오류가 발생해도 스트림이 열린 상태로 유지되어 파일이 잠긴 상태로 유지되고 나중에 다른 문제가 발생할 수 있음을 의미 할 수 있습니다.
  2. fs.Read요청한 것보다 적은 바이트를 읽을 수 있습니다. 일반적으로 인스턴스 의 .Read메서드는 Stream최소 1 바이트를 읽지 만 요청하는 모든 바이트를 읽을 필요는 없습니다. 모든 바이트를 읽을 때까지 읽기를 재 시도하는 루프를 작성해야합니다. 이 페이지에서는 이에 대해 자세히 설명합니다.
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.