Сохранить большой вектор чисел на жесткий диск - PullRequest
4 голосов
/ 28 ноября 2011

Я выделил большой кусок непрерывных байтов в оперативной памяти, используя вектор типа unsigned short.

vector<unsigned short> testDump(204800000);

for(int k = 0; k<204800000; k++)
    testDump[k] = 9; \\ This is different in my real program

Теперь я хочу сохранить этот вектор на моем жестком диске.Как и какой самый быстрый способ сделать это?Размер данных довольно большой (~ 1/2 ГБ).Я попробовал следующее:

ofstream outfile("allMyNumbers.txt", ios::out | ios::binary);
outfile.write(&testDump[0], testDump.size());

Но я получаю следующую ошибку:

cannot convert parameter 1 from 'unsigned short *' to 'const char *'

Какой самый быстрый способ выполнить мою задачу - сохранить вектор в файлиспользуя самый быстрый подход?

* Платформа Windows 7.

Ответы [ 3 ]

3 голосов
/ 28 ноября 2011

Вы могли бы просто навести указатель.

outfile.write(reinterpret_cast<char*>(&testDump[0]), testDump.size() * sizeof(unsigned short));

Имейте в виду, что полученный файл отформатирован так, как это характерно для вашей конкретной платформы / реализации.Таким образом, вы не можете читать его обратно очевидным образом на несовместимом компьютере.

В Windows это даст 400-Мбайтный файл с каждой из 204800000 пар байтов, представляющих младший порядокunsigned short.

Это должно быть достаточно быстро.Мне трудно поверить, что ваша задача - сохранить данные «используя самый быстрый подход».Как кто-нибудь узнает, что ваш код действительно оптимален, что не существует другого кода, который бы делал это на одну наносекунду быстрее?И какой смысл предпринимать какие-либо дополнительные усилия, чтобы сбрасывать наносекунду?И так далее.

Конечно, может быть быстрее использовать алгоритм быстрой потоковой компрессии для уменьшения необходимого дискового пространства, так как операция, вероятно, будет связана с дисковым вводом / выводом.Но код будет гораздо более сложным, и от того, насколько сжимаемыми являются данные, зависит то, поможет ли он или нет.

3 голосов
/ 28 ноября 2011

Одним из методов, не зависящих от платформы, было бы использование ostream_iterator для типа, который содержит ваш векторный класс.Поскольку тип, содержащийся в вашем векторе, уже перегружен для operator<< для класса ostream, у вас не должно возникнуть проблем с созданием шаблона для класса ostream_iterator для вашего типа вектора.Затем вы бы объединили ostream_iterator с алгоритмом copy из STL, чтобы выполнить итерацию по вашему вектору и сериализовать необработанные байты в файл.Использование operator<< будет использовать намного больше данных, чем использование ofstream::write, который записывает необработанные двоичные данные на диск, но имеет преимущество в том, что данные сериализуются, что делает их независимо читаемыми на любой платформе.

Итакнапример:

vector<unsigned short> testDump(2048000000);
//...fill in your vector

ofstream outfile("allMyNumbers.txt", ios::out | ios::binary);

//tab-delinate the data
ostream_iterator<unsigned short> o_iter(outfile, "\t");
copy(testDump.begin(), testDump.end(), o_iter);
1 голос
/ 29 ноября 2011

Кросс-платформенный способ сериализации это будет просто зацикливаться на представлении с прямым порядком байтов для краткости и сбрасывать все шорты.Это позволило бы избежать раздувания данных ASCII в решении Джейсона и в то же время быть кроссплатформенным.

Итак, я бы просто сделал

ofstream outfile("allMyNumbers.data", ios::out | ios::binary);
for(int k = 0; k < testDump.size(); k++)
{
    unsigned short leData = htole16(testDump[k]);    
    outfile.write(&leData, sizeof(leData));
}

Реализация htole16 (host to little endianдля 16-битных целых чисел):

Для x86, x64:

unsigned short htole16(unsigned short x)
{
    return x;
}

Для машин с прямым порядком байтов, таких как Sparc / PowerPC (хотя ни один из них не запустит Windows 7)

unsigned short htole16(unsigned short x)
{
    return _byteswap_ushort(x);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...