перебирая память для чтения значений - PullRequest
0 голосов
/ 22 января 2012

У меня есть текущий код, который читает текстовый файл в память:

std::streampos fsize = 0;
std::ifstream file(fileName, std::ios::binary); // open file

if(!file.good()) {
    std::cout << "Error opening file";
    return 0;
}

// get length of file
file.seekg(0, ios::end);
fsize = file.tellg();

// allocate memory
char *memory = new char[fsize];

// read data as a block
file.seekg (0, ios::beg);
file.read (memory, fsize);

file.close(); // close file

return fsize;

Теперь у меня есть код, который перебирает его.Если строка начинается с 'v', она читает 3 предыдущих значения с плавающей запятой и то же самое с тем, что она начинается с 'n', но в разные массивы.

char* p = memory;       // pointer to start of memory
char* e = memory + fsize;   // pointer to end of memory

while (p != e) {
    if (memcmp(p, "v", 1) == 0) { 
        sscanf(p, "v %f %f %f", &a[vI], &b[vI], &c[vI]);
        vI++;
    } else if (memcmp(p, "n",  1) == 0) {
        sscanf(p, "v %f %f %f", &d[nI], &e[nI], &f[nI]);
        nI++;           
    while (*p++ != (char) 0x0A);
}

Я знаю, что должно быть лучше / безопаснееспособ сделать это.

Ответы [ 2 ]

1 голос
/ 23 января 2012

Используйте mmap , если ваша система поддерживает его (т.е. любая * nix-подобная система).Это (очень быстро) даст вам char* к содержимому файла.Если ваш файл большой, это прекрасно работает, поскольку он использует систему виртуальной памяти для кэширования всего за вас - то есть вам не нужно ждать, пока все данные будут скопированы.Функция mmap мгновенно возвращается, и соответствующий раздел виртуальной памяти уже сопоставлен с вашим файлом.

int fd = open(binaryRAWFileName, O_RDONLY);
... should do some error check to ensure fd != -1

// get the size of the file
struct stat sb;
if (fstat(fd, &sb) == -1) {
        ... there was an error with fstat
}

char * memory = mmap(NULL  // we don't care where the memory is
        , sb.st_size      // length of the file
        , PROT_READ   
        , MAP_PRIVATE
        , fd            // the file descriptor of course
        , 0);

Наконец, memcmp кажется немного бессмысленным с длиной 1. Почему бы не просто if(*p=='v') вместо if(memcmp(p, "v", 1) == 0)

1 голос
/ 22 января 2012

Полагаю, у вас есть текстовый файл.Это можно сделать намного проще.Во-первых, не открывайте файл в бинарном режиме, а просто прочитайте его так же.Ниже приведена возможная реализация:

template<class output_iterator>
void read_file(std::istream &input, output_iterator v1, output_iterator v2,
               output_iterator v1) {
    std::string line_buffer;

    while(std::getline(input, line_buffer)) { // read each line of text
        if(line_buffer[0] == 'v') {
            std::stringstream line_stream(line_buffer.substr(1)); // drop the 'v'
            // read three consecutive floats
            line_stream >> *v1++ >> *v2++ >> *v3++; 
        }
    }
}

В этом коде предполагается, что строки, начинающиеся с 'v', правильно сформированы.Вы можете использовать это так:

std::vector<float> values1, values2, values3;
std::fstream input_file(fileName);

read_file(input_file, std::back_inserter(values1), std::back_inserter(values2),
          std::back_inserter(values3));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...