2017-04-09 92 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; 
}