• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

question-closed [C] Czytanie dużego pliku linijka po linijce fgets()

Object Storage Arubacloud
0 głosów
378 wizyt
pytanie zadane 27 stycznia 2022 w C i C++ przez Marak123 Stary wyjadacz (11,190 p.)
zamknięte 30 stycznia 2022 przez Marak123

Witam smiley

Mam prosty kodzik napisany w "C" który odczytuje duży plik tekstowy linijka po linijce i wypisuje te linijki na ekran(dla przykładu), ale gdy czyta te linijki to przy 6701 linijce się zatrzymuje mimo że plik na pewno jest dłuższy bo sprawdzałem w programie klogg. Po wyświetleniu pliku w tym programie zauważyłem ze pętla zakończa działanie na linijce która jest długa ma ok 250 znaków tylko ze te znaki są trochę dziwne prawdopodobnie złe kodowanie ale nie ważne bo linijki poprzednie które też miały takie znaki normalnie czytała funkcja fgets() ustawiona na 1024 znaki a przy tej linijce zawiesza się funkcja fgets() pokazując za każdym razem null mimo ze następna linijka już jest normalna. 

#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

int main(void)
{
   FILE* fp = fopen("./../file.txt", "r");
   enum {
      BUF_SIZE = 10000000
   };
   char *buffer = (char*)malloc(BUF_SIZE);

   if (fp == NULL)
   {
      printf("Error opening file!\n");
      exit(1);
   }


    int counter = 0;

   clock_t start = clock();
   while (fgets(buffer, BUF_SIZE, fp) != NULL)
   {
      printf("Cos: %s \n", buffer);
      // printf("%s", buffer);
      counter++;
   }
   free(buffer);

   clock_t end = clock();
   double time_spent = (double)(end - start) / CLOCKS_PER_SEC;
   printf("Time: %f\n", time_spent);

   printf("Counter: %d\n", counter);
   printf("End of file\n");

   fclose(fp);
}

Wie ktoś dlaczego tak się może dziać i jak zabezpieczyć program aby czytało kolejne linijki a nie za się zawieszało i zwracało cały czas null? 

Myślałem ze jest to problem z długością wiersza ale użyłem malloc() jak widać w kodzie ale nadal to samo.

komentarz zamknięcia: Dzięki za pomoc. Problem rozwiązany. Kod w komentarzu
komentarz 29 stycznia 2022 przez Marak123 Stary wyjadacz (11,190 p.)

Ok dzięki zrobiłem skrypt z czytaniem całych bloków 1024 bajty i liczby nowe linie(\n) w bloku(tablicy unsigned char). Czyta bloki sposobem binarnym fread() potem pętla for po tablicy bufora i zliczanie znaku za znakiem znaku nowej linii. Dzięki za podpowiedzi, plik 8.5mld linijek zlicza w ok.5 min w porównaniu ze skryptami zrobionymi wcześniej które liczyły to w 30 min jak np. w python skrypt to to jest bardzo duże przyśpieszenie.

Chcę zrobić teraz multiprocessing czyli ze będzie funkcja która się odpali w osobnym procesie i będzie np. liczyć ilość powtórzeń znaku nowej linii w przekazanym bloku danych. Jako ze działam na Windows to chcę to zrobić za pomocą CreateProcess() tylko ze z tego co widzę to odpalić muszę inny skomplikowany już program a nie tak jak to było w python samą funkcje, jakoś spróbuję to ogarnąć. Dzięki za pomoc.smileyyes

Kod do zliczania ilość znaków nowej linii w pliku:

#include <stdio.h>
#include <time.h>
#include <unistd.h>

#define BUF_SIZE 10240
#define FILENAME_FILE "C:\\Users\\user\\Desktop\\file.txt"

int main(void)
{

   FILE* fp = fopen(FILENAME_FILE, "rb");
   unsigned char buffer[BUF_SIZE];// = (unsigned char*)malloc(BUF_SIZE * sizeof(unsigned char));

   if (fp == NULL)
   {
      printf("Error opening file!\n");
      exit(1);
   }

   unsigned long long int counter = 0;

   clock_t start = clock();
   size_t loadedItem = 0;

   while((loadedItem = fread(buffer, sizeof(unsigned char), BUF_SIZE, fp)) != 0){
      for(int i = 0; i < loadedItem; i++)
         if((int)buffer[i] == 10)
            counter++;
   }

   clock_t end = clock();
   double time_spent = (double)(end - start) / CLOCKS_PER_SEC;

   printf("Filename: %s \n", FILENAME_FILE);
   printf("Time: %f\n", time_spent);

   printf("Counter: %llu\n", counter);
   printf("\nEnd of file\n");

   fclose(fp);
   system("pause");
}

 

1
komentarz 30 stycznia 2022 przez Oscar Nałogowiec (29,320 p.)
Rozróżniaj wątek od procesu - proces to oddzielny program z własną pamięcią, wątek to "taki drugi procesor" wykonujący ten sam kod w tej samej pamięci. W drugim przypadku masz wspólną pamięć i zasadniczo uruchamiasz którąś z funkcji.
komentarz 30 stycznia 2022 przez Marak123 Stary wyjadacz (11,190 p.)
Dzięki za informacje ale próbuję właśnie zrobić oddzielne procesy bo nie wiem czy dobrze myślę ale parę wątków jest bez sensowne ponieważ wykonywanie procesów będzie się zazębiał czyli raz będzie wykonywało się jedno zadanie wątku 1 a raz wątku 2 potem od nowa wątek 1 i potem wątek 2. Dobrze myślę??  

A procesy to chyba działają jednocześnie. Pewnie gadam głupoty.

Czy wątek będzie lepszym rozwiązaniem czy jednak szybciej zliczą się znaki używając osobnych procesów??
1
komentarz 30 stycznia 2022 przez Oscar Nałogowiec (29,320 p.)
Wątki też wykonują się w sposób asynchroniczny, nie ma żadnej zależności co do kolejności wykonywania, nawet wręcz instrukcje różnych wątków mogą się wykonywać zupełnie jednocześnie, szczególnie w wielordzeniowych architekturach.

W wątkach masz wspólną pamięć - zmienne (głównie globalne) różnych wątków to są te same zmienne - jak jeden wątek coś zmieni w takiej zmiennej, to i drugiemu się zmieni. Powoduje to łatwą komunikację, ale też powoduje wiele kłopotliwych sytuacji związanych z nieokreślonością kolejności wykonywania instrukcji. Te wszystkie semafory, mutexy, kolejki, zmienne warunkowe itp. Dwa oddzielne procesy wykonują się całkowicie niezależnie z wyjątkiem jawnie zaprogramowanych mechanizmów współpracy. Oczywiście pliki na dysku są, tak czy inaczej, wspólne.
komentarz 30 stycznia 2022 przez Marak123 Stary wyjadacz (11,190 p.)

Ok dzięki za wyjaśnienie czyli może lepszym wyborem będą osobne wątki a nie procesy.
Dziękismiley

Podobne pytania

0 głosów
0 odpowiedzi 145 wizyt
pytanie zadane 8 września 2022 w C i C++ przez benny13 Obywatel (1,150 p.)
0 głosów
1 odpowiedź 1,594 wizyt
pytanie zadane 28 marca 2017 w C i C++ przez Kamil Duljas Użytkownik (990 p.)
0 głosów
2 odpowiedzi 692 wizyt
pytanie zadane 29 listopada 2017 w C i C++ przez Krystek102 Bywalec (2,440 p.)

92,576 zapytań

141,426 odpowiedzi

319,652 komentarzy

61,961 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...