2012-05-08 12 views
6

WindowsのGetPrivateProfileXXX関数(INIファイルの操作に使用)には、バッファ長の処理に関するいくつかの奇妙な規則があります。GetPrivateProfileString - バッファの長さ

のGetPrivateProfileStringのドキュメントの状態:

[..]供給先バッファが要求された文字列を保持するには小さすぎる、文字列が切り捨てられ、ヌル文字が続いており、戻り値が等しい場合nSizeマイナス1。

私はこれを読んで、私は、この動作は、それが不可能で、コードの2つのシナリオを区別することができますことに気づい:値の文字列の長さがnsizeの場合と全く同じである場合には

  • - 1.
  • ときnSize値(すなわち、バッファ)が小さすぎる。

私が試したいと思った:

[Bar] 
foo=123456 

そして、私はテストとしてこれらの引数でのGetPrivateProfileStringと呼ばれる:私は、INIファイルでこれを持って

// Test 1. The buffer is big enough for the string (16 character buffer). 
BYTE* buffer1 = (BYTE*)calloc(16, 2); // using 2-byte characters ("Unicode") 
DWORD result1 = GetPrivateProfileString(L"Bar", L"foo", NULL, buffer, 16, fileName); 

// result1 is 6 
// buffer1 is { 49, 0, 50, 0, 51, 0, 52, 0, 53, 0, 54, 0, 0, 0, 0, 0, ... , 0, 0 } 

// Test 2. The buffer is exactly sufficient to hold the value and the trailing null (7 characters). 
BYTE* buffer2 = (BYTE*)calloc(7, 2); 
DWORD result2 = GetPrivateProfileString(L"Bar", L"foo", NULL, buffer, 7, fileName); 

// result2 is 6. This is equal to 7-1. 
// buffer2 is { 49, 0, 50, 0, 51, 0, 52, 0, 53, 0, 54, 0, 0, 0 } 

// Test 3. The buffer is insufficient to hold the value and the trailing null (6 characters). 
BYTE* buffer3 = (BYTE*)calloc(6, 2); 
DWORD result3 = GetPrivateProfileString(L"Bar", L"foo", NULL, buffer, 6, fileName); 

// result3 is 5. This is equal to 6-1. 
// buffer3 is { 49, 0, 50, 0, 51, 0, 52, 0, 53, 0, 0, 0 } 

このコードを呼び出すプログラムは、実際のキー値が最後の2つのカスのように実際に5文字の長さであっても、6文字であっても確かに知る方法がありません結果はnSize - 1に等しくなります。

唯一の解決策は、結果== nSize - 1を確認し、より大きなバッファで関数を呼び出すことですが、バッファが正確に正しいサイズ。

良い方法はありませんか?

答えて

5

良い方法はありません。最初のバッファが十分に大きいことを確認してください。この問題を解決する方法は、ドキュメントに記載されていないものを使用する必要があるため、動作する保証はありません。

1

いいえ、残念ながら、良い方法はありません。十分に大きなバッファを用意する必要があります。十分でない場合は、バッファを再割り当てします。私はhereからコードスニペットを取って、あなたのケースに適応:

int nBufferSize = 1000; 
int nRetVal; 
int nCnt = 0; 
BYTE* buffer = (BYTE*)calloc(1, 2); 

do 
{ 
    nCnt++; 
     buffer = (BYTE*) realloc (buffer , nBufferSize * 2 * nCnt); 
     DWORD nRetVal = GetPrivateProfileString(L"Bar", L"foo", NULL,   
      buffer, nBufferSize*nCnt, filename);  
} while((nRetVal == ((nBufferSize*nCnt) - 1)) || 
      (nRetVal == ((nBufferSize*nCnt) - 2))); 

しかし、特定の場合には、ファイル名がMAX_PATHよりも大きい長さを持つことができませんので、(MAX_PATH+1)*2常にフィットします。

+0

これはCまたはC++のコードですか? –

0

おそらく、をGetPrivateProfileStringの直後に呼び出すのがいい方法です。バッファが十分に大きく、その他のエラーがない場合、GetLastErrorは0を返します。バッファが小さすぎる場合はGetLastError234 (0xEA) ERROR_MORE_DATAを返します。

+0

残念ながら、バッファを完全に埋めるとき(データを切り捨てなくても)、INI関数は常に 'ERROR_MORE_DATA'を返します。 – efotinis

0

私はそれが少し遅れていることを知っていますが、私は素晴らしい解決策を考え出しました。バッファスペースが残っていない場合(戻り長+ 1 =バッファ長)、バッファを拡張して値を再度取得します。バッファースペースが残るまでこのプロセスを繰り返します。

関連する問題