Append a record to the end of a text file
Many systems offer the ability to open a file for writing, such that any data written will be appended to the end of the file. Further, the file operations will always adjust the position pointer to guarantee the end of the file, even in a multitasking environment.
This feature is most useful in the case of log files, where many jobs may be appending to the log file at the same time, or where care must be taken to avoid concurrently overwriting the same record from another job.
Task: Given a two record sample for a mythical "passwd" file:
- Write these records out in the typical system format.
- Ideally these records will have named fields of various types.
- Close the file, then reopen the file for append.
- Append a new record to the file and close the file again.
- Take appropriate care to avoid concurrently overwrites from another job.
- Open the file and demonstrate the new record has indeed written to the end.
Finally: Provide a summary of the language's "append record" capabilities in a table.
Alternatively: If the language's appends can not guarantee its writes will always append, then note this restriction in the table. If possible, provide an actual code example (possibly using file/record locking) to guarantee correct concurrent appends.
C
Data Representation | IO Library |
Append Possible |
Automatic Append |
Multi-tasking Guaranteed | |
---|---|---|---|---|---|
In core | On disk | ||||
C struct | CSV text file | glibc/stdio | ☑ | ☑ | ☑ |
From a C "struct" to CSV File <lang C>#include <stdio.h>
- include <string.h>
/* note that UID & gid are of type "text" */ typedef char *STRING; typedef struct{STRING fullname, office, extension, homephone, email; } gecos_t; typedef struct{STRING account, password; int uid, gid; gecos_t gecos; STRING directory, shell; } passwd_t;
- define GECOS_FMT "%s,%s,%s,%s"
- define PASSWD_FMT "%s:%s:%d:%d:"GECOS_FMT":%s:%s"
passwd_t passwd_list[]={
{"jsmith", "x", 1001, 1000, /* UID and GID are type int */ {"Joe Smith", "Room 1007", "(234)555-8917", "(234)555-0077", "jsmith@rosettacode.org"}, "/home/jsmith", "/bin/sh"}, {"jdoe", "x", 1002, 1000, {"Jane Doe", "Room 1004", "(234)555-8914", "(234)555-0044", "jdoe@rosettacode.org"}, "/home/jsmith", "/bin/sh"}
};
main(){ /****************************
- Create a passwd text file *
- /
FILE *passwd_text=fopen("passwd.txt", "w"); int rec_num; for(rec_num=0; rec_num < sizeof passwd_list/sizeof(passwd_t); rec_num++) fprintf(passwd_text, PASSWD_FMT"\n", passwd_list[rec_num]); fclose(passwd_text);
/********************************
- Load text ready for appending *
- /
passwd_text=fopen("passwd.txt", "a+"); passwd_t new_rec = {"xyz", "x", 1003, 1000, /* UID and GID are type int */ {"X Yz", "Room 1003", "(234)555-8913", "(234)555-0033", "xyz@rosettacode.org"}, "/home/xyz", "/bin/sh"}; fprintf(passwd_text, PASSWD_FMT"\n", new_rec); fclose(passwd_text);
/***********************************************
- Finally reopen and check record was appended *
- /
char passwd_buf[512]; /* warning: fixed length */ passwd_text=fopen("passwd.txt", "r"); while(!feof(passwd_text)) fscanf(passwd_text, "%[^\n]\n", passwd_buf, "\n"); if(strstr(passwd_buf, "xyz")) printf("Appended record: %s\n", passwd_buf);
}</lang> Output:
Appended record: xyz:x:1003:1000:X Yz,Room 1003,(234)555-8913,(234)555-0033:xyz@rosettacode.org:/home/xyz
Java
<lang java>import java.io.BufferedReader; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.io.PrintWriter;
public class Append{ public static void main(String[] args){ try{ System.out.println("Pre-loading file..."); //the "true" here is for autoflush PrintWriter out = new PrintWriter(new FileWriter("passwd"), true); out.println("user1 password1"); out.println("user2 password2"); out.close(); showFile("passwd");
System.out.println("\nAppending new line to file..."); //the first "true" is for append, the second is for autoflush out = new PrintWriter(new FileWriter("passwd", true), true); out.println("user3 password3"); out.close(); showFile("passwd"); }catch(IOException e){ System.err.println("Error in writing file: " + e.getMessage()); } }
private static void showFile(String filename){ try{ BufferedReader in = new BufferedReader(new FileReader(filename)); while(in.ready()){ System.out.println(in.readLine()); } }catch(FileNotFoundException e){ System.err.println("File " + filename + " not found."); }catch(IOException e){ System.err.println("Error in reading file: " + e.getMessage()); } } }</lang> Output:
Pre-loading file... user1 password1 user2 password2 Appending new line to file... user1 password1 user2 password2 user3 password3
Python
Data Representation | IO Library |
Append Possible |
Automatic Append |
Multi-tasking Guaranteed | |
---|---|---|---|---|---|
In core | On disk | ||||
dict | CSV text file | builtin | ☑ | ☑ | ☑ |
instance | CSV text file | builtin | ? | ? | ? |
From a "dict" to a CSV File <lang python>#############################
- Create a passwd text file
- note that UID & gid are of type "text"
passwd_list=[
dict(account='jsmith', password='x', UID=1001, GID=1000, # UID and GID are type int GECOS=dict(fullname='Joe Smith', office='Room 1007', extension='(234)555-8917', homephone='(234)555-0077', email='jsmith@rosettacode.org'), directory='/home/jsmith', shell='/bin/sh'), dict(account='jdoe', password='x', UID=1002, GID=1000, GECOS=dict(fullname='Jane Doe', office='Room 1004', extension='(234)555-8914', homephone='(234)555-0044', email='jdoe@rosettacode.org'), directory='/home/jsmith', shell='/bin/sh')
]
passwd_fields="account password UID GID GECOS directory shell".split() GECOS_fields="fullname office extension homephone email".split()
def passwd_text_repr(passwd_rec):
- convert individual fields to string type
passwd_rec["GECOS"]=",".join([ passwd_rec["GECOS"][field] for field in GECOS_fields]) for field in passwd_rec: # convert "int" fields if not isinstance(passwd_rec[field], str): passwd_rec[field]=`passwd_rec[field]` return ":".join([ passwd_rec[field] for field in passwd_fields ])
passwd_text=open("passwd.txt","w") for passwd_rec in passwd_list:
print >> passwd_text,passwd_text_repr(passwd_rec)
passwd_text.close()
del passwd_list, passwd_text
- Load text ready for appending
passwd_text=open("passwd.txt","a+") new_rec=dict(account='xyz', password='x', UID=1003, GID=1000,
GECOS=dict(fullname='X Yz', office='Room 1003', extension='(234)555-8913', homephone='(234)555-0033', email='xyz@rosettacode.org'), directory='/home/xyz', shell='/bin/sh')
print >> passwd_text, passwd_text_repr(new_rec) passwd_text.close()
del new_rec, passwd_text
- Finally reopen and check record was appended
passwd_list=list(open("passwd.txt","r")) if "xyz" in passwd_list[-1]:
print "Appended record:",passwd_list[-1][:-1]</lang>
Output:
Appended record: xyz:x:1003:1000:X Yz,Room 1003,(234)555-8913,(234)555-0033,xyz@rosettacode.org:/home/xyz:/bin/sh