Chciałbym znaleźć pierwsze wystąpienie ciągu ANSI w pliku binarnym przy użyciu C++.

Wiem, że klasa string ma przydatną funkcję wyszukiwania, ale nie wiem, jak jej użyć, jeśli plik jest duży, powiedzmy 5-10 MB.

Czy muszę najpierw skopiować cały plik do ciągu w pamięci? Jeśli tak, skąd mogę mieć pewność, że żaden ze znaków binarnych nie zostanie uszkodzony podczas kopiowania?

A może jest na to wydajniejszy sposób, bez konieczności kopiowania go do ciągu znaków?

1
hyperknot 23 czerwiec 2011, 03:41
 – 
GWW
23 czerwiec 2011, 03:43
Zadałeś już zasadniczo to samo pytanie
 – 
GWW
23 czerwiec 2011, 03:44
1
Możesz użyć pliku mapowanego w pamięci. Możesz użyć Boost: boost.org /doc/libs/1_46_1/libs/iostreams/doc/classes/… lub StlSoft: stlsoft.org/doc-1.9/…
 – 
Pablo
23 czerwiec 2011, 03:45
@GWW: Powiedziano mi, że powinienem podzielić to na kilka pytań.
 – 
hyperknot
23 czerwiec 2011, 03:46
1
@GWW: przy drugim pytaniu inni powiedzieli mu, że powinien podzielić je na kilka pytań, i przy drugim pytaniu, które nawet połączył z tym.
 – 
Loduwijk
23 czerwiec 2011, 03:52

3 odpowiedzi

Najlepsza odpowiedź

Czy muszę najpierw skopiować cały plik do ciągu w pamięci?

Nie.

A może jest na to wydajniejszy sposób, bez konieczności kopiowania go do ciągu?

Oczywiście; otwórz plik za pomocą std::ifstream (otwórz w < a href="http://en.cppreference.com/w/cpp/io/ios_base/openmode" rel="nofollow">tryb binarny zamiast trybu tekstowego), utwórz parę multi_pass iteratory ( z Boost.Spirit) wokół strumienia, a następnie wyszukaj ciąg za pomocą std::search.

5
ildjarn 23 czerwiec 2011, 08:41
Dobra odpowiedź! Nie wyobrażam sobie bardziej efektywnego sposobu. Chciałem zaoferować użycie funkcji fstream::read(), a następnie ręczne wyszukiwanie w buforze odczytu. Ale moja droga jest trudniejsza.
 – 
George Gaál
23 czerwiec 2011, 03:51
Fajne rozwiązanie. Jedynym potencjalnym problemem, jaki widzę, jest to, że spowoduje to odczytanie pliku w kawałkach o rozmiarze równym rozmiarowi bufora strumienia. Czy można dostosować ten rozmiar bufora? Bardziej efektywne może być jednoczesne czytanie większych fragmentów.
 – 
HighCommander4
23 czerwiec 2011, 03:52
: Dobre pytanie. Możliwe, że dostarczysz osobno skonstruowaną instancję std::filebuf, ale szczerze mówiąc, iostreams nie są moją specjalizacją.
 – 
ildjarn
23 czerwiec 2011, 03:56
1
Wywołuje to niezdefiniowane zachowanie, ponieważ std::search oczekuje iteratorów do przodu lub lepszych, a std::istream_iterator jest iteratorem wejściowym. Zobacz moje pytanie na ten temat tutaj.
 – 
Benjamin Lindley
23 czerwiec 2011, 08:33
: Całkowicie poprawny, nie wiem, jak zapomniałem o tym pisząc tę ​​odpowiedź. >_> Zredagowano odpowiedź.
 – 
ildjarn
23 czerwiec 2011, 08:42

Przede wszystkim nie przejmuj się skorumpowanymi postaciami. (Ale nie zapomnij też otworzyć pliku w trybie binarnym!) Teraz załóżmy, że wyszukiwany ciąg ma n znaków. Następnie możesz przeszukiwać cały plik blok na raz, o ile zachowasz ostatnie n-1 znaków każdego bloku przed następnym blokiem. W ten sposób nie stracisz dopasowań, które występują poza granicami bloków. Możesz więc użyć tej przydatnej funkcji wyszukiwania bez konieczności jednoczesnego wczytywania całego pliku do pamięci.

2
TonyK 23 czerwiec 2011, 03:46
2
Myślę, że zsero powinno określać, czy istnieje limit długości celu. Jeśli szuka zawartości pliku tekstowego jako celu, szukając tej zawartości w innym pliku, sam cel może z łatwością być dłuższy niż kilka bloków, w którym to przypadku zawsze się nie powiedzie. Jeśli może zagwarantować, że cel jest mały, to jest to dobra optymalizacja.
 – 
Loduwijk
23 czerwiec 2011, 03:56

Jeśli możesz zmapować plik do pamięci, możesz uniknąć kopii.

0
lhf 23 czerwiec 2011, 03:46