Avatar billede ladyhawke Novice
24. september 2002 - 11:53 Der er 22 kommentarer og
3 løsninger

tekstfil

Jeg har tidligere stillet et tilsvarende spørgsmål men endnu ikke fået det til at virke, så please help:

Hvordan erstatter man en vilkårlig linie i en tekstfil med en anden (muligvis kortere/længere)? Jeg kender liniens nummer i filen og det gør ikke noget der bliver oprettet en midlertidig fil, bare den bliver fjernet bagefter. Jeg må ikke ændre på filens navn og extension.... (input og output fil er det samme...)
Avatar billede NanoQ Nybegynder
24. september 2002 - 12:03 #1
Jeg bruger det lille gratis dosprogram YANK.EXE

Den ligger i denne pakke: http://ww2.netnitco.net/users/cruth/cutpak13.zip

1. YANK: * * * * [added 1998-04-19 updated 2000-03-02]. Like KLine, this program can be used to strip out entire lines containing a search string, but it also offers the option of replacing the line with another string rather than deleting it. Search and replace strings can be any combination of literals and ASCII codes. Other differences from KLINE: 1) YANK handles longer lines; 2) does not create a backup file; 4) "can read from another file both the search and replace string specifications or replacement text image (65,534 char. max; search string limit 4,095 char.)." Limitations: Unlike KLine, YANK doesn't output number of changes made per file. Works fine on my MS-DOS machine- but can't get it to work properly under OpenDOS. Part of the CUTPAK package. Author: Clay Ruth (1996, 2000). Sugg. by M. Van Erp.

YANK [/i] filespec "[srchstrng][^[x]chr,][...]" ["[replstrng][^[x]chr,][...]"]
YANK [/i] filespec @scriptfile or YANK [/i] filespec "srchspec" @imagefile
i...case insensitive

03-02-00: Package now at v13; Yank not changed.

NanoQ
Avatar billede ladyhawke Novice
24. september 2002 - 12:06 #2
Hvordan får jeg integreret det i mit program? Jeg skal, efter at have fundet de interessante linier i en fil, redigere i dem og denæst opdatere filen til atafspejle de nye linier. Det er kun det sidste der ikke virker...

NB bruger Visual C++
Avatar billede NanoQ Nybegynder
24. september 2002 - 12:10 #3
undskyld... jeg læste ikke kategorien, så jeg misforstod dit spørgsmål :)
Avatar billede ladyhawke Novice
24. september 2002 - 12:16 #4
alt forladt, håber bare der kommer nogle gode svar :o)
Avatar billede jpk Nybegynder
24. september 2002 - 12:23 #5
1) Læs filen ind i en tekststreng
2) Foretag ændring
3) Overskriv filen med indholdet af tekststrengen
Avatar billede ladyhawke Novice
24. september 2002 - 12:28 #6
jpk >> lidt mere specifikt...

Jeg har en FILE input, som er tekstfilen, kan jeg indlæse hele filen uden at få problemer med at filen er for stor (ofte 10000 linier +++) og hvordan laver jeg ændringen, kan je udskifte alt mellem to newlines eller???
Avatar billede ladyhawke Novice
24. september 2002 - 12:29 #7
der gik vist lidt Fynbo i det: je ->jeg
Avatar billede jpk Nybegynder
24. september 2002 - 12:49 #8
Hvad fylder filen typisk i kB?

Hvis teksten er i en streng, kan du jo benytte strengens metoder (fx replace og insert) til at ændre teksten.
Avatar billede ladyhawke Novice
24. september 2002 - 13:05 #9
Det er meget forskelligt (det er .cpp filer der er tale om hovedsageligt) og det kan være alt fra 1k til 300k +

Måske kunne bruge en midlertidig fil (kopier alt før linien, indsæt den rettede linie og kopier alt efter), men hvordan gør man det nemmest, så man får slettet den midliertige fil hver gang...
Avatar billede ladyhawke Novice
24. september 2002 - 13:15 #10
BTW. tidligere i programmet benyttes en ifstream til at åbne filen med...
Avatar billede jpk Nybegynder
24. september 2002 - 13:16 #11
Du anvender ikke MFC i programmet?
Avatar billede ladyhawke Novice
24. september 2002 - 13:20 #12
Jo, nogen steder...
Jeg kan sådan set bruge "hvad som helst", jeg skal bare være 100% sikker på at filen ikke bliver ødelagt af opdateringen...
Avatar billede jpk Nybegynder
24. september 2002 - 13:26 #13
Er filen åben i andre programmer samtidig?
Avatar billede ladyhawke Novice
24. september 2002 - 13:27 #14
nej :o)
Avatar billede ladyhawke Novice
24. september 2002 - 13:54 #15
kigger igen i morgen... :o)
Avatar billede jpk Nybegynder
24. september 2002 - 13:56 #16
Noget lign.:

CFile File;
if(!File.Open("C:\\MyFile.cpp", CFile::modeReadWrite))
{
  // error
}

int nFileLength = File.GetLength();
CString strData;
File.Read(strData.GetBufferSetLength(nFileLength), nFileLength);

if(bBackupFile)
{
  CFile BackupFile;
  if(BackupFile.Open("C:\\MyFile.bak", CFile::modeCreate))
  {
    BackupFile.Write((void*)(LPCTSTR)strData, nFileLength);
  }
  else
  {
    // error
  }
}

// Ret tekst...
strData.Replace(..);

File.SetLength(strData.GetLength());
File.SeekToBegin();
File.Write((void*)(LPCTSTR)strData);
Avatar billede mbulow Nybegynder
24. september 2002 - 14:11 #17
Hvis vi nu forestiller os at du har en tekstfil (a.txt) med k100 linjer, og du vil ændre noget i linje 42, kunne du gøre sådan her:

1) Opret en ny fil (b.txt)
2) Kopier de første 41 linjer fra a.txt til b.txt
3) Skriv den ændrede linje til b.txt
4) Kopier de efterfølgende linjer (linje 43 - 100) fra a.txt til b.txt
5) Slet evt a.txt og omdøb b.txt til a.txt
Avatar billede kamikaze Nybegynder
24. september 2002 - 15:51 #18
Har lige stykket noget sammen, som du måske kan tage udgangspunkt i:

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

#define MAX_LINE_LEN 1024

bool replace_line(char* filename, char* pReplaceBuf, int line, int num_lines = 1)
{
    FILE* pFile = fopen(filename, "r+b");
    if (!pFile) return false;
    fseek(pFile, 0, SEEK_END);
    long iSize = ftell(pFile);
    fseek(pFile, 0, SEEK_SET);
    char* pFileBuffer = new char[iSize + strlen(pReplaceBuf)];
    long pos = 0;
    char* pLineBuffer = new char[MAX_LINE_LEN];
   
    // read first half
    for (int i=0; i<line; ++i)
    {
        fgets(pLineBuffer, MAX_LINE_LEN, pFile);
        if (pLineBuffer == NULL) return false;
        for (int n=0; n<strlen(pLineBuffer); ++n)
            pFileBuffer[n + pos] = pLineBuffer[n];
        pos += strlen(pLineBuffer);
    }

    // insert new text
    for (i=0; i<strlen(pReplaceBuf); ++i)
        pFileBuffer[i + pos] = pReplaceBuf[i];

    pos += strlen(pReplaceBuf);

    // skip num_lines lines
    for (i=0; i< num_lines; ++i)
    {
        fgets(pLineBuffer, MAX_LINE_LEN, pFile);
        if (pLineBuffer == NULL) return false;
    }

    // read second half
    while((fgets(pLineBuffer, MAX_LINE_LEN, pFile)) != NULL)
    {
        for (int n=0; n<strlen(pLineBuffer); ++n)
            pFileBuffer[n + pos] = pLineBuffer[n];
        pos += strlen(pLineBuffer);
    }

    pFileBuffer[pos] = 0;
    fclose(pFile);

    pFile = fopen(filename, "w+b");
    // write file
    for (i=0; i<strlen(pFileBuffer); ++i)
        fputc(pFileBuffer[i], pFile);
    fclose(pFile);
    delete pFileBuffer;
    delete pLineBuffer;

    return true;
}

int main()
{
    if (!replace_line("C:\\test.txt", "Hello\n", 4, 2))
        cout << "ERROR" << endl;
    cout << "<any key>" << endl;
    getch();
    return 0;
}
Avatar billede kamikaze Nybegynder
24. september 2002 - 15:55 #19
Ovenstående funktion tager flg. parametre:
bool replace_line(char* filename, char* pReplaceBuf, int line, int num_lines = 1)

filename == giver sig selv
pReplaceBuf == buffer, indeholdende den tekst der skal indsættes
line == nul-baseret nummer på den linie der skal udskiftes
num_lines == antal linier der skal udskiftes

Koden er lidt spaghetti-agtig, men den er platforms-uafhængig og kan nemt rettes lidt til...
Avatar billede ladyhawke Novice
25. september 2002 - 10:38 #20
Mange tak for hjælpen! Jeg har anvendt kamikazes forslag, men i har alle bidraget med råd og vejledning, så pointene fordeles herefter
Avatar billede jpk Nybegynder
25. september 2002 - 10:41 #21
Skal du erstatte flere linier i samme fil?
Avatar billede kamikaze Nybegynder
25. september 2002 - 10:47 #22
Takker for points :o)
Avatar billede ladyhawke Novice
25. september 2002 - 11:30 #23
jpk >> i nogle tilfælde, men foreløbig nøjes jeg med denne version, selvom der er noget overhead... Jeg kan jo senere ændre den, så den ændrer de ønskede linier, når resten af programmet kommer til at understøtte det
Avatar billede kamikaze Nybegynder
25. september 2002 - 14:01 #24
Hmmm...Det forslag jeg lagde her kan godt håndtere ændring af flere sammenhængende linier. Hvis det er ikke-sammenhængende linier der skal ændres er der en del overhead.

Man kunne jo i stedet for ...char* pReplaceBuf, int line, int num_lines... give en vector med flg. structs som noder:

typedef struct _ChangeNode
{
  int line;
  int num_lines;
  char* pReplaceBuf;
} ChangeNode;

og håndtere alle ændringer på en gang.
Avatar billede soepro Nybegynder
25. september 2002 - 15:21 #25
Er vi så ikke tilbage til http://www.eksperten.dk/spm/248154 - du skal blot lave følgende krølle til sidst i programmet:

remove("C:\\gl_txt.fil");
rename("C:\\ny_txt.fil", "C:\\gl_txt.fil");
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester