2009-01-24 13 views
26

다른 사람이이를 수행하는 방법에 대해 설명해 줄 수 있습니까? 일반 텍스트 또는 바이트 배열에 대해이 작업을 수행 할 수 있지만 pdf에 접근하는 방법을 알 수는 없습니다. 먼저 바이트 배열로 pdf를 채우는가?Base64 C#으로 PDF를 인코딩 하시겠습니까?

+2

PDF가 바이트 배열과 다른 이유는 무엇입니까? –

답변

39

File.ReadAllBytes을 사용하여 PDF 파일을로드 한 다음 Convert.ToBase64String(bytes)을 사용하여 정상적으로 바이트 배열을 인코딩합니다.

+2

Yikes! 그것은 커질 수 있습니다. –

+0

사실. 요즘 컴퓨터는 많은 메모리를 가지고 있습니다. 그리고 필요한 경우 파일에서 버퍼링 된 블록을 읽는 것은 꽤 표준적인 기술입니다. –

+0

내가 필요한 순간에 효과적입니다. 팁 고마워! – Tone

34

한꺼번에 많은 양의 메모리를 구울 필요가 없도록이 작업을 청크로 수행 할 수있는 방법이 있습니다.

.Net에는 청크를 수행 할 수있는 인코더가 포함되어 있지만 이상한 장소에 있습니다. 그들은 그것을 System.Security.Cryptography 네임 스페이스에 넣었습니다.

아래의 예제 코드를 테스트했으며 위에 나온 방법이나 Andrew의 방법을 사용하여 동일한 결과를 얻었습니다.

어떻게 작동합니까? CryptoStream이라는 클래스를 시작합니다. 이것은 다른 스트림에 연결되는 어댑터의 일종입니다. CryptoTransform 클래스를 CryptoStream (파일/메모리/네트워크 스트림에 연결됨)에 연결하고 스트림에서 읽거나 스트림에 쓰는 동안 데이터에 대한 데이터 변환을 수행합니다.

일반적으로 변환은 암호화/복호화이지만 .net에는 ToBase64 및 FromBase64 변환도 포함되어 있으므로 암호화하지 않고 인코딩 만합니다.

다음은 코드입니다. 앤드류 (Andrew)의 제안을 어쩌면 잘못 작성한 구현을 포함 시켰기 때문에 결과를 비교할 수 있습니다.

 

    class Base64Encoder 
    { 
     public void Encode(string inFileName, string outFileName) 
     { 
      System.Security.Cryptography.ICryptoTransform transform = new System.Security.Cryptography.ToBase64Transform(); 
      using(System.IO.FileStream inFile = System.IO.File.OpenRead(inFileName), 
             outFile = System.IO.File.Create(outFileName)) 
      using (System.Security.Cryptography.CryptoStream cryptStream = new System.Security.Cryptography.CryptoStream(outFile, transform, System.Security.Cryptography.CryptoStreamMode.Write)) 
      { 
       // I'm going to use a 4k buffer, tune this as needed 
       byte[] buffer = new byte[4096]; 
       int bytesRead; 

       while ((bytesRead = inFile.Read(buffer, 0, buffer.Length)) > 0) 
        cryptStream.Write(buffer, 0, bytesRead); 

       cryptStream.FlushFinalBlock(); 
      } 
     } 

     public void Decode(string inFileName, string outFileName) 
     { 
      System.Security.Cryptography.ICryptoTransform transform = new System.Security.Cryptography.FromBase64Transform(); 
      using (System.IO.FileStream inFile = System.IO.File.OpenRead(inFileName), 
             outFile = System.IO.File.Create(outFileName)) 
      using (System.Security.Cryptography.CryptoStream cryptStream = new System.Security.Cryptography.CryptoStream(inFile, transform, System.Security.Cryptography.CryptoStreamMode.Read)) 
      { 
       byte[] buffer = new byte[4096]; 
       int bytesRead; 

       while ((bytesRead = cryptStream.Read(buffer, 0, buffer.Length)) > 0) 
        outFile.Write(buffer, 0, bytesRead); 

       outFile.Flush(); 
      } 
     } 

     // this version of Encode pulls everything into memory at once 
     // you can compare the output of my Encode method above to the output of this one 
     // the output should be identical, but the crytostream version 
     // will use way less memory on a large file than this version. 
     public void MemoryEncode(string inFileName, string outFileName) 
     { 
      byte[] bytes = System.IO.File.ReadAllBytes(inFileName); 
      System.IO.File.WriteAllText(outFileName, System.Convert.ToBase64String(bytes)); 
     } 
    } 
 

나는 또한 CryptoStream을 첨부하여 놀고 있습니다. Encode 메서드에서는 출력 (쓰기) 스트림에 연결하고 있으므로 CryptoStream을 인스턴스화 할 때 Write() 메서드를 사용합니다.

읽을 때 입력 (읽기) 스트림에 연결하므로 CryptoStream에서 read 메서드를 사용합니다. 내가 어떤 물줄기를 붙일지는별로 중요하지 않다. CryptoStream의 생성자에 적절한 읽기 또는 쓰기 열거 형 멤버를 전달하면됩니다.

+0

나는 이것을 달리고 검증하지 않았지만 이것은 유망하게 훌륭하고 굉장한 것처럼 보인다. 멋진 아이디어! +1 – codingbear

+1

나는 이것을 테스트했다. 매력처럼 작동합니다. 잘 했어. – mcNux

+0

@mcNux : 감사합니다. – JMarsch