读取文件由浮点数和C ++中的mmap()组成

时间:2018-02-06 03:00:35

标签: c++ scanf mmap

我试图读取一个文件,包含100,000个浮点数,如 0.12345678 -0.1234567 ,用c ++中的空格分隔。我用 fscanf()来读取文件,代码是这样的:

FILE *fid = fopen("testingfile.txt", "r");
if (fid == NULL)
    return false;

float v;

for (int i = 0; i < 100000000; i++)
    fscanf(fid, "%f", &v);

fclose(fid);

该文件的大小为1199999988字节,并使用 fscanf()完成 18秒 以完成阅读。因此,我想使用 mmap()来加快阅读速度,代码如下:

#define FILEPATH "testingfile.txt"

char text[10] = {'\0'};
struct stat s;
int status = stat(FILEPATH, &s);
int fd = open(FILEPATH, O_RDONLY);
if (fd == -1)
{
    perror("Error opening file for reading");
    return 0;
}

char *map = (char *)mmap(NULL, s.st_size, PROT_READ, MAP_SHARED, fd, 0);
close(fd);

if (map == MAP_FAILED)
{
    perror("Error mmapping the file");
    return 0;
}

for (int i = 0,j=0; i < s.st_size; i++)
{
    if (isspace(map[i]))
    {
        text[j] = '\0';
        j = 0;
        float v = atof(text);
        for (int j = 0; j < 10; j++)
            text[j] = '\0';
        continue;
    }
    text[j] = map[i];
    j++;

}
if (munmap(map, s.st_size) == -1)
{
    return 0;
}

但是,仍然需要 14.5秒 才能完成阅读。我发现最耗时的部分是将数组转换为浮点数,其消耗大约 10秒

所以我有三个问题:

  1. 有什么方法可以直接读取float而不是char或

  2. 有没有更好的方法将char数组转换为float

  3. fscanf如何识别浮点值并读取它,这比atof()快得多。

  4. 提前致谢!

1 个答案:

答案 0 :(得分:0)

根据给出的建议,以下是此问题的两种可能解决方案:

第一种方法有点“愚蠢”。由于存储浮点数值的格式是已知的,因此可以在不使用atof()的情况下轻松完成从char数组到float数的转换。 删除atof()后,只需 8秒 即可完成同一文件的阅读和转换。

第二种方法是更改​​文件中浮点数的存储格式(由Jeremy Friesner建议)。浮点数值以二进制格式存储,因此不需要mmap()的转换部分。代码变成这样:

#define FILEPATH "myfile.bin"

int main()
{
int start_s = clock();
struct stat s;
int status = stat(FILEPATH, &s);

int fd = open(FILEPATH, O_RDONLY);
if (fd == -1)
{
    perror("Error opening file for reading");
    return 0;
}

float *map = (float *)mmap(NULL, s.st_size, PROT_READ, MAP_SHARED, fd, 0);
close(fd);

if (map == MAP_FAILED)
{
    perror("Error mmapping the file");
    return 0;
}

for (int i = 0; i < s.st_size / 4; i++)
{
    float v = map[i];
}

if (munmap(map, s.st_size) == -1)
{
    return 0;
}
}

这将大大减少以相同大小读取文件所需的时间。