How to resolve the algorithm Append a record to the end of a text file step by step in the Nim programming language

Published on 12 May 2024 09:40 PM

How to resolve the algorithm Append a record to the end of a text file step by step in the Nim programming language

Table of Contents

Problem Statement

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.

Given a two record sample for a mythical "passwd" file: Resulting file format: should mimic Linux's /etc/passwd file format with particular attention to the "," separator used in the GECOS field. But if the specific language has a particular or unique format of storing records in text file, then this format should be named and demonstrated with an additional example. Expected output: Finally: Provide a summary of the language's "append record" capabilities in a table. eg. 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.

Let's start with the solution:

Step by Step solution about How to resolve the algorithm Append a record to the end of a text file step by step in the Nim programming language

Source code in the nim programming language

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


  

You may also check:How to resolve the algorithm Ludic numbers step by step in the Delphi programming language
You may also check:How to resolve the algorithm Matrix-exponentiation operator step by step in the K programming language
You may also check:How to resolve the algorithm Pick random element step by step in the Groovy programming language
You may also check:How to resolve the algorithm Reduced row echelon form step by step in the VBA programming language
You may also check:How to resolve the algorithm Angle difference between two bearings step by step in the RPL programming language