2011-08-21 12 views
6

大きなファイルを書き込もうとしていますが、問題が発生しました。C++で4GBを超えるファイルにデータを書き込む方法は?

書き込む場所を探すのに長いロングを使用しますが、4,2Gbを超えるファイルは書き込めません。私が忘れたのは何ですか?

詳細: 私は4GBのファイル開く:その後

ifstream ifs(db_name.c_str(), ios_base::binary); 
if (!ifs) 
    throw Bad_archive(); 
ifs.read(as_bytes(seg_size), sizeof(int)); 
ifs.read(as_bytes(last_idx), sizeof(int)); 
ifs.read(as_bytes(free_segs), sizeof(int)); 
if (free_segs > 0) 
{ 
    long long seek_g = 3 * sizeof(int) + (long long)last_idx * seg_size; 
    ifs.seekg(seek_g, ios_base::beg); 
    for (int i = 0; i < free_segs; i++) 
    { 
     int tmp = 0; 
     ifs.read(as_bytes(tmp), sizeof(int)); 
     free_spaces.push_back(tmp); 
    } 
} 
ifs.close(); 

は、私は、DBに追加する最大400Mbファイルを読み込みます。 (ここでは短いコードがある)書き込み:その後

// write object 
ofstream ofs(db_name.c_str(), ios_base::binary | ios_base::in | ios_base::ate); 
for (int i = 0; ; i++) 
{ 
    // set stream position 
    long long write_position = sizeof(int) * 3; 

    ... 

    write_position += (long long) seg_size * last_idx; 
    ofs.seekp(write_position, ios::beg); 

      ... 

    // write sizeof object 
    if (i == 0) 
     ofs.write(as_bytes(object_size), sizeof(object_size)); 
    else 
    { 
     int null = 0; 
     ofs.write(as_bytes(null), sizeof(null)); 
    } 

    // write data 
    for (int j = 0; j < (seg_size - sizeof(int) * 2); j++) 
    { 
     ofs.write(as_bytes(obj_content[j + i * (seg_size - sizeof(int) * 2)]), 
     sizeof(char)); 

    } 
    if (write_new_seg) 
     last_idx++; 

    ... 

    ofs.write(as_bytes(cont_seg), sizeof(cont_seg)); 
} 
ofs.close(); 

を、私はDBの情報を保存します

if (last_idx == 0) 
{ 
    ofstream ofs(db_name.c_str()); 
    ofs.close(); 
} 
ofstream ofs(db_name.c_str(), ios_base::binary | ios_base::in | 
      ios_base::out | ios_base::ate); 
long long seek_p = 0; 
ofs.seekp(seek_p, ios_base::beg); 
ofs.write(as_bytes(seg_size), sizeof(seg_size)); 
ofs.write(as_bytes(last_idx), sizeof(last_idx)); 
ofs.write(as_bytes(free_segs), sizeof(free_segs)); 
ofs.close(); 

をしかし、このコードは動作します:

ofstream ofs2("huge2"); 
ofs2.close(); 
ofstream ofs("huge2", ios_base::in | ios_base::ate); 
long long sp = 10000000000; 
ofs.seekp(10000000000, ios_base::beg); 

ofs.write(as_bytes(sp), sizeof(sp)); 

ofs.close(); 
+0

ループ内で常にシークして、目的のポイントに進むことはできますが、位置合わせされていないオフセットを追跡することは難しくなります。 –

+0

私はお試しください。 Thanx – bluebyte

+0

多くのC++ストリームの実装は、これまでの世紀に止まっています。誰もが4ギガバイトで十分でした。 64フィンガーでカウントするchar_traits :: pos_typeを更新するのは簡単ではなく、既存のコードを破壊します。 intについて語ったupvoted答えはそれを明白にします。 –

答えて

4
fseeko64 (Filename, 0, SEEK_END); 
    long size = ftello64 (Filename); 
    fclose (Filename); 

、fseek関数を使用することはできません、代わりにfseeko64()のために行く必要が。ここでは、Linux用の素敵な要約があり

0

多くfilesystemsは、ファイルをサポートしていません。 4GBより大きいさらに、intタイプの範囲は、2^32で終わる範囲(4.29497e + 09)になる可能性があります。

+1

1.私はNTFSを持っています。私はintについて知っています。私はこのケースで過大になる可能性がある変数に長い間使っています。 – bluebyte

+0

それは本当に説明ではありません。 c標準では、8バイト以上の型を必要とするため、それらの関数の1つを使用して関数を追加できます。また、32MBを超えるファイルシステムは存在しないので、値が大きすぎるという問題はすでに存在しています。 – Voo

+0

@Voo:履歴ファイルシステムがない限り、この問題は_常に存在しています。かつては無限大サイズのファイルを許可していました。 –

1

Win32では_lseeki64()、* nixではlseek64()という関数があります。しかし、iostreamライブラリはそれらを直接ラップしません。何らかの理由でファイル記述子を取得し、バッファリングについて何かしなければなりません。大きなファイルにアクセスするための

+0

実際にプラットフォーム固有のコードを使用している場合は、Windows上で 'OVERLAPPED'構造の'(Write | Read)ファイル 'を使うことができます。これは8byteのオフセットをサポートしていますが、4GBを片方だけ書き込むことができます。私はPOSIXで定義されたどこかの同様の快適な関数があると仮定します。 – Voo

関連する問題