[C] fopen w+ zonder truncate

Pagina: 1
Acties:

  • Olaf van der Spek
  • Registratie: September 2000
  • Niet online
Ik zit met een simpel probleem dat ik niet simpel kan oplossen. Ik wil een file openen voor read en write access, indien de file niet bestaat ik ik een nieuwe file maken en indien de file wel bestaat wil ik de inhoud behouden. Vrij simpel, maar met een enkele fopen call onmogelijk.

In aanmerking komen de volgende modes, maar beide doen net niet wat ik wil (append != write).
"w+": Opens an empty file for both reading and writing. If the given file exists, its contents are destroyed.

"a+": Opens for reading and appending; the appending operation includes the removal of the EOF marker before new data is written to the file and the EOF marker is restored after writing is complete; creates the file first if it doesn't exist.
Is dit nou echt niet mogelijk met fopen of zie ik iets over het hoofd.

[ Voor 7% gewijzigd door Olaf van der Spek op 27-10-2003 21:08 ]


  • Soultaker
  • Registratie: September 2000
  • Laatst online: 20-08 00:10
Je kunt in append-modus gewoon in het hele bestand schrijven, maar omdat de file pointer aan het eind van het bestand geplaatst wordt, moet je wel even naar het begin van de file seeken (met fseek of, meer specifiek, rewind).

  • Olaf van der Spek
  • Registratie: September 2000
  • Niet online
Soultaker schreef op 27 oktober 2003 @ 21:03:
Je kunt in append-modus gewoon in het hele bestand schrijven, maar omdat de file pointer aan het eind van het bestand geplaatst wordt, moet je wel even naar het begin van de file seeken (met fseek of, meer specifiek, rewind).
MSDN:
When a file is opened with the "a" or "a+" access type, all write operations occur at the end of the file. The file pointer can be repositioned using fseek or rewind, but is always moved back to the end of the file before any write operation is carried out. Thus, existing data cannot be overwritten.

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 12:02

.oisyn

Moderator Devschuur®

Demotivational Speaker

Je kunt een file openen met open (). Is geen ANSI, maar wel POSIX, dus op zich wel widely supported. Evt kun je met fdopen () de file descriptor handle (een int) converteren naar een FILE *

[ Voor 32% gewijzigd door .oisyn op 27-10-2003 21:18 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • Soultaker
  • Registratie: September 2000
  • Laatst online: 20-08 00:10
Hmz, ik was zeker in de war met 'r+'. Die modus kun je nog steeds wel gebruiken, maar dan wil je 'm misschien eerst openen met 'a+' om er zeker van te zijn dat 'ie er is.

Zoiets wordt 't dan:
C:
1
2
3
4
FILE *fp = fopen("test.txt", "a+");
freopen(NULL, "r+", fp);
fprintf(fp, "foobar!\n");
fclose(fp);

Het nut van die freopen() is niet zo groot; je zou misschien ook fclose() gevolgd door fopen() kunnen doen (maar dan kan iemand je file tussendoor wissen en dan faalt die fopen-call weer, denk ik). Officieel moet je natuurlijk ook de return values van fopen() en freopen() checken op fouten!

[ Voor 54% gewijzigd door Soultaker op 27-10-2003 21:32 ]


  • Olaf van der Spek
  • Registratie: September 2000
  • Niet online
The freopen function closes the file currently associated with stream and reassigns stream to the file specified by path.
Ik ben bang dat freopen ook geen atomic functie is. De code van .oisyn is dan iets beter, maar ik snap niet dat het niet in een keer kan.

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 20-08 00:10
OlafvdSpek schreef op 27 oktober 2003 @ 21:46:
Ik ben bang dat freopen ook geen atomic functie is. De code van .oisyn is dan iets beter, maar ik snap niet dat het niet in een keer kan.
Waarom zou het eigenlijk een atomaire operatie moeten zijn? Als de file aangemaakt wordt en iemand delete 'm gelijk, ben je de inhoud toch kwijt; ik zou zeggen dat het dan weinig uitmaakt of je er nog wel of niet naar kan schrijven (jij bent toch de laatste met een referentie naar dat bestand, dus zodra je 'm sluit, is je uitvoer toch verloren gegaan).

Overigens ben ik er niet van overtuigd dat freopen niet atomair zou zijn, als je NULL als argument gebruikt. Ik heb even in een standard C library implementatie gespiekt en daar wordt alleen de toegangsmodus aangepast (en wordt dus geen close uitgevoerd), mits het file argument NULL is.

  • Olaf van der Spek
  • Registratie: September 2000
  • Niet online
Soultaker schreef op 27 October 2003 @ 21:53:
Waarom zou het eigenlijk een atomaire operatie moeten zijn? Als de file aangemaakt wordt en iemand delete 'm gelijk, ben je de inhoud toch kwijt; ik zou zeggen dat het dan weinig uitmaakt of je er nog wel of niet naar kan schrijven (jij bent toch de laatste met een referentie naar dat bestand, dus zodra je 'm sluit, is je uitvoer toch verloren gegaan).

Overigens ben ik er niet van overtuigd dat freopen niet atomair zou zijn, als je NULL als argument gebruikt. Ik heb even in een standard C library implementatie gespiekt en daar wordt alleen de toegangsmodus aangepast (en wordt dus geen close uitgevoerd), mits het file argument NULL is.
In dit geval is het niet zo erg dat de functie niet atomair is.
Wat gebeurd er dan als je een read-only file eerst in read-only mode opent, dan de file read-write maakt en dan switched naar read-write mode met freopen? Gebeurd dat zonder close?

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 12:02

.oisyn

Moderator Devschuur®

Demotivational Speaker

Ik bedacht me ineens, waarom doe je het niet gewoon zo?
C++:
1
2
3
FILE * f = fopen ("file", "r+");
if (!f)
    f = fopen ("file", "w+");


r+ opent voor lezen en schrijven, maar alleen als het bestand al bestaat, anders retourneert ie NULL. En als het dus niet bestaat kun je 'm openen met w+. En ik zie niet in waarom dit fout zou kunnen gaan omdat het geen atomaire actie is, het bestand bestaat immers nog niet als de 2e fopen wordt uitgevoerd

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Verwijderd

.oisyn schreef op 28 October 2003 @ 12:50:
Ik bedacht me ineens, waarom doe je het niet gewoon zo?
C++:
1
2
3
FILE * f = fopen ("file", "r+");
if (!f)
    f = fopen ("file", "w+");


r+ opent voor lezen en schrijven, maar alleen als het bestand al bestaat, anders retourneert ie NULL. En als het dus niet bestaat kun je 'm openen met w+. En ik zie niet in waarom dit fout zou kunnen gaan omdat het geen atomaire actie is, het bestand bestaat immers nog niet als de 2e fopen wordt uitgevoerd
Ik denk dat hij nodig heeft:
C:
1
2
3
FILE * f = fopen ("file", "a+");
if (!f)
    f = fopen ("file", "w+");

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 12:02

.oisyn

Moderator Devschuur®

Demotivational Speaker

Ja ook zo lekker nuttig
"a+": Opens for reading and appending; the appending operation includes the removal of the EOF marker before new data is written to the file and the EOF marker is restored after writing is complete; creates the file first if it doesn't exist.
Oftewel, die failt niet als de file nog niet bestaat

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • Soultaker
  • Registratie: September 2000
  • Laatst online: 20-08 00:10
OlafvdSpek schreef op 27 October 2003 @ 23:39:
In dit geval is het niet zo erg dat de functie niet atomair is.
Wat gebeurd er dan als je een read-only file eerst in read-only mode opent, dan de file read-write maakt en dan switched naar read-write mode met freopen? Gebeurd dat zonder close?
De man-pages die ik heb zijn daar dus niet zo duidelijk over; wat bedoel je precies met die derde stap? Ik weet niet of er ergens een officiële specificatie van de ANSI C standard library te vinden is (of is die voor $700 oid te bestellen bij de ISO :/ )...
.oisyn schreef op 28 October 2003 @ 12:50:
C++:
1
2
3
FILE * f = fopen ("file", "r+");
if (!f)
    f = fopen ("file", "w+");
Het (nogal vergezochte) probleem daarmee zou kunnen zijn dat ik na de eerste fopen() call nét een bestaande grote database naar "file" move, die dan met de tweede fopen() call overschreven wordt (wat dus in principe nooit had mogen geburen: de bedoeling is dat het bestand geopend wordt zonder overschreven te worden en aangemaakt wordt als het niet bestaat; volgens die specificatie zou je nooit gegevens kunnen wissen).

  • Olaf van der Spek
  • Registratie: September 2000
  • Niet online
.oisyn schreef op 28 oktober 2003 @ 12:50:
Ik bedacht me ineens, waarom doe je het niet gewoon zo?
C++:
1
2
3
FILE * f = fopen ("file", "r+");
if (!f)
    f = fopen ("file", "w+");


r+ opent voor lezen en schrijven, maar alleen als het bestand al bestaat, anders retourneert ie NULL. En als het dus niet bestaat kun je 'm openen met w+. En ik zie niet in waarom dit fout zou kunnen gaan omdat het geen atomaire actie is, het bestand bestaat immers nog niet als de 2e fopen wordt uitgevoerd
Het gaat fout als:
fopen r+
andere app fopen w+, fclose (multi-threading en processing)
fopen w+

Dit is natuurlijk een relatief theoretische situatie.
Verder gebruik ik normaal CreateFile waarmee het wel kan, maar dit keer wilde ik een portable app schrijven.

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 12:02

.oisyn

Moderator Devschuur®

Demotivational Speaker

Dan gewoon open () ipv fopen (), dan is het nog steeds vrij portable :)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • Olaf van der Spek
  • Registratie: September 2000
  • Niet online
Soultaker schreef op 28 October 2003 @ 13:23:
De man-pages die ik heb zijn daar dus niet zo duidelijk over; wat bedoel je precies met die derde stap? Ik weet niet of er ergens een officiële specificatie van de ANSI C standard library te vinden is (of is die voor $700 oid te bestellen bij de ISO :/ )...
freopen in read-write mode? freopen(NULL, "rw", f)
.oisyn schreef op 28 oktober 2003 @ 15:44:
Dan gewoon open () ipv fopen (), dan is het nog steeds vrij portable :)
Natuurlijk.

[ Voor 19% gewijzigd door Olaf van der Spek op 28-10-2003 15:45 ]

Pagina: 1