Append a record to the end of a text file: Difference between revisions
Content deleted Content added
Thundergnat (talk | contribs) Rename Perl 6 -> Raku, alphabetize, minor clean-up |
Add ed example |
||
(24 intermediate revisions by 15 users not shown) | |||
Line 60:
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.
<br><br>
=={{header|Action!}}==
<syntaxhighlight lang="action!">PROC CreateLog(CHAR ARRAY fname)
CHAR ARRAY header="account:password:UID:GID:fullname,office,extension,homephone,email:directory:shell"
BYTE dev=[1]
Close(dev)
Open(dev,fname,8)
PrintDE(dev,header)
Close(dev)
RETURN
PROC AppendLog(CHAR ARRAY fname,line)
BYTE dev=[1]
Close(dev)
Open(dev,fname,9)
PrintDE(dev,line)
Close(dev)
RETURN
PROC ReadFile(CHAR ARRAY fname)
CHAR ARRAY line(255)
BYTE dev=[1]
Close(dev)
Open(dev,fname,4)
WHILE Eof(dev)=0
DO
InputSD(dev,line)
IF line(0) THEN
PutE() Print(line)
FI
OD
Close(dev)
RETURN
PROC PrintInv(CHAR ARRAY a)
BYTE i
IF a(0)>0 THEN
FOR i=1 TO a(0)
DO
Put(a(i)%$80)
OD
FI
RETURN
PROC Main()
CHAR ARRAY fname="D:PASSWD"
BYTE LMARGIN=$52,oldLMARGIN
oldLMARGIN=LMARGIN
LMARGIN=0 ;remove left margin on the screen
Put(125) PutE() ;clear the screen
CreateLog(fname)
AppendLog(fname,"jsmith:x:1001:1000:Joe Smith,Room 1007,(234)555-8917,(234)555-0077,jsmith@rosettacode.org:/home/jsmith:/bin/bash")
AppendLog(fname,"jdoe:x:1002:1000:Jane Doe,Room 1004,(234)555-8914,(234)555-0044,jdoe@rosettacode.org:/home/jdoe:/bin/bash")
PrintInv("Initial log:")
ReadFile(fname)
AppendLog(fname,"xyz:x:1003:1000:X Yz,Room 1003,(234)555-8913,(234)555-0033,xyz@rosettacode.org:/home/xyz:/bin/bash")
PutE() PrintInv("Updated log:")
ReadFile(fname)
LMARGIN=oldLMARGIN ;restore left margin on the screen
RETURN</syntaxhighlight>
{{out}}
[https://gitlab.com/amarok8bit/action-rosetta-code/-/raw/master/images/Append_a_record_to_the_end_of_a_text_file.png Screenshot from Atari 8-bit computer]
<pre>
Initial log:
account:password:UID:GID:fullname,office,extension,homephone,email:directory:shell
jsmith:x:1001:1000:Joe Smith,Room 1007,(234)555-8917,(234)555-0077,jsmith@rosettacode.org:/home/jsmith:/bin/bash
jdoe:x:1002:1000:Jane Doe,Room 1004,(234)555-8914,(234)555-0044,jdoe@rosettacode.org:/home/jdoe:/bin/bash
Updated log:
account:password:UID:GID:fullname,office,extension,homephone,email:directory:shell
jsmith:x:1001:1000:Joe Smith,Room 1007,(234)555-8917,(234)555-0077,jsmith@rosettacode.org:/home/jsmith:/bin/bash
jdoe:x:1002:1000:Jane Doe,Room 1004,(234)555-8914,(234)555-0044,jdoe@rosettacode.org:/home/jdoe:/bin/bash
xyz:x:1003:1000:X Yz,Room 1003,(234)555-8913,(234)555-0033,xyz@rosettacode.org:/home/xyz:/bin/bash
</pre>
=={{header|Ada}}==
<syntaxhighlight lang="ada">
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Integer_Text_IO; use Ada.Integer_Text_IO;
with Ada.Strings.Bounded;
procedure Main is
package data_string is new Ada.Strings.Bounded.Generic_Bounded_Length(80);
use data_string;
type GCOSE_Rec is record
Full_Name : Bounded_String;
Office : Bounded_String;
Extension : Bounded_String;
Homephone : Bounded_String;
Email : Bounded_String;
end record;
type Password_Rec is record
Account : Bounded_String;
Password : Bounded_String;
Uid : Natural;
Gid : Natural;
GCOSE : GCOSE_Rec;
Directory : Bounded_String;
Shell : Bounded_String;
end record;
function To_String(Item : GCOSE_Rec) return String is
begin
return To_String(Item.Full_Name) & "," &
To_String(Item.Office) & "," &
To_String(Item.Extension) & "," &
To_String(Item.Homephone) & "," &
To_String(Item.Email);
end To_String;
function To_String(Item : Password_Rec) return String is
uid_str : string(1..4);
gid_str : string(1..4);
Temp : String(1..5);
begin
Temp := Item.Uid'Image;
uid_str := Temp(2..5);
Temp := Item.Gid'Image;
gid_str := Temp(2..5);
return To_String(Item.Account) & ":" &
To_String(Item.Password) & ":" &
uid_str & ":" & gid_str & ":" &
To_String(Item.GCOSE) & ":" &
To_String(Item.Directory) & ":" &
To_String(Item.Shell);
end To_String;
Pwd_List : array (1..3) of Password_Rec;
Filename : String := "password.txt";
The_File : File_Type;
Line : String(1..256);
Length : Natural;
begin
Pwd_List(1) := (Account => To_Bounded_String("jsmith"),
Password => To_Bounded_String("x"),
Uid => 1001, GID => 1000,
GCOSE => (Full_Name => To_Bounded_String("Joe Smith"),
Office => To_Bounded_String("Room 1007"),
Extension => To_Bounded_String("(234)555-8917"),
Homephone => To_Bounded_String("(234)555-0077"),
email => To_Bounded_String("jsmith@rosettacode.org")),
directory => To_Bounded_String("/home/jsmith"),
shell => To_Bounded_String("/bin/bash"));
Pwd_List(2) := (Account => To_Bounded_String("jdoe"),
Password => To_Bounded_String("x"),
Uid => 1002, GID => 1000,
GCOSE => (Full_Name => To_Bounded_String("Jane Doe"),
Office => To_Bounded_String("Room 1004"),
Extension => To_Bounded_String("(234)555-8914"),
Homephone => To_Bounded_String("(234)555-0044"),
email => To_Bounded_String("jdoe@rosettacode.org")),
directory => To_Bounded_String("/home/jdoe"),
shell => To_Bounded_String("/bin/bash"));
Pwd_List(3) := (Account => To_Bounded_String("xyz"),
Password => To_Bounded_String("x"),
Uid => 1003, GID => 1000,
GCOSE => (Full_Name => To_Bounded_String("X Yz"),
Office => To_Bounded_String("Room 1003"),
Extension => To_Bounded_String("(234)555-8913"),
Homephone => To_Bounded_String("(234)555-0033"),
email => To_Bounded_String("xyz@rosettacode.org")),
directory => To_Bounded_String("/home/xyz"),
shell => To_Bounded_String("/bin/bash"));
Create(File => The_File,
Mode => Out_File,
Name => Filename);
for I in 1..2 loop
Put_Line(File => The_File,
Item => To_String(Pwd_List(I)));
end loop;
Reset(File => The_File,
Mode => In_File);
while not End_Of_File(The_File) loop
Get_Line(File => The_File,
Item => Line,
Last => Length);
Put_Line(Line(1..Length));
end loop;
New_Line;
Reset(File => The_File,
Mode => Append_File);
Put_Line(File => The_File,
Item => To_String(Pwd_List(3)));
Reset(File => The_File,
Mode => In_File);
while not End_Of_File(The_File) loop
Get_Line(File => The_File,
Item => Line,
Last => Length);
Put_Line(Line(1..Length));
end loop;
Close(The_File);
end Main;
</syntaxhighlight>
{{output}}
<pre>
jsmith:x:1001:1000:Joe Smith,Room 1007,(234)555-8917,(234)555-0077,jsmith@rosettacode.org:/home/jsmith:/bin/bash
jdoe:x:1002:1000:Jane Doe,Room 1004,(234)555-8914,(234)555-0044,jdoe@rosettacode.org:/home/jdoe:/bin/bash
jsmith:x:1001:1000:Joe Smith,Room 1007,(234)555-8917,(234)555-0077,jsmith@rosettacode.org:/home/jsmith:/bin/bash
jdoe:x:1002:1000:Jane Doe,Room 1004,(234)555-8914,(234)555-0044,jdoe@rosettacode.org:/home/jdoe:/bin/bash
xyz:x:1003:1000:X Yz,Room 1003,(234)555-8913,(234)555-0033,xyz@rosettacode.org:/home/xyz:/bin/bash
</pre>
=={{header|AWK}}==
<syntaxhighlight lang="awk">
# syntax: GAWK -f APPEND_A_RECORD_TO_THE_END_OF_A_TEXT_FILE.AWK
BEGIN {
Line 87 ⟶ 304:
printf("%d records\n\n",nr)
}
</syntaxhighlight>
<p>Output:</p>
<pre>
Line 105 ⟶ 322:
=={{header|Batch File}}==
<
@echo off
Line 122 ⟶ 339:
type append.txt
pause>nul
</syntaxhighlight>
{{out}}
Line 153 ⟶ 370:
'''From a C "struct" to CSV File'''
<
#include <string.h>
/* note that UID & GID are of type "int" */
Line 205 ⟶ 422:
if(strstr(passwd_buf, "xyz"))
printf("Appended record: %s\n", passwd_buf);
}</
{{out}}
<pre>
Line 212 ⟶ 429:
=={{header|C sharp|C#}}==
<
using System.IO;
Line 255 ⟶ 472:
}
}
</syntaxhighlight>
{{out}}
Line 263 ⟶ 480:
=={{header|C++}}==
{{trans|C#}}
<
#include <fstream>
#include <string>
Line 343 ⟶ 560:
return 0;
}</
{{out}}
<pre>Appended record: xyz:x:1003:1000:X Yz,Room 1003,(234)555-8913,(234)555-0033,xyz@rosettacode.org:/home/xyz:/bin/bash</pre>
Line 394 ⟶ 611:
'''Record group to passwd format, LINE SEQUENTIAL'''
<syntaxhighlight lang="cobol">
*> Tectonics:
*> cobc -xj append.cob
Line 666 ⟶ 883:
.
end program append.</
{{out}}
<pre>prompt$ cobc -xj append.cob
Line 674 ⟶ 891:
=={{header|Common Lisp}}==
Tested on CLISP 2.49
<
(list
(list "jsmith" "x" 1001 1000
Line 726 ⟶ 943:
(main)
</syntaxhighlight>
{{out}}
<pre>$ clisp append_file.cl
Line 747 ⟶ 964:
=={{header|D}}==
{{trans|Java}}
<
private const string account;
private const string password;
Line 839 ⟶ 1,056:
}
passwd.close();
}</
{{out}}
Line 845 ⟶ 1,062:
jdoe:x:1002:1000:Jane Doe,Room 1004,(234)555-8914,(234)555-0044,jdoe@rosettacode.org:/home/jdoe:/bin/bash
xyz:x:1003:1000:X Yz,Room 1003,(234)555-8913,(234)555-0033,xyz@rosettacode.org:/home/xyz:/bin/bash</pre>
=={{header|ed}}==
<syntaxhighlight lang="sed">
H
r append.input
,p
a
xyz:x:1003:1000:X Yz,Room 1003,(234)555-8913,(234)555-0033,xyz@rosettacode.org:/home/xyz:/bin/bash
.
w
,p
q
</syntaxhighlight>
{{out}}
<pre>$ ed -s < append.ed
Newline appended
account:password:UID:GID:fullname,office,extension,homephone,email:directory:shell
jsmith:x:1001:1000:Joe Smith,Room 1007,(234)555-8917,(234)555-0077,jsmith@rosettacode.org:/home/jsmith:/bin/bash
jdoe:x:1002:1000:Jane Doe,Room 1004,(234)555-8914,(234)555-0044,jdoe@rosettacode.org:/home/jdoe:/bin/bash
account:password:UID:GID:fullname,office,extension,homephone,email:directory:shell
jsmith:x:1001:1000:Joe Smith,Room 1007,(234)555-8917,(234)555-0077,jsmith@rosettacode.org:/home/jsmith:/bin/bash
jdoe:x:1002:1000:Jane Doe,Room 1004,(234)555-8914,(234)555-0044,jdoe@rosettacode.org:/home/jdoe:/bin/bash
xyz:x:1003:1000:X Yz,Room 1003,(234)555-8913,(234)555-0033,xyz@rosettacode.org:/home/xyz:/bin/bash</pre>
{|class="wikitable" style="text-align: center; margin: 1em auto 1em auto;"
|+ Append Capabilities.
|-
!colspan=2| Data Representation
!rowspan=2| IO<BR>Library
!rowspan=2| Append<BR>Possible
!rowspan=2| Automatic<BR>Append
!rowspan=2| Multi-tasking<BR>Safe
|-
! In core || On disk
|-
| text lines || /etc/passwd format file || editor functionality || ☑ || ☑ || ☑
|}
=={{header|Elixir}}==
Line 860 ⟶ 1,117:
| objects (subclass of Struct builtin) || text file || builtin || ☑ || ☑ || ☒
|}
<
defmodule Gecos do
defstruct [:fullname, :office, :extension, :homephone, :email]
Line 947 ⟶ 1,204:
Appender.write("passwd.txt")
</syntaxhighlight>
{{out}}
<pre>
Line 960 ⟶ 1,217:
In the absence of a length indication, when outputting text variables with a view to having them read in again, delimiting them with quotes (and doubling internal quotes) is the route to peace of mind, because otherwise a text might contain a comma as in "43 Gurney Road, Belmont" and in the absence of quoting, such a sequence on input might well be taken as two fields rather than one and a mess is certain. This facility is offered by the free-format (or, "list directed") style initiated by the use of * in place of a format label, as in <code>WRITE (MSG,*) ''etc.''</code>, provided however that the output file has been opened with the optional usage attribute <code>DELIM = "QUOTE"</code>, an unfortunate choice of name, because the field separator character could also be termed a "delimiter" and the default value is both a space or comma, when often what is preferable is only a comma, or even a tab. But there is no standard method to specify this desire. Only if the texts never themselves contain commas or spaces will this unquoted free-format scheme evade extra effort, and the specified example precludes this simplicity.
The resulting output is strung along an output line, with a default line length of 132 (a standard lineprinter width); the specification of RECL = 666 ensures that all the output fields are rolled to one line - that isn't padded out to 666 characters: this is not a fixed-length record despite the specification of RECL as a constant, though each record turns out to be 248 characters long. Unfortunately, the trailing spaces in each character variable are rolled forth and there is no option along the lines of <code>WRITE (MSG,*) TRIM(NOTE)</code> One could instead use a suitable FORMAT statement with "A" format codes, but every element of NOTE would have to be named in the output list and the TRIM function applied only to each character field. Not only would this be tedious and error-prone, there is no format code for the enquoting and double-quoting of the texts and thus, no peace of mind... One would of course devise a subroutine to write out such a record (which would probably be more complex, with the FULLNAME subdivided, etc.), but the task's main objective is to demonstrate appending output to a file.<
TYPE DETAILS !Define a component.
CHARACTER*28 FULLNAME
Line 1,023 ⟶ 1,280:
Closedown.
20 CLOSE (F)
END</
The output can be read back in with the same free-format style. The fields are separated by spaces (outside a quoted string) though commas are also allowed. The file content is as follows:
Line 1,085 ⟶ 1,342:
=={{header|FreeBASIC}}==
<
Type Person
Line 1,170 ⟶ 1,427:
Open "passwd.txt" For Append Lock Write As #1
Print #1, records(3)
Close #1</
{{out}}
Line 1,194 ⟶ 1,451:
| FB Type || CSV text file || FB Standard Library || ☑ || ☑ || ☑ (Hopefully!)
|}
=={{header|Free Pascal}}==
''See also [[#Pascal|Pascal]]''
{{works with|Linux}}
<syntaxhighlight lang="delphi">{$mode objFPC}
{$longStrings on}
{$modeSwitch classicProcVars+}
uses
cTypes,
// for system call wrappers
unix;
const
passwdPath = '/tmp/passwd';
resourceString
advisoryLockFailed = 'Error: could not obtain advisory lock';
type
GECOS = object
fullname: string;
office: string;
extension: string;
homephone: string;
email: string;
function asString: string;
end;
entry = object
account: string;
password: string;
UID: cUInt;
GID: cUInt;
comment: GECOS;
directory: string;
shell: string;
function asString: string;
end;
function GECOS.asString: string;
const
separator = ',';
begin
with self do
begin
writeStr(result, fullname, separator, office, separator, extension,
separator, homephone, separator, email);
end;
end;
function entry.asString: string;
const
separator = ':';
begin
with self do
begin
writeStr(result, account, separator, password, separator, UID:1,
separator, GID:1, separator, comment.asString, separator, directory,
separator, shell);
end;
end;
procedure writeEntry(var f: text; const value: entry);
begin
writeLn(f, value.asString);
end;
procedure appendEntry(var f: text; const value: entry);
begin
// (re-)open for writing and immediately seek to EOF
append(f);
writeEntry(f, value);
end;
// === MAIN ==============================================================
var
passwd: text;
procedure releaseLock;
begin
// equivalent to `exitCode := exitCode + …`
inc(exitCode, fpFLock(passwd, lock_un));
end;
var
user: entry;
line: string;
begin
assign(passwd, passwdPath);
// open for reading
reset(passwd);
if fpFLock(passwd, lock_ex or lock_NB) <> 0 then
begin
writeLn(stdErr, advisoryLockFailed);
halt(1);
end;
addExitProc(releaseLock);
// reopen for _over_writing: immediately sets file size to 0
rewrite(passwd);
user.account := 'jsmith';
user.password := 'x';
user.UID := 1001;
user.GID := 1000;
user.comment.fullname := 'Joe Smith';
user.comment.office := 'Room 1007';
user.comment.extension := '(234)555-8917';
user.comment.homephone := '(234)555-0077';
user.comment.email := 'jsmith@rosettacode.org';
user.directory := '/home/jsmith';
user.shell := '/bin/bash';
appendEntry(passwd, user);
with user do
begin
account := 'jdoe';
password := 'x';
UID := 1002;
GID := 1000;
with comment do
begin
fullname := 'Jane Doe';
office := 'Room 1004';
extension := '(234)555-8914';
homephone := '(234)555-0044';
email := 'jdoe@rosettacode.org';
end;
directory := '/home/jdoe';
shell := '/bin/bash';
end;
appendEntry(passwd, user);
// Close the file, ...
close(passwd);
with user, user.comment do
begin
account := 'xyz';
UID := 1003;
fullname := 'X Yz';
office := 'Room 1003';
extension := '(234)555-8913';
homephone := '(234)555-0033';
email := 'xyz@rosettacode.org';
directory := '/home/xyz';
end;
// ... then reopen the file for append.
appendEntry(passwd, user);
// open the file and demonstrate the new record has indeed written to the end
reset(passwd);
while not EOF(passwd) do
begin
readLn(passwd, line);
writeLn(line);
end;
end.</syntaxhighlight>
{{out}}
<pre>jsmith:x:1001:1000:Joe Smith,Room 1007,(234)555-8917,(234)555-0077,jsmith@rosettacode.org:/home/jsmith:/bin/bash
jdoe:x:1002:1000:Jane Doe,Room 1004,(234)555-8914,(234)555-0044,jdoe@rosettacode.org:/home/jdoe:/bin/bash
xyz:x:1003:1000:X Yz,Room 1003,(234)555-8913,(234)555-0033,xyz@rosettacode.org:/home/xyz:/bin/bash</pre>
{| class="wikitable" style="text-align: center; margin: 1em auto;"
|+ Append Capabilities.
|-
! colspan="2" | Data Representation
! rowspan="2" | IO<br/>Library
! rowspan="2" | Append<br/>Possible
! rowspan="2" | Automatic<br/>Append
! rowspan="2" | Multi-tasking<br/>Safe
|-
! In core || On disk
|-
| <tt>record</tt> || ASCII text || default <abbr title="run-time library">RTL</abbr> || ☑ || ☐ || ☐
|}
=={{header|FutureBasic}}==
<syntaxhighlight lang="futurebasic">
local fn AppendRecordToFile( pwStr as CFStringRef, url as CFURLRef ) as BOOL
ErrorRef err = NULL
BOOL success = YES
CFDataRef pwData = fn StringData( pwStr, NSUTF8StringEncoding )
FileHandleRef fh = fn FileHandleForWritingToURL( url, @err )
if ( err )
success = fn FileManagerFileExistsAtURL( url )
if success == NO then fn FileManagerCreateFileAtURL( url, pwData, NULL ) : success = YES : exit fn
end if
success = fn FileHandleSeekToEnd( fh, NULL, @err )
if success == NO then print fn ErrorLocalizedDescription( err ) : exit fn
success = fn FileHandleWriteData( fh, pwData, @err )
if success == NO then print fn ErrorLocalizedDescription( err ) : exit fn
success = fn FileHandleClose( fh, @err )
if success == NO then print fn ErrorLocalizedDescription( err ) : exit fn
end fn = success
local fn ReadFileRecords( url as CFURLRef )
ErrorRef err = NULL
CFDataRef pwData = fn DataWithContentsOfURL( url, NSDataReadingMappedIfSafe, @err )
if err then print fn ErrorLocalizedDescription( err ) : exit fn
print fn StringWithData( pwData, NSUTF8StringEncoding )
end fn
local fn ProcessRecords
BOOL success = NO
CFURLRef desktopURL = fn FileManagerURLForDirectory( NSDesktopDirectory, NSUserDomainMask )
CFURLRef url = fn URLByAppendingPathComponent( desktopURL, @"passwords.txt" )
CFArrayRef pwRecords = @[@"account:password:UID:GID:fullname,office,extension,homephone,email:directory:shell\n",¬
@"jsmith:x:1001:1000:Joe Smith,Room 1007,(234)555-8917,(234)555-0077,jsmith@rosettacode.org:/home/jsmith:/bin/bash\n",¬
@"jdoe:x:1002:1000:Jane Doe,Room 1004,(234)555-8914,(234)555-0044,jdoe@rosettacode.org:/home/jdoe:/bin/bash\n"]
NSUInteger i, count = len(pwRecords)
for i = 0 to count - 1
success = fn AppendRecordToFile( pwRecords[i], url )
if success then printf @"Record appended to file." else printf @"Failed to append record."
next
fn ReadFileRecords( url )
end fn
fn ProcessRecords
HandleEvents
</syntaxhighlight>
{{output}}
<pre>
Record appended to file.
Record appended to file.
Record appended to file.
account:password:UID:GID:fullname,office,extension,homephone,email:directory:shell
jsmith:x:1001:1000:Joe Smith,Room 1007,(234)555-8917,(234)555-0077,jsmith@rosettacode.org:/home/jsmith:/bin/bash
jdoe:x:1002:1000:Jane Doe,Room 1004,(234)555-8914,(234)555-0044,jdoe@rosettacode.org:/home/jdoe:/bin/bash
</pre>
=={{header|Go}}==
<
import (
Line 1,296 ⟶ 1,793:
fmt.Println("it didn't work")
}
}</
{{out}}
<pre>
Line 1,324 ⟶ 1,821:
=={{header|Groovy}}==
Solution:
<
String account, password, directory, shell
int uid, gid
Line 1,391 ⟶ 1,888:
w.append('\r\n')
}
}</
Test:
<
File passwd = new File('passwd.txt')
assert passwd.exists()
Line 1,414 ⟶ 1,911:
println "File contents after new record added"
checkPasswdFile()</
Output:
Line 1,428 ⟶ 1,925:
=={{header|Haskell}}==
Solution:
<
{-# LANGUAGE RecordWildCards #-}
Line 1,458 ⟶ 1,955:
addRecord :: String -> Record -> IO ()
addRecord path r = appendFile path (show r)
</syntaxhighlight>
Test:
<
t1 = Record "jsmith" "x" 1001 1000 "/home/jsmith" "/bin/bash"
(Gecos "Joe Smith" "Room 1007" "(234)555-8917" "(234)555-0077" "jsmith@rosettacode.org")
Line 1,476 ⟶ 1,973:
lastLine <- fmap (last . lines) (readFile path)
putStrLn lastLine
</syntaxhighlight>
=={{header|Icon}} and {{header|Unicon}}==
Works in both languages:
<
orig := [
"jsmith:x:1001:1000:Joe Smith,Room 1007,(234)555-8917,(234)555-0077,jsmith@rosettacode.org:/home/jsmith:/bin/bash",
Line 1,492 ⟶ 1,989:
every (f := open(fName,"a")) | write(f,!new) | close(f)
every (f := open(fName,"r")) | write(!f) | close(f)
end</
Run:
Line 1,517 ⟶ 2,014:
=={{header|J}}==
<
record=: [:|: <@deb;._1@(':',]);._2@do bind '0 :0'
Line 1,559 ⟶ 2,056:
R3 fappend passwd
assert 1 e. R3 E. fread passwd </
{|class="wikitable" style="text-align: center; margin: 1em auto 1em auto;"
Line 1,574 ⟶ 2,071:
=={{header|Java}}==
<syntaxhighlight lang="java">
import java.io.IOException;
</syntaxhighlight>
<syntaxhighlight lang="java">
void append(String path, byte[] data) throws IOException {
/* the second argument here is for appending bytes */
try (FileOutputStream output = new FileOutputStream(path, true)) {
output.write(data);
}
}
</syntaxhighlight>
<br />
An alternate implementation.
<syntaxhighlight lang="java">import static java.util.Objects.requireNonNull;
import java.io.IOException;
Line 1,645 ⟶ 2,155:
}
}
}</
{{out}}
<pre>Appended Record: xyz:x:1003:1000:X Yz,Room 1003,(234)555-8913,(234)555-0033,xyz@rosettacode.org:/home/xyz:/bin/bash</pre>
=={{header|Julia}}==
<
using SHA # security instincts say do not write bare passwords to a shared file even in toy code :)
Line 1,697 ⟶ 2,207:
writepasswd(pfile, xyz)
println("After last record added, file is:\n$(readstring(pfile))")
</syntaxhighlight>
{{output}}<pre>
Before last record added, file is:
Line 1,711 ⟶ 2,221:
=={{header|Kotlin}}==
{{works with|Ubuntu 16.04}}
<
import java.io.File
Line 1,766 ⟶ 2,276:
println(parseRecord(it))
}
}</
{{output}}
Line 1,797 ⟶ 2,307:
=={{header|Lua}}==
<
local file,err = io.open(filename, "a")
if err then return err end
Line 1,848 ⟶ 2,358:
xyz.directory = "/home/xyz"
xyz.shell = "/bin/bash"
append(xyz, ".passwd")</
=={{header|M2000 Interpreter}}==
<syntaxhighlight lang="m2000 interpreter">Module TestThis {
Class passwd {
account$, password$
UID, GID
group GECOS {
fullname$,office$,extension$,homephone$,email$
function Line$() {
=format$("{0},{1} {2},{3},{4}", .fullname$,.office$,.extension$,.homephone$,.email$)
}
}
directory$, shell$
Function Line$() {
=format$("{0}:{1}:{2}:{3}:{4}:{5}:{6}",.account$,.password$, .UID, .GID, .GECOS.Line$(), .directory$, .shell$)
}
class:
Module passwd {
if match("SSNNSSSSSSS") then
Read .account$, .password$
Read .UID, .GID
For .GECOS {
Read .fullname$,.office$,.extension$,.homephone$,.email$
}
Read .directory$, .shell$
Else.If Match("S") then
Dim a$(), b$()
a$()=Piece$(letter$, ":")
.account$<=a$(0)
.password$<=a$(1)
.UID<=Val(a$(2))
.GID<=Val(a$(3))
For .GECOS {
b$()=Piece$(a$(4), ",")
.fullname$<=b$(0)
.office$<=Piece$(b$(1), " ")(0)
.extension$<=Piece$(b$(1), " ")(1)
.homephone$<=b$(2)
.email$<=b$(3)
}
.directory$<=a$(5)
.shell$<=a$(6)
End if
}
}
Flush
Data PASSWD("jsmith", "x", 1001, 1000, "Joe Smith", "Room", "1007","(234)555-8917","(234)555-0077","jsmith@rosettacode.org","/home/jsmith","/bin/bash")
Data PASSWD("jdoe:x:1002:1000:Jane Doe,Room 1004,(234)555-8914,(234)555-0044:jdoe@rosettacode.org:/home/jdoe")
\\ we have to make the file if not exist before we use APPEND
if not exist("passwd") then
Open "passwd" for Output as #F
Close #F
end if
Open "passwd" for wide append as #F
While not empty
read A
Print #F, A.Line$()
End While
Close #F
Ret=PASSWD("xyz","x",1003,1000,"X Yz", "Room", "1003", "(234)555-8913", "(234)555-0033", "xyz@rosettacode.org","/home/xyz","/bin/bash")
Repeat
Try ok {
Open "passwd" for wide append exclusive as F
Print #F, Ret.Line$()
close #F
}
Until Not (Error or Not ok)
I=1
Document Ret$
Open "passwd" for wide input as #F
While not Eof(#F)
Line Input #F, record$
Ret$=Format$("{0}|{1}",Str$(I,"0000"),Record$)+{
}
I++
End While
Close #F
ClipBoard Ret$
Report Ret$
}
TestThis
</syntaxhighlight>
{{out}}
<pre>
0001|jsmith:x:1001:1000:Joe Smith,Room 1007,(234)555-8917,(234)555-0077:jsmith@rosettacode.org:/home/jsmith
0002|jdoe:x:1002:1000:Jane Doe,Room 1004,(234)555-8914,(234)555-0044:jdoe@rosettacode.org:/home/jdoe
0003|xyz:x:1003:1000:X Yz,Room 1003,(234)555-8913,(234)555-0033:xyz@rosettacode.org:/home/xyz
</pre>
=={{header|Mathematica}} / {{header|Wolfram Language}}==
<
"GID" -> 1000, "fullname" -> "X Yz", "office" -> "Room 1003",
"extension" -> "(234)555-8913", "homephone" -> "(234)555-0033",
Line 1,867 ⟶ 2,465:
str = OpenWrite[fname]; (* Use OpenAppend if file exists *)
Close[str];
Print["Appended record: " <> asString[data]];</
{{out}}
<pre>Appended record: xyz:x:1003:1000:X Yz,Room 1003,(234)555-8913,(234)555-0033,xyz@rosettacode.org:/home/xyz:/bin/bash</pre>
Line 1,885 ⟶ 2,483:
=={{header|MATLAB}} / {{header|Octave}}==
<
DS{1}.password='x';
DS{1}.UID=1001;
Line 1,942 ⟶ 2,540:
printf('%s\n',fgetl(fid));
end;
fclose(fid); </
{{out}}
<pre>jsmith:x:1001:1000:Joe Smith,Room 1007,(234)555-8917,(234)555-0077,jsmith@rosettacode.org:/home/jsmith/bin/bash
Line 1,948 ⟶ 2,546:
xyz:x:1003:1000:X Yz,Room 1003,(234)555-8913,(234)555-0033,xyz@rosettacode.org:/home/xyz/bin/bash
</pre>
=={{header|Nim}}==
This solution defines a procedure "getlock" which try the get an exclusive (write) lock on the file. On Posix systems, the standard Posix advisory locking mechanism, which works at process level, is used. On other systems, especially Windows, the procedure does nothing and returns true as there is no need for such a mechanism.
Note that on Posix system, other programs may still write on the file if they do not check if an exclusive lock is already set on the file.
As several other solutions, we have chosen to parse the "passwd" lines even if it not required.
<syntaxhighlight lang="nim">import posix
import strutils
type
# GECOS representation.
Gecos = tuple[fullname, office, extension, homephone, email: string]
# Record representation.
Record = object
account: string
password: string
uid: int
gid: int
gecos: Gecos
directory: string
shell: string
#---------------------------------------------------------------------------------------------------
proc str(gecos: Gecos): string =
## Explicit representation of a GECOS.
result = "("
for name, field in gecos.fieldPairs:
result.addSep(", ", 1)
result.add(name & ": " & field)
result.add(')')
#---------------------------------------------------------------------------------------------------
proc `$`(gecos: Gecos): string =
## Compact representation of a GECOS.
for field in gecos.fields:
result.addSep(",", 0)
result.add(field)
#---------------------------------------------------------------------------------------------------
proc parseGecos(s: string): Gecos =
## Parse a string and return a Gecos tuple.
let fields = s.split(",")
result = (fields[0], fields[1], fields[2], fields[3], fields[4])
#---------------------------------------------------------------------------------------------------
proc str(rec: Record): string =
## Explicit representation of a record.
for name, field in rec.fieldPairs:
result.add(name & ": ")
when typeof(field) is Gecos:
result.add(str(field))
else:
result.add($field)
result.add('\n')
#---------------------------------------------------------------------------------------------------
proc `$`(rec: Record): string =
# Compact representation fo a record.
for field in rec.fields:
result.addSep(":", 0)
result.add($field)
#---------------------------------------------------------------------------------------------------
proc parseRecord(line: string): Record =
## Parse a string and return a Record object.
let fields = line.split(":")
result.account = fields[0]
result.password = fields[1]
result.uid = fields[2].parseInt()
result.gid = fields[3].parseInt()
result.gecos = parseGecos(fields[4])
result.directory = fields[5]
result.shell = fields[6]
#---------------------------------------------------------------------------------------------------
proc getLock(f: File): bool =
## Try to get an exclusive write lock on file "f". Return false is unsuccessful.
when defined(posix):
var flock = TFlock(l_type: cshort(F_WRLCK), l_whence: cshort(SEEK_SET), l_start: 0, l_len: 0)
result = f.getFileHandle().fcntl(F_SETLK, flock.addr) >= 0
else:
result = true
#———————————————————————————————————————————————————————————————————————————————————————————————————
var pwfile: File
const Filename = "passwd"
const Data = ["jsmith:x:1001:1000:Joe Smith,Room 1007,(234)555-8917,(234)555-0077,jsmith@rosettacode.org:/home/jsmith:/bin/bash",
"jdoe:x:1002:1000:Jane Doe,Room 1004,(234)555-8914,(234)555-0044,jdoe@rosettacode.org:/home/jdoe:/bin/bash"]
# Prepare initial file.
# We don'’t use a lock here as it is only the preparation.
pwfile = open(FileName, fmWrite)
for line in Data:
pwfile.writeLine(line)
pwfile.close()
# Display initial contents.
echo "Raw content of initial password file:"
echo "-------------------------------------"
var records: seq[Record]
for line in lines(FileName):
echo line
records.add(line.parseRecord())
echo ""
echo "Structured content of initial password file:"
echo "--------------------------------------------"
for rec in records:
echo str(rec)
# Add a new record at the end of password file.
pwfile = open(Filename, fmAppend)
let newRecord = Record(account: "xyz",
password: "x",
uid: 1003,
gid: 1000,
gecos: ("X Yz", "Room 1003", "(234)555-8913", "(234)555-0033", "xyz@rosettacode.org"),
directory: "/home/xyz",
shell: "/bin/bash")
echo "Appending new record:"
echo "---------------------"
echo str(newRecord)
if pwfile.getLock():
pwFile.writeLine(newRecord)
pwfile.close()
else:
echo "File is locked. Quitting."
pwFile.close()
quit(QuitFailure)
# Reopen the file and display its contents.
echo "Raw content of updated password file:"
echo "-------------------------------------"
for line in lines(FileName):
echo line</syntaxhighlight>
{{out}}
<pre>Raw content of initial password file:
-------------------------------------
jsmith:x:1001:1000:Joe Smith,Room 1007,(234)555-8917,(234)555-0077,jsmith@rosettacode.org:/home/jsmith:/bin/bash
jdoe:x:1002:1000:Jane Doe,Room 1004,(234)555-8914,(234)555-0044,jdoe@rosettacode.org:/home/jdoe:/bin/bash
Structured content of initial password file:
--------------------------------------------
account: jsmith
password: x
uid: 1001
gid: 1000
gecos: (fullname: Joe Smith, office: Room 1007, extension: (234)555-8917, homephone: (234)555-0077, email: jsmith@rosettacode.org)
directory: /home/jsmith
shell: /bin/bash
account: jdoe
password: x
uid: 1002
gid: 1000
gecos: (fullname: Jane Doe, office: Room 1004, extension: (234)555-8914, homephone: (234)555-0044, email: jdoe@rosettacode.org)
directory: /home/jdoe
shell: /bin/bash
Appending new record:
---------------------
account: xyz
password: x
uid: 1003
gid: 1000
gecos: (fullname: X Yz, office: Room 1003, extension: (234)555-8913, homephone: (234)555-0033, email: xyz@rosettacode.org)
directory: /home/xyz
shell: /bin/bash
Raw content of updated password file:
-------------------------------------
jsmith:x:1001:1000:Joe Smith,Room 1007,(234)555-8917,(234)555-0077,jsmith@rosettacode.org:/home/jsmith:/bin/bash
jdoe:x:1002:1000:Jane Doe,Room 1004,(234)555-8914,(234)555-0044,jdoe@rosettacode.org:/home/jdoe:/bin/bash
xyz:x:1003:1000:X Yz,Room 1003,(234)555-8913,(234)555-0033,xyz@rosettacode.org:/home/xyz:/bin/bash</pre>
{|class="wikitable" style="text-align: center; margin: 1em auto 1em auto;"
|+ Append Capabilities.
|-
!colspan=2| Data Representation
!rowspan=2| IO<BR>Library
!rowspan=2| Append<BR>Possible
!rowspan=2| Automatic<BR>Append
!rowspan=2| Multi-tasking<BR>Safe
|-
! In core || On disk
|-
| Object/Tuple || Text file || Nim Io || ☑ || ☑ || Window: yes<br/>Posix: Advisory lock
|}
=={{header|Pascal}}==
''See also: [[#Free Pascal|Free Pascal]]''
{{works with|Extended Pascal}}
<syntaxhighlight lang="pascal">program appendARecordToTheEndOfATextFile;
var
passwd: bindable text;
FD: bindingType;
begin
{ initialize FD }
FD := binding(passwd);
FD.name := '/tmp/passwd';
{ attempt opening file [e.g. effective user has proper privileges?] }
bind(passwd, FD);
{ query binding state of `passwd` }
FD := binding(passwd);
if not FD.bound then
begin
writeLn('Error: could not open ', FD.name);
halt;
end;
{ open for overwriting }
rewrite(passwd);
writeLn(passwd, 'jsmith:x:1001:1000:Joe Smith,Room 1007,(234)555-8917,(234)555-0077,jsmith@rosettacode.org:/home/jsmith:/bin/bash');
writeLn(passwd, 'jdoe:x:1002:1000:Jane Doe,Room 1004,(234)555-8914,(234)555-0044,jdoe@rosettacode.org:/home/jdoe:/bin/bash');
{ close }
unbind(passwd);
{ rebind }
bind(passwd, FD);
FD := binding(passwd);
if not FD.bound then
begin
writeLn('Error: could not reopen ', FD.name);
halt;
end;
{ open in append/writable mode }
extend(passwd);
{ write another record to file }
writeLn(passwd, 'xyz:x:1003:1000:X Yz,Room 1003,(234)555-8913,(234)555-0033,xyz@rosettacode.org:/home/xyz:/bin/bash');
end.</syntaxhighlight>
{| class="wikitable" style="text-align: center; margin: 1em auto;"
|+ Append Capabilities.
|-
! colspan="2" | Data Representation
! rowspan="2" | IO<br/>Library
! rowspan="2" | Append<br/>Possible
! rowspan="2" | Automatic<br/>Append
! rowspan="2" | Multi-tasking<br/>Safe
|-
! In core || On disk
|-
| string literal || ASCII text || language core || ☑ || ☐ || ☐
|}
=={{header|Perl}}==
The program uses flock(2) (or emulation, if flock is not available) to lock the file.
<
use warnings;
Line 2,057 ⟶ 2,931:
);
}
</syntaxhighlight>
Output:
Line 2,104 ⟶ 2,978:
same process, in which case locking does not make any real difference - because there is no task_yield() in a locked state.
You can also test the locking when running multiple processes/threads by uncommenting the wait_key() lines.
<!--<syntaxhighlight lang="phix">(notonline)-->
<span style="color: #008080;">without</span> <span style="color: #008080;">js</span> <span style="color: #000080;font-style:italic;">-- (file i/o, sleep, task_yield, wait_key)</span>
<span style="color: #008080;">constant</span> <span style="color: #000000;">filename</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"passwd.txt"</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">fn</span>
<span style="color: #008080;">constant</span>
<span style="color: #000000;">rec1</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #008000;">"jsmith"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"x"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1001</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1000</span><span style="color: #0000FF;">,{</span><span style="color: #008000;">"Joe Smith"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"Room 1007"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"(234)555-8917"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"(234)555-0077"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"jsmith@rosettacode.org"</span><span style="color: #0000FF;">},</span><span style="color: #008000;">"/home/jsmith"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"/bin/bash"</span><span style="color: #0000FF;">},</span>
<span style="color: #000000;">rec2</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #008000;">"jdoe"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"x"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1002</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1000</span><span style="color: #0000FF;">,{</span><span style="color: #008000;">"Jane Doe"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"Room 1004"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"(234)555-8914"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"(234)555-0044"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"jdoe@rosettacode.org"</span><span style="color: #0000FF;">},</span><span style="color: #008000;">"/home/jdoe"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"/bin/bash"</span><span style="color: #0000FF;">},</span>
<span style="color: #000000;">rec3</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #008000;">"xyz"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"x"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1003</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1000</span><span style="color: #0000FF;">,{</span><span style="color: #008000;">"X Yz"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"Room 1003"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"(234)555-8913"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"(234)555-0033"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"xyz@rosettacode.org"</span><span style="color: #0000FF;">},</span><span style="color: #008000;">"/home/xyz"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"/bin/bash"</span><span style="color: #0000FF;">}</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">tostring</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">record</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">record</span><span style="color: #0000FF;">[</span><span style="color: #000000;">3</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">sprintf</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"%d"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">record</span><span style="color: #0000FF;">[</span><span style="color: #000000;">3</span><span style="color: #0000FF;">]})</span>
<span style="color: #000000;">record</span><span style="color: #0000FF;">[</span><span style="color: #000000;">4</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">sprintf</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"%d"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">record</span><span style="color: #0000FF;">[</span><span style="color: #000000;">4</span><span style="color: #0000FF;">]})</span>
<span style="color: #000000;">record</span><span style="color: #0000FF;">[</span><span style="color: #000000;">5</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">join</span><span style="color: #0000FF;">(</span><span style="color: #000000;">record</span><span style="color: #0000FF;">[</span><span style="color: #000000;">5</span><span style="color: #0000FF;">],</span><span style="color: #008000;">","</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">record</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">join</span><span style="color: #0000FF;">(</span><span style="color: #000000;">record</span><span style="color: #0000FF;">,</span><span style="color: #008000;">":"</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">record</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">procedure</span> <span style="color: #000000;">wait</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">what</span><span style="color: #0000FF;">)</span>
<span style="color: #0000FF;">?</span><span style="color: #7060A8;">sprintf</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"wait (%s)"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">what</span><span style="color: #0000FF;">})</span>
<span style="color: #7060A8;">sleep</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">task_yield</span><span style="color: #0000FF;">()</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
<span style="color: #008080;">if</span> <span style="color: #008080;">not</span> <span style="color: #7060A8;">file_exists</span><span style="color: #0000FF;">(</span><span style="color: #000000;">filename</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">fn</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">open</span><span style="color: #0000FF;">(</span><span style="color: #000000;">filename</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"w"</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">fn</span><span style="color: #0000FF;">!=-</span><span style="color: #000000;">1</span> <span style="color: #008080;">then</span> <span style="color: #000080;font-style:italic;">-- (someone else just beat us to it?)</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">fn</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"account:password:UID:GID:fullname,office,extension,homephone,email:directory:shell\n"</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">fn</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%s\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">tostring</span><span style="color: #0000FF;">(</span><span style="color: #000000;">rec1</span><span style="color: #0000FF;">)})</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">fn</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%s\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">tostring</span><span style="color: #0000FF;">(</span><span style="color: #000000;">rec2</span><span style="color: #0000FF;">)})</span>
<span style="color: #7060A8;">close</span><span style="color: #0000FF;">(</span><span style="color: #000000;">fn</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">while</span> <span style="color: #000000;">1</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">fn</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">open</span><span style="color: #0000FF;">(</span><span style="color: #000000;">filename</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"a"</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">fn</span><span style="color: #0000FF;">!=-</span><span style="color: #000000;">1</span> <span style="color: #008080;">then</span> <span style="color: #008080;">exit</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #000000;">wait</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"append"</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
<span style="color: #000080;font-style:italic;">--?"file open in append mode"; {} = wait_key()</span>
<span style="color: #008080;">while</span> <span style="color: #000000;">1</span> <span style="color: #008080;">do</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">lock_file</span><span style="color: #0000FF;">(</span><span style="color: #000000;">fn</span><span style="color: #0000FF;">,</span><span style="color: #000000;">LOCK_EXCLUSIVE</span><span style="color: #0000FF;">,{})</span> <span style="color: #008080;">then</span> <span style="color: #008080;">exit</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #000000;">wait</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"lock"</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
<span style="color: #000080;font-style:italic;">--?"file locked"; {} = wait_key()</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">fn</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%s\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">tostring</span><span style="color: #0000FF;">(</span><span style="color: #000000;">rec3</span><span style="color: #0000FF;">)})</span>
<span style="color: #000000;">unlock_file</span><span style="color: #0000FF;">(</span><span style="color: #000000;">fn</span><span style="color: #0000FF;">,{})</span>
<span style="color: #7060A8;">close</span><span style="color: #0000FF;">(</span><span style="color: #000000;">fn</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">while</span> <span style="color: #000000;">1</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">fn</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">open</span><span style="color: #0000FF;">(</span><span style="color: #000000;">filename</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"r"</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">fn</span><span style="color: #0000FF;">!=-</span><span style="color: #000000;">1</span> <span style="color: #008080;">then</span> <span style="color: #008080;">exit</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #000000;">wait</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"read"</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
<span style="color: #0000FF;">?</span><span style="color: #7060A8;">gets</span><span style="color: #0000FF;">(</span><span style="color: #000000;">fn</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">while</span> <span style="color: #000000;">1</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">object</span> <span style="color: #000000;">line</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">gets</span><span style="color: #0000FF;">(</span><span style="color: #000000;">fn</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #004080;">atom</span><span style="color: #0000FF;">(</span><span style="color: #000000;">line</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span> <span style="color: #008080;">exit</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #0000FF;">?</span><span style="color: #000000;">line</span>
<span style="color: #0000FF;">{</span><span style="color: #000000;">line</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">scanf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">line</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%s:%s:%d:%d:%s:%s:%s\n"</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">line</span><span style="color: #0000FF;">[</span><span style="color: #000000;">5</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">split</span><span style="color: #0000FF;">(</span><span style="color: #000000;">line</span><span style="color: #0000FF;">[</span><span style="color: #000000;">5</span><span style="color: #0000FF;">],</span><span style="color: #008000;">','</span><span style="color: #0000FF;">)</span>
<span style="color: #0000FF;">?</span><span style="color: #000000;">line</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
<span style="color: #7060A8;">close</span><span style="color: #0000FF;">(</span><span style="color: #000000;">fn</span><span style="color: #0000FF;">)</span>
<!--</syntaxhighlight>-->
{{out}}
<pre>
Line 2,175 ⟶ 3,052:
{"xyz","x",1003,1000,{"X Yz","Room 1003","(234)555-8913","(234)555-0033","xyz@rosettacode.org"},"/home/xyz","/bin/bash"}
</pre>
=={{header|Phixmonti}}==
<syntaxhighlight lang="phixmonti">include ..\Utilitys.pmt
def ltos /# l -- s #/
"" >ps
len for get
string? not if
number? if
tostr
else
ltos
"<ls>:" swap "</ls>" chain chain
endif
endif
ps> swap chain ":" chain >ps
endfor
drop
ps>
enddef
def stol /# s -- l #/
-1 del
":" xplit
"<ls>" find 1 + snip
"</ls>" find snip 1 del
rot len >ps rot ps> set swap chain
enddef
( "jsmith" "x" 1001 1000 ( "Joe Smith" "Room 1007" "(234)555-8917" "(234)555-0077" "jsmith@rosettacode.org" ) "/home/jsmith" "/bin/bash" )
( "jdoe" "x" 1002 1000 ( "Jane Doe" "Room 1004" "(234)555-8914" "(234)555-0044" "jdoe@rosettacode.org" ) "/home/jdoe" "/bin/bash" )
swap
"passwd.txt" var file
file "w" fopen var f
ltos 10 chain f fputs
ltos 10 chain f fputs
f fclose
( "xyz" "x" 1003 1000 ( "X Yz" "Room 1003" "(234)555-8913" "(234)555-0033" "xyz@rosettacode.org" ) "/home/xyz" "/bin/bash" )
file "a" fopen var f
ltos 10 chain f fputs
f fclose
file "r" fopen var f
true while
f fgets number? if
drop false
else
stol ? true
endif
endwhile
f fclose</syntaxhighlight>
{{out}}
<pre>["jsmith", "x", "1001", "1000", ["Joe Smith", "Room 1007", "(234)555-8917", "(234)555-0077", "jsmith@rosettacode.org"], "/home/jsmith", "/bin/bash"]
["jdoe", "x", "1002", "1000", ["Jane Doe", "Room 1004", "(234)555-8914", "(234)555-0044", "jdoe@rosettacode.org"], "/home/jdoe", "/bin/bash"]
["xyz", "x", "1003", "1000", ["X Yz", "Room 1003", "(234)555-8913", "(234)555-0033", "xyz@rosettacode.org"], "/home/xyz", "/bin/bash"]
=== Press any key to exit ===</pre>
=={{header|PHP}}==
Line 2,192 ⟶ 3,133:
|}
<
$filename = '/tmp/passwd';
Line 2,211 ⟶ 3,152:
echo 'File contents after new record added:', PHP_EOL, file_get_contents($filename), PHP_EOL;
</syntaxhighlight>
{{out}}
Line 2,226 ⟶ 3,167:
=={{header|PicoLisp}}==
<
"Joe Smith,Room 1007,(234)555-8917,\
(234)555-0077,jsmith@rosettacode.org"
Line 2,252 ⟶ 3,193:
(= 3 (lines "mythical") ) ) ) )
(bye)</
=={{header|PowerShell}}==
Line 2,258 ⟶ 3,199:
Since PowerShell loves to deal in objects I wrote extra code to better manipilate and display data.
<syntaxhighlight lang="powershell">
function Test-FileLock
{
Line 2,422 ⟶ 3,363:
}
}
</syntaxhighlight>
Create record objects.
<syntaxhighlight lang="powershell">
$records = @()
Line 2,450 ⟶ 3,391:
-Directory '/home/jdoe' `
-Shell '/bin/bash'
</syntaxhighlight>
Display record objects.
<syntaxhighlight lang="powershell">
$records | Format-Table -AutoSize
</syntaxhighlight>
{{Out}}
<pre>
Line 2,463 ⟶ 3,404:
</pre>
Export records to file.
<syntaxhighlight lang="powershell">
if (-not(Test-FileLock -Path ".\passwd.txt"))
{
$records | Export-File -Path ".\passwd.txt"
}
</syntaxhighlight>
This is the file.
<syntaxhighlight lang="powershell">
Get-Content -Path ".\passwd.txt"
</syntaxhighlight>
{{Out}}
<pre>
Line 2,479 ⟶ 3,420:
</pre>
Add a record to the record set.
<syntaxhighlight lang="powershell">
$records+= New-Record -Account 'xyz' `
-Password 'x' `
Line 2,491 ⟶ 3,432:
-Directory '/home/xyz' `
-Shell '/bin/bash'
</syntaxhighlight>
Display record objects, sorted on last name; and display them.
<syntaxhighlight lang="powershell">
$records | Sort-Object { $_.GECOS.FullName.Split(" ")[1] } | Format-Table -AutoSize
</syntaxhighlight>
{{Out}}
<pre>
Line 2,505 ⟶ 3,446:
</pre>
Export records to file.
<syntaxhighlight lang="powershell">
if (-not(Test-FileLock -Path ".\passwd.txt"))
{
$records | Export-File -Path ".\passwd.txt"
}
</syntaxhighlight>
This is the file.
<syntaxhighlight lang="powershell">
Get-Content -Path ".\passwd.txt"
</syntaxhighlight>
{{Out}}
<pre>
Line 2,565 ⟶ 3,506:
|}
'''From a "dict" to a CSV File'''
<
# Create a passwd text file
#############################
Line 2,612 ⟶ 3,553:
passwd_list=list(open("passwd.txt","r"))
if "xyz" in passwd_list[-1]:
print "Appended record:",passwd_list[-1][:-1]</
{{out}}
<pre>Appended record: xyz:x:1003:1000:X Yz,Room 1003,(234)555-8913,(234)555-0033,xyz@rosettacode.org:/home/xyz:/bin/bash</pre>
Line 2,634 ⟶ 3,575:
|}
<
#lang racket
Line 2,671 ⟶ 3,612:
(printf "Looking up xyz in current file:\n=> ~s\n" (lookup "xyz"))
</syntaxhighlight>
{{out}}
Line 2,687 ⟶ 3,628:
This is kind of silly as it takes a string, converts it to a record, and then instantly converts it back to a string to write out to a file. Most of the "record handling" code is just demonstrating a possible way to store records in memory. It really has nothing to do with appending a string to a file.
<syntaxhighlight lang="raku"
has $.name;
has $.password;
Line 2,753 ⟶ 3,694:
put "Last line of $fname after append:";
put $fname.IO.lines.tail;
</syntaxhighlight>
{{out}}
<pre>Last line of foo.fil before append:
Line 2,791 ⟶ 3,732:
|}
'''The easy short solution'''
<syntaxhighlight lang="vb">
'Short solution: Append record and read last record
$Include "Rapidq.inc"
Line 2,820 ⟶ 3,761:
showmessage "Appended record: " + LogRec
</syntaxhighlight>
{{out}}
<pre>Appended record: xyz:x:1003:1000:X Yz,Room 1003,(234)555-8913,(234)555-0033,xyz@rosettacode.org:/home/xyz:/bin/bash</pre>
'''Full solution: create an object to handle all functions'''
<syntaxhighlight lang="vb">
'Full solution: Create an object with all required fields and
'build-in functions to append a record and to read the last record
Line 2,971 ⟶ 3,912:
Print ""
input "Press enter to exit:";a$
</syntaxhighlight>
=={{header|REXX}}==
Line 2,989 ⟶ 3,930:
The data fields for the three records were coded on two statements instead of
<br>continuing them on separate statements for brevity.
<
tFID= 'PASSWD.TXT' /*define the name of the output file.*/
call lineout tFID /*close the output file, just in case,*/
Line 3,024 ⟶ 3,965:
say '***error***'; say r 'record's(r) "not written to file" fid; exit 13
/*some error causes: no write access, disk is full, file lockout, no authority*/</
'''PASSWD.TXT''' file before the REXX program ran:
<pre>
Line 3,051 ⟶ 3,992:
| objects (subclass of Struct builtin) || text file || builtin || ☑ || ☑ || ☒
|}
<
class Gecos
def to_s
Line 3,086 ⟶ 4,027:
puts "after appending:"
puts File.readlines(filename)</
{{out}}
<pre>
Line 3,099 ⟶ 4,040:
=={{header|Rust}}==
<
use std::fs::File;
use std::fs::OpenOptions;
Line 3,271 ⟶ 4,212:
}
}
</syntaxhighlight>
{{out}}
<pre>
Line 3,285 ⟶ 4,226:
=={{header|Scala}}==
{{libheader|Scala}}<
import scala.io.Source
Line 3,340 ⟶ 4,281:
case e: IOException => println(s"Running Example failed: ${e.getMessage}")
}
} // 57 lines</
=={{header|Scheme}}==
{{works with|Chez Scheme}}
<syntaxhighlight lang="scheme">; Join list of strings into single string, with given separator between elements.
(define string-join
(lambda (str-lst sep)
(fold-right (lambda (ele acc) (if (string=? acc "") ele (string-append ele sep acc)))
""
str-lst)))
; Define the output file name and the three records to write to it.
(let ((filename
"mimic-passwd.txt")
(record1
(string-join
(list
"jsmith" "x" "1001" "1000"
(string-join
'("Joe Smith" "Room 1007" "(234)555-8917" "(234)555-0077" "jsmith@rosettacode.org")
",")
"/home/jsmith" "/bin/bash")
":"))
(record2
(string-join
(list
"jdoe" "x" "1002" "1000"
(string-join
'("Jane Doe" "Room 1004" "(234)555-8914" "(234)555-0044" "jdoe@rosettacode.org")
",")
"/home/jdoe" "/bin/bash")
":"))
(record3
(string-join
(list
"xyz" "x" "1003" "1000"
(string-join
'("X Yz" "Room 1003" "(234)555-8913" "(234)555-0033" "xyz@rosettacode.org")
",")
"/home/xyz" "/bin/bash")
":")))
; Write the first two records to the output file.
; Replace any existing file. Lock file for exclusive access.
(let ((op (open-file-output-port filename
(file-options replace exclusive)
'line
(make-transcoder (latin-1-codec) 'lf))))
(format op "~a~%" record1)
(format op "~a~%" record2)
(close-output-port op))
; Append the third record to the output file.
; Open existing file keeping contents. Append to file. Lock file for exclusive access.
(let ((op (open-file-output-port filename
(file-options no-fail no-truncate append exclusive)
'line
(make-transcoder (latin-1-codec) 'lf))))
(format op "~a~%" record3)
(close-output-port op)))</syntaxhighlight>
{{out}}
<pre>
jsmith:x:1001:1000:Joe Smith,Room 1007,(234)555-8917,(234)555-0077,jsmith@rosettacode.org:/home/jsmith:/bin/bash
jdoe:x:1002:1000:Jane Doe,Room 1004,(234)555-8914,(234)555-0044,jdoe@rosettacode.org:/home/jdoe:/bin/bash
xyz:x:1003:1000:X Yz,Room 1003,(234)555-8913,(234)555-0033,xyz@rosettacode.org:/home/xyz:/bin/bash
</pre>
{|class="wikitable" style="text-align: center; margin: 1em auto 1em auto;"
|+ Append Capabilities.
|-
!colspan=2| Data Representation
!rowspan=2| IO<BR>Library
!rowspan=2| Append<BR>Possible
!rowspan=2| Automatic<BR>Append
!rowspan=2| Multi-tasking<BR>Safe
|-
! In core || On disk
|-
| lists || text file || built-in || ☑ || ☑ || ☑ (system dependent)
|}
=={{header|Sidef}}==
Line 3,358 ⟶ 4,376:
|}
<
RECORD_FIELDS = %w(account password UID GID GECOS directory shell),
GECOS_FIELDS = %w(fullname office extension homephone email),
Line 3,455 ⟶ 4,473:
'(234)555-0033,xyz@rosettacode.org:/home/xyz:/bin/bash')
say "** Test passed!"</
Note that flock uses advisory lock; some other program (if it doesn't use flock) can still unexpectedly write to the file.
=={{header|Swift}}==
<syntaxhighlight lang="swift">
import Foundation
func appendPasswd(
account: String,
passwd: String,
uid: Int,
gid: Int,
bio: String,
home: String,
shell: String
) {
let str = [
account,
passwd,
String(uid),
String(gid),
bio,
home,
shell
].joined(separator: ":").appending("\n")
guard let data = str.data(using: .utf8) else { return }
let url = URL(fileURLWithPath: "./passwd")
do {
if let fileHandle = try? FileHandle(forWritingTo: url) {
fileHandle.seekToEndOfFile()
fileHandle.write(data)
try? fileHandle.close()
} else {
try data.write(to: url)
}
} catch {
print(error)
}
}
</syntaxhighlight>
Usage:
<syntaxhighlight lang="swift">
appendPasswd(
account: "jsmith",
passwd:"x",
uid: 1001,
gid: 1000,
bio: "Joe Smith,Room 1007,(234)555-8917,(234)555-0077,jsmith@rosettacode.org",
home: "/home/jsmith",
shell: "/bin/bash"
)
</syntaxhighlight>
=={{header|Tcl}}==
Line 3,474 ⟶ 4,541:
|}
Note that appending is only safe on POSIX OSes where the data is written in “small enough” amounts to a local disk. This is a limitation of the OS APIs.
<
set basicRecords {
{
Line 3,558 ⟶ 4,625:
set recs [readRecords $f]
close $f
puts "last record is for [lindex $recs end 0], named [lindex $recs end 4 0]"</
last record is for xyz, named X Yz
The file will have this content:
Line 3,579 ⟶ 4,646:
| one-dimensional arrays (indexed or associative) || text file || builtin (shell redirections) || ☑ || ☑ || OS defined
|}
<
jsmith
x
Line 3,627 ⟶ 4,694:
echo after appending:
cat "$filename"</
{{output}}
Line 3,640 ⟶ 4,707:
=={{header|Ursa}}==
{{trans|Awk}}
<
# create new passwd in working directory
Line 3,667 ⟶ 4,734:
while (f.hasline)
out (in string f) endl console
end while</
=={{header|Visual Basic .NET}}==
{{trans|C#}}
<
Module Module1
Line 3,724 ⟶ 4,791:
End Sub
End Module</
{{out}}
<pre>Appended record: xyz:x:1003:1000:X Yz,Room 1003,(234)555-8913,(234)555-0033,xyz@rosettacode.org:/home/xyz:/bin/bash</pre>
=={{header|Wren}}==
Although Wren has basic classes to work with the file system, these are only available when creating standalone scripts using the command line interpreter (CLI) and not when Wren is being embedded. In the latter case it relies on the host application for such support.
To append a record to an existing file in a CLI script, a little digging is required as the method to do this (''File.openWithFlags'') is currently undocumented. However, the following works fine.
<syntaxhighlight lang="wren">import "io" for File, FileFlags
var records = [
"jsmith:x:1001:1000:Joe Smith,Room 1007,(234)555-8917,(234)555-0077,[email protected]:/home/jsmith:/bin/bash",
"jdoe:x:1002:1000:Jane Doe,Room 1004,(234)555-8914,(234)555-0044,[email protected]:/home/jdoe:/bin/bash"
]
// Write records to a new file called "passwd.csv" and close it.
var fileName = "passwd.csv"
File.create(fileName) {|file|
records.each { |r| file.writeBytes(r + "\n") }
}
// Check file has been created correctly.
var contents = File.read(fileName)
System.print("Initial records:\n")
System.print(contents)
var newRec = "xyz:x:1003:1000:X Yz,Room 1003,(234)555-8913,(234)555-0033,[email protected]:/home/xyz:/bin/bash"
// Append the new record to the file and close it.
File.openWithFlags(fileName, FileFlags.writeOnly) { |file|
file.writeBytes(newRec + "\n")
}
// Check the new record has been appended correctly.
contents = File.read(fileName)
System.print("Records after appending new one:\n")
System.print(contents)</syntaxhighlight>
{{out}}
<pre>
Initial records:
jsmith:x:1001:1000:Joe Smith,Room 1007,(234)555-8917,(234)555-0077,[email protected]:/home/jsmith:/bin/bash
jdoe:x:1002:1000:Jane Doe,Room 1004,(234)555-8914,(234)555-0044,[email protected]:/home/jdoe:/bin/bash
Records after appending new one:
jsmith:x:1001:1000:Joe Smith,Room 1007,(234)555-8917,(234)555-0077,[email protected]:/home/jsmith:/bin/bash
jdoe:x:1002:1000:Jane Doe,Room 1004,(234)555-8914,(234)555-0044,[email protected]:/home/jdoe:/bin/bash
xyz:x:1003:1000:X Yz,Room 1003,(234)555-8913,(234)555-0033,[email protected]:/home/xyz:/bin/bash
</pre>
{|class="wikitable" style="text-align: center; margin: 1em auto 1em auto;"
|+ Append Capabilities.
|-
!colspan=2| Data Representation
!rowspan=2| IO<BR>Library
!rowspan=2| Append<BR>Possible
!rowspan=2| Automatic<BR>Append
!rowspan=2| Multi-tasking<BR>Safe
|-
! In core || On disk
|-
| Wren string / class || CSV text file || Wren io module / libuv || ☑ || ☒ || ☑ (AFAIK)
|}
<br>
=={{header|Yabasic}}==
<
// If the file does not exist, it will be created.
Line 3,767 ⟶ 4,897:
wend
close #a</
=={{header|zkl}}==
Line 3,784 ⟶ 4,914:
|}
{{trans|Ruby}}
<
gnames=T("fullname","office","extension","homephone","email"),
pnames=T("account","password","uid","gid","gecos","directory","shell");
Line 3,797 ⟶ 4,927:
fcn init(str){ pnames.zipWith(setVar,vm.arglist) }
fcn toString { pnames.apply(setVar).concat(":") }
}</
The class setVar method takes one or two parameters. With two, it sets the named class variable to a value; with one, it gets the var.
If there aren't enough parameters, the missing ones with be set to Void (yeah, poor error checking).
<
p:=str.strip().split(":");
g:=Gecos(p[4].split(",").xplode());
Passwd(p[0,4].xplode(),g,p[5,*].xplode());
}</
The List xplode method pushes the list contents to the parameter list.
<
Gecos("Joe Smith", "Room 1007", "(234)555-8917", "(234)555-0077", "jsmith@rosettacode.org"),
"/home/jsmith", "/bin/bash");
Line 3,821 ⟶ 4,951:
f.writeln(xyz); f.close();
File(filename).read().text.print(); // print file</
{{out}}
<pre>
Line 3,828 ⟶ 4,958:
xyz:x:1003:1000:X Yz,Room 1003,(234)555-8913,(234)555-0033,xyz@rosettacode.org:/home/xyz:/bin/bash
</pre>
{{omit from|EasyLang}}
|