今晩は、嶋谷です。
すみません。せっかくサンプルコードまで書いていただいたのですが、
ちょっと私のレベルが低くてあまり理解できていません。
よろしければ、もう少し補足説明戴けないでしょうか?
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を使用するなら,よくそのソースをご覧になる
> 事をお勧めします。(^^)
もう少しにらんでみます。
すみません。せっかくサンプルコードまで書いていただいたのですが、
ちょっと私のレベルが低くてあまり理解できていません。
よろしければ、もう少し補足説明戴けないでしょうか?
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を使用するなら,よくそのソースをご覧になる
> 事をお勧めします。(^^)
もう少しにらんでみます。