遍历内存读取值

发布于 2024-12-28 20:02:48 字数 1011 浏览 1 评论 0原文

我有将文本文件读入内存的当前代码:

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);
}

我知道必须有更好/更安全的方法来做到这一点。

I have the current code that readings a text file into memory:

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;

Now i have code that iterates over it. If the line starts with 'v' it reads the 3 preceding float values, and same with if it starts with 'n', but into different arrays.

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);
}

I know there must be a better/safer way to do this.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

忆梦 2025-01-04 20:02:49

我假设你那里有一个文本文件。这可以做得更简单。首先,不要以二进制模式打开文件,而只是按行读取。以下是一个可能的实现:

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));

I assume you have a text-file there. This can be done a lot simpler. First, don't open the file in binary-mode, and simply read linewise. The following is a possible implementation:

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++; 
        }
    }
}

This code assumes that lines starting with 'v' are well-formed. You can use it like this:

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));
云朵有点甜 2025-01-04 20:02:49

如果您的系统支持(即任何类似 *nix 的系统),请使用 mmap。这将(很快)为您提供文件内容的 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)

Use mmap if your system supports it (i.e. any *nix-like system). This will (very quickly) give you a char* to the file contents. If your file is big, this works great as it uses the virtual memory system to cache everything for you - i.e you don't have to wait while all the data is copied around. The mmap function returns instantly and the relevant section of virtual memory is already mapped to the your file.

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);

Finally, memcmp seems a bit pointless with a length of 1. Why not just to if(*p=='v') instead of if(memcmp(p, "v", 1) == 0)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文