2013-04-11 5 views
7

W C++ mamy metodę wyszukiwania tekstu w pliku. Działa poprzez odczytanie pliku do zmiennej i użycie polecenia strstr. Ale pojawiły się kłopoty, gdy plik stał się bardzo duży.Błąd z find.exe?

Myślałem, że mogę rozwiązać ten problem, wywołując find.exe za pomocą _popen. Działa znaleźć, chyba że te warunki są spełnione:

  • Plik jest typu Unicode (BOM = fffe)
  • Plik jest dokładnie 4096 bajty
  • Tekst szukasz jest ostatnim tekst w pliku

Aby odtworzyć, można to zrobić:

  1. Otwórz notatnik
  2. Insert 2046 X. wówczas A przy końcu
  3. Zapisz jako test.txt, kodowanie = "Unicode"
  4. Sprawdź, czy plik jest dokładnie 4096 bajty
  5. Otwórz wiersz polecenia i wpisać: znaleźć "A"/c test2.txt -> No uderza

próbowałem też tak:

  • Dodaj lub usuń X, a otrzymasz trafienie (plik nie jest 4096 bajtów już)
  • Zapisz jako UTF-8 (i dodaj tyle X, aby plik miał ponownie 4096 bajtów), a otrzymasz trafienie
  • Wyszukaj coś w środku pliku (plik wciąż unicode i 4096 bajtów), a otrzymasz Cios.

Czy to błąd, czy jest coś, czego mi brakuje?

+2

To jest interesujące. Czy próbowałeś z innymi wielokrotnościami 1024? Lub 4096? To znaczy. 8192 bajtów? –

+0

1024 i 2048 jest w porządku, ale kończy się niepowodzeniem na 8192. –

+0

Wow - to nieprzyjemny błąd :(To również nie powiedzie się, jeśli rozmiar pliku wynosi 8192 bajtów. Gdy szukasz znaku w środku, znajduje on " line ", ale zauważ, że brakuje ostatniego znaku na wyjściu! Otrzymujesz X'es ale nie A's – dbenham

Odpowiedz

4

Bardzo interesujący błąd.

To pytanie spowodowało, że zrobiłem kilka eksperymentów na XP i Win 7 - zachowania są różne.

XP

ANSI - tu nie można odczytać przeszłe 1023 znaków (1023 bajtów) na jednej linii. ZNAJDŹ można dopasować linię, która przekracza 1023 znaki, o ile łańcuch wyszukiwania pasuje przed 1024-tą. Dopasowany wydruk linii jest obcięty po 1023 znakach.

Unicode - FIND nie może odczytać ostatnich 1024 znaków (2048 bajtów) w jednym wierszu. ZNAJDŹ można dopasować linię, która przekracza 1024 znaki, o ile łańcuch wyszukiwania pasuje przed 1025-tą. Dopasowany wydruk linii jest obcięty po 1024 znakach.

Uważam, że to bardzo dziwne, że ograniczenia linii dla Unicode i ANSI na XP nie są tą samą liczbą bajtów, ani nie jest to prosta wielokrotność. Limit Unicode wyrażony jako bajty jest 2-krotnością limitu dla ANSI plus 1.

Uwaga: obcinanie pasujących długich linii powoduje również obcięcie znaku nowej linii, aby następna zgodna linia pojawiła się w dołączeniu do poprzedniego wiersza.Możesz powiedzieć, że jest to nowa linia, jeśli używasz opcji/N.

Okno 7

ANSI - Nie znalazłem ograniczenie do max długości linii, które mogą być przeszukiwane, (choć nie bardzo się starają). Każda pasująca linia, która przekracza 4095 znaków (4095 bajtów) jest obcięta po 4095 znakach. FIND może z powodzeniem przeszukać ponad 4095 znaków w linii, po prostu nie może wyświetlić wszystkich z nich.

Unicode - Nie znalazłem limitu maksymalnej długości linii, która może być przeszukana (chociaż nie próbowałem bardzo mocno). Każda pasująca linia, która przekracza 2047 znaków (4094 bajtów), jest skracana po 2047 znakach. FIND może pomyślnie przeszukać 2047 znaków w linii, po prostu nie może wyświetlić wszystkich.

Ponieważ długości bajtów w Unicode są zawsze wielokrotnością 2, a maksymalna wyświetlana długość ANSI jest liczbą nieparzystą, ma sens, że maksymalna wyświetlana długość linii w bajtach jest o jeden mniej dla kodu Unicode niż dla ANSI.

Ale jest też dziwny błąd Unicode. Jeśli długość pliku Unicode jest dokładną wielokrotnością 4096 bajtów, to ostatniego znaku nie można wyszukać ani wydrukować. Nie ma znaczenia, czy plik zawiera pojedynczą linię, czy wiele linii. To zależy tylko od całkowitej długości pliku.

Uważam za interesujące, że wielokrotność błędu 4096 mieści się w jednej z maksymalnie zadawanych długości linii (w bajtach). Ale nie wiem, czy istnieje związek między tymi zachowaniami, czy jest to po prostu zbieg okoliczności.

Uwaga: obcinanie pasujących długich linii powoduje również obcięcie wszystkich znaków nowej linii, więc następna zgodna linia zostanie dodana do poprzedniego wiersza. Możesz powiedzieć, że jest to nowa linia, jeśli używasz opcji/N.

+0

Bardzo interesujący błąd! – Patashu