今晩は、嶋谷です。

すみません。せっかくサンプルコードまで書いていただいたのですが、
ちょっと私のレベルが低くてあまり理解できていません。
よろしければ、もう少し補足説明戴けないでしょうか?

At 19:13 99/08/31 +0900, S.Yoshida wrote:
>  shiumatani = Keisuke SHIMATANI writes:
> shiumatani># 使っている CBase64 は、行単位で処理するのだろうか???

> こちらは私は知りませんです。

申し訳ないです。少し長くなりますが、MFC Programmer's Source Book の
CBase64 を掲載させていただきます。
出典:
http://www.codeguru.com/xlate/japanese/

// The size of the output buffer must not be less than
// 3/4 the size of the input buffer. For simplicity,
// make them the same size.
int CBase64::Decode(LPCTSTR szDecoding, LPTSTR szOutput)
{
CString sInput;
int c, lp =0;
int nDigit;
int nDecode[ 256 ];

ASSERT( szDecoding != NULL );
ASSERT( szOutput != NULL );
if( szOutput == NULL )
return 0;
if( szDecoding == NULL )
return 0;
sInput = szDecoding;
if( sInput.GetLength() == 0 )
return 0;

// Build Decode Table
//
for( int i = 0; i < 256; i++ ) 
nDecode[i] = -2; // Illegal digit
for( i=0; i < 64; i++ )
{
nDecode[ m_sBase64Alphabet[ i ] ] = i;
nDecode[ m_sBase64Alphabet[ i ] | 0x80 ] = i; // Ignore 8th bit
nDecode[ '=' ] = -1; 
nDecode[ '=' | 0x80 ] = -1; // Ignore MIME padding char
}

// Clear the output buffer
memset( szOutput, 0, sInput.GetLength() + 1 );

// Decode the Input
//
for( lp = 0, i = 0; lp < sInput.GetLength(); lp++ )
{
c = sInput[ lp ];
nDigit = nDecode[ c & 0x7F ];
if( nDigit < -1 ) 
{
return 0;

else if( nDigit >= 0 ) 
// i (index into output) is incremented by write_bits()
write_bits( nDigit & 0x3F, 6, szOutput, i );
}
return i;
}


void CBase64::write_bits(UINT nBits,
 int nNumBits,
 LPTSTR szOutput,
 int& i)
{
UINT nScratch;

m_lBitStorage = (m_lBitStorage << nNumBits) | nBits;
m_nBitsRemaining += nNumBits;
while( m_nBitsRemaining > 7 ) 
{
nScratch = m_lBitStorage >> (m_nBitsRemaining - 8);
szOutput[ i++ ] = nScratch & 0xFF;
m_nBitsRemaining -= 8;
}
}

> CStdioFile::ReadString を使うと長さを調べる必要はありません。
> 今回は楽じゃないでしょうか?こんな感じ。

> CBase64    base64;  /* デコーダ     */
> CStdioFile file;    /* テキスト入力 */
> CString    line;    /* 行入力用     */

行単位の処理の場合ですね。

> CString    rcvbuf;  /* デコーダ出力 */
> CFile      output;  /* バイナリ出力 */
> int        b_len;
> char      *b_buf;

>   while( file.ReadString( &line ) ){

ファイルの終わりまで達すると(戻り値NULLで)ループを抜けるのですね。

>     if( line.Length() == 0 ){
>       continue;
>     }

GetLength() して、長さが0だったら再び制御式を評価するのですね。
break ではだめですか。

>     // Alloc 失敗のチェックを省略
>     b_buf = rcvbuf.GetBuffer( line.Length() );

rcvbuf のバッファへポインタの取得ですか?
バッファのサイズもここで確保しているのですか?

>     // 出力 bytes を返却されるものとして,,f(^^;
>     b_len = base64.Decode( (LPCTSTR)line, b_buf );

デコード結果が、b_buf に入るのですか?

>     TRY {

ここに、出力ファイルのオープンは、いりますか?

output.Open("output.bin", CFile::modeWrite | CFile::modeCreate);

>       output.Write( b_buf, b_len );

そして、ファイルに出力ですか?

>     }
>     CATCH( CFileException, e ) {
>       // WriteError
>     }
>     rcvbuf.ReleaseBuffer(); // 必要だろうか?

output.Close(); もいりますか?

>   }

> 二つのループをまとめれば,長さのチェックは不要になると思います。

読み出しと書き出しの二つのループのことですね?

> shiumatani>TRY、CATCH とやらもいるのでしょうか?

> 楽に済ませるならば必要でしょうね。 (^^;)

楽に済ませたいのですが、TRYを使えば何故楽になるのか分かりません。

> CBase64には,入力長を指定する手段は用意されていないのでしょうか?
> インスタンスがあるという事は,バッファリングも行うのでしょうか?
> 行単位で処理する(最低でも 4 bytes 単位)方法が無難なきがします。

> バッファリングしてくれるなら,ReadFileの戻り値が 入力バッファの
> サイズになるはずです。

残念ながらソースを見ても分からないのです・・・。m(_ _)m

> # 私はどのクラスライブラリも使わない方が安全な気がします。
> # 下で呼び出している fopen がちょっと。
> # ところで,stream は消えてしまったのでしょうか? > 皆さん

> とりあえず,CBase64を使用するなら,よくそのソースをご覧になる
> 事をお勧めします。(^^)

もう少しにらんでみます。