2012-01-27 13 views
15

Ho scritto un programma che prende un file come input e ogni volta che trova una linea di lunghezza> 80, si aggiunge \ e \ n a quella file per renderlo 80 caratteri in larghezza max.funzione C per inserire testo in particolare posizione nel file senza eccesso di scrivere il testo esistente

Il problema è che ho usato fseek per inserire \ e \ n quando la lunghezza supera 80, quindi sostituisce due caratteri di quella linea che supera la lunghezza 80. C'è un modo con cui posso inserire testo senza sovrascrivere le testo esistente?

Ecco il mio codice: -

#include<stdio.h> 
#include<string.h> 

int main(int argc, char *argv[]) 
{ 
    FILE *fp1,*fp2; 
    int prev=0,now=0; 
    char ch; 
    int flag=0; 
    long cur; 
    fp1=fopen(argv[1],"r+"); 
    if(fp1==NULL){ 
    printf("Unable to open the file to read. Program will exit."); 
    exit(0); 
    } 
    else{ 
    while((ch=fgetc(fp1))!=EOF){ 
     if(ch!=' ' && ch!='\n'){ 
     now=now+1; 
     } 
     else{ 
     if(now>=80){ 
      fseek(fp1,cur,SEEK_SET); 
      fputc('\\',fp1); 
      fputc('\n',fp1); 
      now=0; 
      continue; 
     } 
     if(ch=='\n'){ 
      flag=0; 
      now=0; 
      continue; 
      } 
     else{ 
      prev=now; 
      cur=ftell(fp1); 
     } 
     now=now+1; 
     } 
    } 
    } 
    fclose(fp1); 
    return 0; 
} 

Per eseguirlo, è necessario fare seguente: -

[email protected]$ cc xyz.c 
[email protected]$ ./a.out file_to_check.txt 
+2

No, non c'è modo per inserire dati in t lui mezzo di un file. È necessario gestire "lo spostamento" dei dati da soli e/o scrivere in un nuovo file. – Mat

+1

@Mat: vorrei segnalare il tuo commento come "Non un commento", poiché è una risposta :) –

+2

possibile duplicato di [Come inserire e cancellare alcuni caratteri nel mezzo di un file?] (Http: // StackOverflow. it/questions/2431073/how-do-i-insert-and-delete-some-characters-in-the-middle-of-a-file) – Mat

risposta

7

No, non c'è modo di inserire caratteri in un file esistente. Dovrai usare un secondo file per farlo.

+1

non è completamente vero Puoi cercare(), fread(), seek() e fwrite() di nuovo. Ovviamente quindi la coda deve inserirsi nella memoria. – ckruse

+1

@ckruse: Questo, e rischi anche di distruggere il file originale se il 'fwrite()' non viene completato per qualche motivo. Pertanto, non ritengo che questo approccio sia una soluzione fattibile. – NPE

+0

Mi hai convinto. – ckruse

2

No, non c'è modo. Devi creare un nuovo file o spostare i contenuti del file 2 caratteri all'indietro.

0

è possibile caricare il file come pezzi (nel tuo caso è di 80 caratteri) e quindi aggiungere due caratteri (nuova linea) e scrivere il contenuto in anohter file.

16

Mentre ci sono un paio di tecniche per farlo sul posto, si sta lavorando con un file di testo e desidera eseguire inserimenti. I sistemi operativi in ​​genere non supportano l'inserimento di file di testo come un primitivo del file system e non c'è ragione per cui dovrebbero farlo.

Il migliore modo per fare questo genere di cose è quello di aprire il file per la lettura, aprire un nuovo file per la scrittura, copiare la parte del file prima del punto di inserimento, inserire i dati, copiare il resto, e quindi sposta il nuovo file su quello vecchio.

Questa è una tecnica comune ed ha uno scopo. Se qualcosa va storto (ad esempio con il tuo sistema), hai ancora il file originale e puoi ripetere la transazione in un secondo momento. Se si avviano due istanze del processo e si utilizza un modello specifico, la seconda istanza è in grado di rilevare che la transazione è già stata avviata. Con accesso file esclusivo, può anche rilevare se la transazione è stata interrotta o è ancora in esecuzione.

In questo modo è molto meno soggetto a errori rispetto a qualsiasi delle tecniche eseguite direttamente sul file originale e viene utilizzato da tutti questi strumenti tradizionali come sed anche se si chiede loro di lavorare sul posto (sed -i). Un altro vantaggio è che puoi sempre rinominare il file originale in uno con un suffisso di backup prima di sovrascriverlo (sed offre anche questa opzione).

La stessa tecnica viene spesso utilizzato per i file di configurazione, anche se il programma sta scrivendo una versione completamente nuova e non utilizza il file originale per questo. Non è passato molto tempo da quando molte riviste online hanno affermato che ext4 tronca accidentalmente i file di configurazione a lunghezza zero. Ciò è dovuto al fatto che alcune applicazioni mantenevano i file di configurazione aperti e troncati mentre il sistema veniva chiuso forzatamente. Queste applicazioni spesso manomettevano i file di configurazione originali prima del, avevano i dati pronti e quindi li tenevano aperti anche senza sincronizzarli, il che rendeva la finestra per la corruzione dei dati molto più grande.

TL; DR versione:

Quando si apprezzi i dati, non distruggerlo prima di avere i dati di sostituzione pronto.

1

Questa è la funzione che uso per questo genere di cose:

int finsert (FILE* file, const char *buffer) { 

    long int insert_pos = ftell(file); 
    if (insert_pos < 0) return insert_pos; 

    // Grow from the bottom 
    int seek_ret = fseek(file, 0, SEEK_END); 
    if (seek_ret) return seek_ret; 
    long int total_left_to_move = ftell(file); 
    if (total_left_to_move < 0) return total_left_to_move; 

    char move_buffer[1024]; 
    long int ammount_to_grow = strlen(buffer); 
    if (ammount_to_grow >= sizeof(move_buffer)) return -1; 

    total_left_to_move -= insert_pos; 

    for(;;) { 
     u16 ammount_to_move = sizeof(move_buffer); 
     if (total_left_to_move < ammount_to_move) ammount_to_move = total_left_to_move; 

     long int read_pos = insert_pos + total_left_to_move - ammount_to_move; 

     seek_ret = fseek(file, read_pos, SEEK_SET); 
     if (seek_ret) return seek_ret; 
     fread(move_buffer, ammount_to_move, 1, file); 
     if (ferror(file)) return ferror(file); 

     seek_ret = fseek(file, read_pos + ammount_to_grow, SEEK_SET); 
     if (seek_ret) return seek_ret; 
     fwrite(move_buffer, ammount_to_move, 1, file); 
     if (ferror(file)) return ferror(file); 

     total_left_to_move -= ammount_to_move; 

     if (!total_left_to_move) break; 

    } 

    seek_ret = fseek(file, insert_pos, SEEK_SET); 
    if (seek_ret) return seek_ret; 
    fwrite(buffer, ammount_to_grow, 1, file); 
    if (ferror(file)) return ferror(file); 

    return 0; 
} 

usare in questo modo:

FILE * file= fopen("test.data", "r+"); 
ASSERT(file); 

const char *to_insert = "INSERT"; 

fseek(file, 3, SEEK_SET); 
finsert(file, to_insert); 

ASSERT(ferror(file) == 0); 
fclose(file); 

questo (come altri qui hanno detto) può teoricamente corrompere un file, se non ci è un errore, ma ecco un codice per farlo davvero ... Farlo sul posto come questo di solito va bene, ma dovresti fare il backup del file se sei preoccupato per questo ...

Problemi correlati