Ecco una soluzione scritta in C per Windows. Verrà eseguito e terminato su un file di 700.000 linee, 245 MB in pochissimo tempo. (0,14 secondi)
Fondamentalmente, la memoria mappa il file, in modo che sia possibile accedere ai contenuti utilizzando le funzioni utilizzate per l'accesso alla memoria non elaborata. Una volta che il file è stato mappato, uso semplicemente la funzione strchr per trovare la posizione di una delle coppie di simboli usati per denotare un EOL in windows (\ n e \ r) - questo ci dice per quanto tempo in byte la prima riga è .
Da qui, ho appena memcpy dal primo byte della seconda riga indietro all'inizio dell'area di memoria mappata (in pratica, il primo byte nel file).
Una volta eseguita questa operazione, il file non viene mappato, l'handle per il file mem-mapped viene chiuso e viene quindi utilizzata la funzione SetEndOfFile per ridurre la lunghezza del file in base alla lunghezza della prima riga. Quando chiudiamo il file, si è ridotto di questa lunghezza e la prima riga è sparita.
Avere il file già in memoria da quando l'ho appena creato e scritto, ovviamente modifica un po 'il tempo di esecuzione, ma il meccanismo di caching di Windows è il "colpevole" qui - lo stesso meccanismo che stiamo sfruttando per rendere operazione completa molto rapidamente.
I dati di test sono la fonte del programma duplicati 100.000 volte e salvati come testInput2.txt (incollarlo 10 volte, selezionare tutto, copiare, incollare 10 volte - sostituendo l'originale 10, per un totale di 100 volte - ripetere fino all'output abbastanza grande.Mi sono fermato qui perché più sembrava rendere Notepad ++ un po 'infelice)
Il controllo degli errori in questo programma è praticamente inesistente e l'ingresso non dovrebbe essere UNICODE, cioè l'input è di 1 byte per carattere. La sequenza EOL è 0x0D, 0x0A (\ r \ n)
Codice:
#include <stdio.h>
#include <windows.h>
void testFunc(const char inputFilename[])
{
int lineLength;
HANDLE fileHandle = CreateFile(
inputFilename,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH,
NULL
);
if (fileHandle != INVALID_HANDLE_VALUE)
{
printf("File opened okay\n");
DWORD fileSizeHi, fileSizeLo = GetFileSize(fileHandle, &fileSizeHi);
HANDLE memMappedHandle = CreateFileMapping(
fileHandle,
NULL,
PAGE_READWRITE | SEC_COMMIT,
0,
0,
NULL
);
if (memMappedHandle)
{
printf("File mapping success\n");
LPVOID memPtr = MapViewOfFile(
memMappedHandle,
FILE_MAP_ALL_ACCESS,
0,
0,
0
);
if (memPtr != NULL)
{
printf("view of file successfully created");
printf("File size is: 0x%04X%04X\n", fileSizeHi, fileSizeLo);
LPVOID eolPos = strchr((char*)memPtr, '\r'); // windows EOL sequence is \r\n
lineLength = (char*)eolPos-(char*)memPtr;
printf("Length of first line is: %ld\n", lineLength);
memcpy(memPtr, eolPos+2, fileSizeLo-lineLength);
UnmapViewOfFile(memPtr);
}
CloseHandle(memMappedHandle);
}
SetFilePointer(fileHandle, -(lineLength+2), 0, FILE_END);
SetEndOfFile(fileHandle);
CloseHandle(fileHandle);
}
}
int main()
{
const char inputFilename[] = "testInput2.txt";
testFunc(inputFilename);
return 0;
}
file semplicemente non funziona in questo modo (simile a un array cruda, non è possibile rimuovere il primo elemento senza spostare tutti gli elementi rimanenti in uno slot). – crashmstr
Ogni ramo di quell'istruzione 'if' ha' file.close(); lock.unlock(); '. Il distruttore per l'oggetto 'std :: file' chiuderà il file, quindi non è necessario chiuderlo esplicitamente (e quando' file.is_open() 'restituisce false, non è necessario chiuderlo). E c'è senza dubbio un tipo RAII in Boost per gestire quel blocco, con un distruttore per sbloccarlo. –
Sì certo, "tutti" ... https://www.google.com/search?q=c%2B%2B+modify+file+in+place –