Wprawdzie odpowiedź z wykrzyku jest zdecydowanie poprawna, ale często zwraca nieoczekiwane wyniki. Powodem tego jest to, że przynajmniej w moim systemie operacyjnym (Mac OSX 10.9.5), wielu edytorów tekstu kończy swoje pliki znakiem końca wiersza.
Na przykład, gdy otwieram vim wpisać tylko jeden znak 'a' (No Return), a następnie zapisz plik będzie teraz zawierać (w hex):
61 0A
Gdzie 61 to litera "a" i 0A to znak końca linii.
Oznacza to, że kod przez derpface zwróci pusty ciąg we wszystkich plikach utworzonych przez taki edytor tekstu.
Chociaż z pewnością mogę sobie wyobrazić przypadki, w których plik zakończony "linią końcową" powinien zwracać pusty ciąg, myślę, że ignorowanie ostatniego znaku końca wiersza byłoby bardziej odpowiednie w przypadku zwykłych plików tekstowych; jeśli plik zostanie zakończony znakiem "linii końcowej", zignorujemy go właściwie, a jeśli plik nie zostanie zakończony znakiem "linii końcowej", nie musimy go sprawdzać.
Mój kod do ignorowania ostatni znak pliku wejściowego jest:
#include <iostream>
#include <string>
#include <fstream>
#include <iomanip>
int main() {
std::string result = "";
std::ifstream fin("test.txt");
if(fin.is_open()) {
fin.seekg(0,std::ios_base::end); //Start at end of file
char ch = ' '; //Init ch not equal to '\n'
while(ch != '\n'){
fin.seekg(-2,std::ios_base::cur); //Two steps back, this means we
//will NOT check the last character
if((int)fin.tellg() <= 0){ //If passed the start of the file,
fin.seekg(0); //this is the start of the line
break;
}
fin.get(ch); //Check the next character
}
std::getline(fin,result);
fin.close();
std::cout << "final line length: " << result.size() <<std::endl;
std::cout << "final line character codes: ";
for(size_t i =0; i<result.size(); i++){
std::cout << std::hex << (int)result[i] << " ";
}
std::cout << std::endl;
std::cout << "final line: " << result <<std::endl;
}
return 0;
}
które wyjście będzie:
final line length: 1
final line character codes: 61
final line: a
Na pojedynczym pliku 'a'.
EDYCJA: Linia if((int)fin.tellg() <= 0){
w rzeczywistości powoduje problemy, jeśli plik jest zbyt duży (> 2 GB), ponieważ tellg nie zwraca tylko liczby znaków od początku pliku (tellg() function give wrong size of file?). Może być lepiej osobno przetestować na początek pliku fin.tellg()==tellgValueForStartOfFile
i błędów fin.tellg()==-1
. tellgValueForStartOfFile
jest prawdopodobnie 0, ale lepszym sposobem na upewnienie będzie prawdopodobnie:
fin.seekg (0, is.beg);
tellgValueForStartOfFile = fin.tellg();
Czy istnieje * cokolwiek *, które jest odporne na fakt, że ktoś * nieustannie * modyfikuje plik? Jak byś zdefiniował "mocną" w takiej sytuacji? –
@ user788171 powinieneś być w stanie szukać do końca i skanować wstecz dla terminatora linii. Prawdopodobnie sugerowałbym, żebyś nie używał tutaj surowego pliku, ponieważ brzmi bardziej jak chcesz fajkę. – oldrinb