NYCJUG/2012-02-14/compareReadingFilesInC(2b2b)AndJ

From J Wiki
Jump to navigation Jump to search

There is a considerable amount of coding overhead associated with the basic task of reading a file in C++. By comparison, the J code is trivially simple.

Compare Simple C++ File Readers

Both of these versions are Microsoft Visual Studio C++ “Console CLR” applications. The first reads a text file (from http://msdn.microsoft.com/en-us/library/y52yxde8.aspx), the second a binary file containing four integers.

// readDataFileCLR.cpp : main project file.

#include "stdafx.h"

using namespace System;
using namespace System::IO;
using namespace System::Collections;

int main(array<System::String ^> ^args)
{  String^ fileName = "textfile.txt";
   try
   {  Console::WriteLine("Trying to open file {0}...", fileName);
      StreamReader^ din = File::OpenText(fileName);

      String^ str;
      int count = 0;
      while ((str = din->ReadLine()) != nullptr)
      {  count++;
         Console::WriteLine("Line {0}: {1}", count, str );
      }
   }
   catch (Exception^ e)
   {  if (dynamic_cast<FileNotFoundException^>(e))
         Console::WriteLine("File '{0}' not found", fileName);
      else
         Console::WriteLine("Problem reading file '{0}'", fileName);
   }
    return 0;
}

This reads a binary file (from http://msdn.microsoft.com/en-us/library/3f3t7tke.aspx):

// binary_readCLR.cpp : main project file.
// compile with: /clr
#include "stdafx.h"

#using<system.dll>
using namespace System;
using namespace System::IO;

int main()
{  String^ fileName = "C:\\amisc\\data.bin";
   try
   {  FileStream^ fs = gcnew FileStream(fileName, FileMode::Open);
      BinaryReader^ br = gcnew BinaryReader(fs);

      Console::WriteLine("Contents of {0}:", fileName);
      while (br->BaseStream->Position < br->BaseStream->Length)
         Console::WriteLine(br->ReadInt32().ToString());

      fs->Close( );
   }
   catch (Exception^ e)
   {  if (dynamic_cast<FileNotFoundException^>(e))
         Console::WriteLine("File '{0}' not found", fileName);
      else
         Console::WriteLine("Exception: ({0})", e);
      return -1;
   }
   return 0;
}

Read Text File with J

Doing the same thing in J is far simpler. The following two examples leave out the checks for the existence and the readability of the file that the C code has since the J code is typically used interactively. If we wished to more exactly emulate the C code, the checks would require only a line or two more.

   text=. fread 'textfile.txt'
   $text                 NB. Shape - too big to show all right now...
807
   >3{.<;._2 text-.CR    NB. Look at first 3 lines only.
// Readdatafileclr.Cpp : Main Project File.

#Include "Stdafx.H"

Read Binary File with J

Notice that we do exactly the same thing as we did reading a text file – why wouldn’t we? It’s one less variation to remember. A copy of this file is File:Databin.txt; you may want to rename it to "data.bin".

   bindat=. fread 'C:\amisc\data.bin'
   $bindat               NB. Only 16 bytes = 4 integers.
16
   bindat                NB. Binary doesn’t display nicely,
[1]
----
   '
                         NB.  so let’s convert the bytes into integers.
   cvtIntFromBytes=: 256 #. [: |. a. i. ]
   cvtIntFromBytes _4{.bindat     NB. Works for last 4 and
10000
   cvtIntFromBytes 4{.bindat      NB. for first 4, so apply it to whole array,
1
   cvtIntFromBytes &> _4<\bindat  NB. to non-overlapping windows of 4 bytes.
1 2 3 10000

Here’s the cover function fread we used above. It uses one of the J foreign conjunctions “1!:1” if file is identified by a handle (file number) or “1!:11” if identified by name.

fread=: 3 : 0
if. 1 = #y=. boxopen y do.
  1!:1 :: _1: fboxname y
else.
  1!:11 :: _1: (fboxname {.y),{:y
end.
:
x freads y
)