Soru c içindeki bir diziye bir metin dosyası okuma


Bir metin dosyasını dinamik tek boyutlu bir diziye okumada en verimli yöntem ne olurdu? Her okunan ardı sonra aptalca görünüyor, her okunan çizgiden sonra daha iyi görünmüyor. Tüm dosyayı diziye okumak istiyorum. Nasıl yapardın?


18
2018-01-04 12:57


Menşei


Ne yapmak istediğinizi yanlış düşünebilirim: Tüm dosyayı büyük bir arabelleğe okumak mı yoksa her satır için bir girişe sahip bir dizi mi istiyorsunuz? - Christoph


Cevaplar:


Tam olarak ne istediğini anlamıyorum. Dosyayı aşamalı olarak işlemek, ondan bir satır okumak, sonra bırakmak ve bir sonraki süreci işlemek mi istiyorsunuz? Veya tüm dosyayı bir tamponda okumak ister misiniz? Eğer ikincisini istiyorsanız, bunun uygun olduğunu düşünüyorum (dosyanın mevcut olup olmadığını ve yeterli bellek olup olmadığını gerçek kodda malloc ve fopen için NULL dönüşünü kontrol edin):

FILE *f = fopen("text.txt", "rb");
fseek(f, 0, SEEK_END);
long pos = ftell(f);
fseek(f, 0, SEEK_SET);

char *bytes = malloc(pos);
fread(bytes, pos, 1, f);
fclose(f);

hexdump(bytes); // do some stuff with it
free(bytes); // free allocated memory

25
2018-01-04 13:04



Evet, bu benim davam için geçerli. Ben her okunan char sonra realloc kullanarak, her okunduğunda \ n (diziyi uzatmak için) benzer şekilde, çok verimsiz görünüyordu. - diminish
harika, sana yardım ettiğine sevindim - Johannes Schaub - litb
merhaba, aradaki fark nedir? (pos yerine 100 kullanacağımızı varsayalım) char * bytes = malloc (100 * sizeof (char)); ve yazdığınız satırın üstünde char * bytes = malloc (100); ikinci soru şu ki dosyamda 180205962 karakter varsa ne olur? Dosyayı okumak için yukarıdaki yol verimli olacak mı? - asel
@asel, ilk soru: sizeof(char) 1 olarak tanımlanmıştır, bu yüzden fark yoktur. İkinci soru: hayır, muhtemelen bunu aşamalı olarak okumalısınız (örneğin, satır satır veya başka bir parçalı yöntem). Aksi halde, hafızanız hızla tükenecektir. - Johannes Schaub - litb
Dosyanın boyutunu almak için fseek / ftell kullanmak güvensizdir. Bunun neden ve nasıl güvenli bir şekilde yapılacağı için bu CERT referansına bakın: securecoding.cert.org/confluence/display/seccode/... - Bryan


Eğer mmap (2) Sisteminizde kullanılabilir, dosyayı açabilir ve belleğe eşleyebilirsiniz. Bu şekilde, tahsis edecek bir hafızanız yok, hatta dosyayı okumak zorunda değilsiniz, sistem bunu yapacak. Boyutu almak için fseek () trick litb kullanabilirsiniz.

void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset);

DÜZENLEKullanmalısın lseek() dosyanın boyutunu elde etmek.

int fd = open("filename", O_RDONLY);
int nbytes = lseek(fd, 0, SEEK_END);
void *content = mmap(NULL, nbytes, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);

13
2018-01-04 14:21



@saffsd, düzeltmek için yeterli temsilciniz var, burada nasıl çalıştığını biliyorsunuz. - philant
Bu, sabit ve silinmiş yorum unuttu. - saffsd
Dosya boyutunu elde etmek için muhtemelen daha idiomatik bir yol kullanmaktır fstat(2) fonksiyon: struct stat S; fstat(fd, &S);, sonra int nbytes = S.st_size dosya sisteminden, dosya sisteminden herhangi bir dosyaya gerek duymadan, bayt cinsinden dosya boyutudır (bu, yukarıdaki gibi aynı sonucu elde edersiniz; büyük ölçüde eksiksizlik için bahsederim). - Norman Gray


ISO C kullanmak istiyorsanız, bu işlev.

Litb'nin cevabı, bazı hatalarla dolu ...


1
2018-01-04 17:16