2017-04-09 90 views
-2

我有一个包含浮点数的大文件,我想阅读它们。快速双文件读取C

52.881 49.779 21.641 37.230 23.417 7.506 120.190 1.240 79.167 82.397 126.502 47.377 112.583 124.590 103.339 5.821 24.566 38.916 42.576 

这只是文件的开始。它有1000万个数字。

我得到了这段代码,但我不知道如何打印数字。

#include <stdio.h> 
#include <stdlib.h> 
#include <err.h> 
#include <fcntl.h> 
#include <sysexits.h> 
#include <unistd.h> 

int main() 
{ 
    int fd; 
    size_t bytes_read, bytes_expected = 1000000*sizeof(double); 
    double *data; 
    char *infile = "file.dat"; 

    if ((fd = open(infile,O_RDONLY)) < 0) 
     err(EX_NOINPUT, "%s", infile); 

    if ((data = malloc(bytes_expected)) == NULL) 
     err(EX_OSERR, "data malloc"); 

    bytes_read = read(fd, data, bytes_expected); 

    if (bytes_read != bytes_expected) 
     err(EX_DATAERR, "Read only %d of %d bytes", 
     bytes_read, bytes_expected); 

    /* print all */ 

    free(data); 

    exit(EX_OK); 
} 
+4

我不需要读你的代码来解决问题'100000000 * sizeof(double)',为什么这个值?为什么SOOOOO巨大?此外,出于多种原因,'bytes_read'不一定等于'bytes_expected',请张贴一些文件的内容。 –

+0

只是一个例子。我可以把它降低。 – zaig

+0

当您打开文件时,您是否看到垃圾字符或格式化的十进制数字? – anonymoose

回答

2

您正试图读取文本文件,如果数据是二进制的,所以你会读一些字节,但存放在数组中的double值不会是你想从文件中读取值,你可以这样做

FILE *file; 
double *array; 
size_t count; 
const char *infile = "file.dat"; 

file = fopen(infile, "r"); 
if (file == NULL) 
    return -1; 
count = 0; 
while (fscanf(file, "%*lf") == 1) 
    count += 1; 
rewind(file); 
array = malloc(count * sizeof(*array)); 
if (array == NULL) { 
    fprintf(stderr, "cannot allocate %zu bytes!\n", count * sizeof(*array)); 
    fclose(file); 
    return -1; 
} 
// Read the values into the array 
for (size_t i = 0; i < count; ++i) { 
    fscanf(file, "%lf", &array[i]); 
} 
// Print the array 
for (size_t i = 0; i < count; ++i) { 
    fprintf(stdout, "%f\n", array[i]); 
} 
// Release memory 
free(array); 
+0

这是我的第一个方法,但我想尝试一些可能更快的方法 – zaig

+2

由于问题的标题带有“* fast *”这个词,我倾向于争辩说,为了计算数字(第一遍),可能会更快地计算空格,但要做一个完整的双重扫描。 – alk

+1

@zaig:如果你有文本(也就是'char's)并且想要'double's,那么需要完成转换工作。这不是免费的。这不会在0s神奇地发生。 – alk

-1

既然你想要一个快速的解决方案,也许你必须牺牲内存。
阅读文件的更快方式是二进制形式。
因此,我会用有效的方法获得文件大小,然后我会相应地分配内存,
与上传整个文件到内存的想法。
在那里,由于内存读取速度快于文件读取速度,因此可以使用sscanf(...)快速读取数据。
我们也可以看到,每一个浮点数
需求至少3个字符将被存储在一个文本文件:

  • 1字符的点('.'
  • 1焦炭一些数字,
  • 和1个字符用于 用于从 文件中将值与其继承者分离的空间('')。

因此,文件大小除以3将是双精度数组大小的上限。

#include <stdio.h> 
int main(void) { 
    char *filename = "file.dat"; 
    FILE *F = fopen(filename, "rb"); 
    fseek(F, 0L, SEEK_END); 
    long int filesize = ftell(F); 
    rewind(F); 
    char *data = malloc(filesize+1); 
    fread(data, filesize, 1, F); 
    data[filesize] = '\0';        // End of string, just in case 
    fclose(F); 

    // The desired data will be stored in array: 
    double *array = malloc(sizeof(double) * filesize/3); 

    int ret; 
    int n;  // represents the no chars in a sscanf(...) reading 
    double *a = array; 
    while (1) {  // Infinite loop... 
    ret = sscanf(data, " %lg%n", a, &n); 
    if (ret == EOF) break; // <<---- EXIT POINT of the loop 
    a++; 
    data += n; 
    } 

    long int array_size = a - array + 1; 
}