Dietmar Kuehl said:
Steve said:
ifs.seekg(0,std::ios::end);
int len = ifs.tellg();
ifs.seekg(0,std::ios::beg);
char* buf = new char[len];
This is a pretty dangerous approach: there is actually no
portable approach to determine the number of characters in a
file except counting them, e.g. like this:
/**/ std::streamsize len = std::distance(
/**/ std::istreambuf_iterator<char>(ifs),
/**/ std::istreambuf_iterator<char>());
[snip]
Those methods has different behavior (see program below).
There are another methods with once more behavior?
Compiler g++ 3.4.1
// ====== foo.cpp : BEGIN ======
#include <cassert>
#include <string>
#include <iostream>
#include <fstream>
using namespace std;
// ------------------
#define TXT_FILE_NAME "foo.txt"
#define BIN_FILE_NAME "foo.bin"
enum OpenMode { BIN_MODE, TXT_MODE };
// -----------------
size_t get_filesize_via_fseek_ftell (
const char * const filename_i,
OpenMode mode_i
)
{
FILE* fp = NULL;
assert ((mode_i == TXT_MODE) || (mode_i == BIN_MODE));
fp = fopen(filename_i, ((mode_i == TXT_MODE) ? "r" : "rb"));
assert (fp);
int rc = fseek(fp, 0, SEEK_END);
assert (rc == 0);
const size_t ret_filesize (ftell(fp));
rc = fclose(fp);
assert (rc == 0);
return ret_filesize;
}
// -----------------
size_t get_filesize_via_seekg_tellg (
const char * const filename_i,
OpenMode mode_i
)
{
ifstream fs;
assert ((mode_i == TXT_MODE) || (mode_i == BIN_MODE));
if (mode_i == TXT_MODE) fs.open (filename_i);
else fs.open (filename_i, ios::binary);
assert (fs);
assert (fs.is_open());
fs.seekg(0, ios::beg);
const ios:
os_type start_pos = fs.tellg();
fs.seekg(0, ios::end);
const ios:
os_type end_pos = fs.tellg();
const size_t ret_filesize (static_cast<size_t>(end_pos - start_pos));
fs.close();
assert (!fs.is_open());
return ret_filesize;
}
// -----------------
size_t get_filesize_via_distance (
const char * const filename_i,
OpenMode mode_i
)
{
ifstream fs;
assert ((mode_i == TXT_MODE) || (mode_i == BIN_MODE));
if (mode_i == TXT_MODE) fs.open (filename_i);
else fs.open (filename_i, ios::binary);
assert (fs);
assert (fs.is_open());
const size_t ret_filesize (static_cast<size_t>(distance(
istreambuf_iterator<char>(fs),
istreambuf_iterator<char>()
)
)
);
fs.close();
assert (!fs.is_open());
return ret_filesize;
}
// -----------------
void create_file (
const string& data_i,
const char * const filename_i,
OpenMode mode_i
)
{
remove (filename_i);
ofstream fs;
assert ((mode_i == TXT_MODE) || (mode_i == BIN_MODE));
if (mode_i == TXT_MODE) fs.open (filename_i);
else fs.open (filename_i, ios::binary);
assert (fs);
assert (fs.is_open());
fs << data_i;
fs.close();
assert (!fs.is_open());
}
int main ()
{
const char data[] = "\n";
create_file (data, TXT_FILE_NAME, TXT_MODE);
create_file (data, BIN_FILE_NAME, BIN_MODE);
// -------------------------------------------
cout << endl;
cout << "--- get_filesize_via_fseek_ftell" << endl;
cout << "Created in TXT mode, read in TXT mode: "
<< get_filesize_via_fseek_ftell (TXT_FILE_NAME, TXT_MODE)
<< endl;
cout << "Created in BIN mode, read in BIN mode: "
<< get_filesize_via_fseek_ftell (BIN_FILE_NAME, BIN_MODE)
<< endl;
cout << "Created in TXT mode, read in BIN mode: "
<< get_filesize_via_fseek_ftell (TXT_FILE_NAME, BIN_MODE)
<< endl;
cout << "Created in BIN mode, read in TXT mode: "
<< get_filesize_via_fseek_ftell (BIN_FILE_NAME, TXT_MODE)
<< endl;
// -------------------------------------------
cout << endl;
cout << "--- get_filesize_via_seekg_tellg" << endl;
cout << "Created in TXT mode, read in TXT mode: "
<< get_filesize_via_seekg_tellg (TXT_FILE_NAME, TXT_MODE)
<< endl;
cout << "Created in BIN mode, read in BIN mode: "
<< get_filesize_via_seekg_tellg (BIN_FILE_NAME, BIN_MODE)
<< endl;
cout << "Created in TXT mode, read in BIN mode: "
<< get_filesize_via_seekg_tellg (TXT_FILE_NAME, BIN_MODE) << endl;
cout << "Created in BIN mode, read in TXT mode: "
<< get_filesize_via_seekg_tellg (BIN_FILE_NAME, TXT_MODE)
<< endl;
// -------------------------------------------
cout << endl;
cout << "--- get_filesize_via_distance" << endl;
cout << "Created in TXT mode, read in TXT mode: "
<< get_filesize_via_distance (TXT_FILE_NAME, TXT_MODE)
<< endl;
cout << "Created in BIN mode, read in BIN mode: "
<< get_filesize_via_distance (BIN_FILE_NAME, BIN_MODE)
<< endl;
cout << "Created in TXT mode, read in BIN mode: "
<< get_filesize_via_distance (TXT_FILE_NAME, BIN_MODE)
<< endl;
cout << "Created in BIN mode, read in TXT mode: "
<< get_filesize_via_distance (BIN_FILE_NAME, TXT_MODE)
<< endl;
return 0;
}
// ====== foo.cpp : END ========
// ====== Run Log ========
--- get_filesize_via_fseek_ftell
Created in TXT mode, read in TXT mode: 2
Created in BIN mode, read in BIN mode: 1
Created in TXT mode, read in BIN mode: 2
Created in BIN mode, read in TXT mode: 1
--- get_filesize_via_seekg_tellg
Created in TXT mode, read in TXT mode: 2
Created in BIN mode, read in BIN mode: 1
Created in TXT mode, read in BIN mode: 2
Created in BIN mode, read in TXT mode: 1
--- get_filesize_via_distance
Created in TXT mode, read in TXT mode: 1
Created in BIN mode, read in BIN mode: 1
Created in TXT mode, read in BIN mode: 2
Created in BIN mode, read in TXT mode: 1
// =======================