Question
· Oct 9, 2017

How to read CSV file contents into Objects in Cache

I have this code here;I am trying to read a csv file but when I run this code I get  <LIST>%open+3^%stream.Object.1 would anyone have a look and tell me where I am going wrong .Record mapper is fine but I need a custom csv Importer

ClassMethod ImportCSV()
{
   set adapter =##class(%File).%New()
  
  set status=adapter.%Open("C:\In\in.csv")
  
  if $$$ISERR(status)
  {
   do $System.Status.DisplayError(status)
  }
  
  set counter =1
  
  while 'adapter.AtEnd
  {
   set line=adapter.ReadLine()
   
   set rec= ##class(CSVRecord).%New()
   
   set rec.ID=$piece(line,",",1)
   set rec.FName=$piece(line,",",2)
   set rec.SecName=$piece(line,",",3)
   set rec.Gender=$piece(line,",",4)
   set rec.Age=$piece(line,",",5)
   
     write rec.ID,
 
             rec.FName,

             rec.Secname ,

             rec.Gender,

             rec.Age,!
        
         Set savestatus=rec.%Save()
              
      if $$$ISERR(savestatus)
    {
     do $System.Status.DisplayError(status)
    }
   
    }
   
    //if error found during processing,show it
    if $$$ISERR(status)
    {
     do $System.Status.DisplayError(status)
    }
}

Discussion (13)1
Log in or sign up to continue

Use this method for reading the file:

ClassMethod ReadFile()
{
       set stream=##class(%Stream.FileCharacter).%New()
       set sc=stream.LinkToFile("c:\test.csv")
      do stream.Rewind()
       while 'stream.AtEnd {
                 set line=stream.ReadLine()
                 W line,!
        }
}

 

***Make sure that the path of the file is on the computer that runs cache instance
 

Hi Robert, you are right, but I forgot to mention I got the error after adding Eduard his recommendationsmiley.

This is the code:

ClassMethod ImportCSV()
{
  set adapter = ##class(%File).%New("C:\temp\in.csv")
  
  set status = adapter.%Open("R")
  
  if $$$ISERR(status)
  {
   do $System.Status.DisplayError(status)
  }
  
  set counter =1
  
  while 'adapter.AtEnd
  {
   set line=adapter.ReadLine()
   
   set rec= ##class(CSVRecord).%New()
   
   set rec.ID=$piece(line,";",1)
   set rec.FName=$piece(line,";",2)
   set rec.Secname=$piece(line,";",3)
   set rec.Gender=$piece(line,";",4)
   set rec.Age=$piece(line,";",5)
   
     write rec.ID,
 
             rec.FName,
             rec.Secname ,
             rec.Gender,
             rec.Age,!
        
         Set savestatus=rec.%Save()
              
      if $$$ISERR(savestatus)
    {
     do $System.Status.DisplayError(status)
    }
   
    }
   
    //if error found during processing,show it
    if $$$ISERR(status)
    {
     do $System.Status.DisplayError(status)
    }
}

I do notice this topic comes back in time in the Community, so people are interested -and struggling with it like myself, but if we look back the items leave quite unanswered.... as people do not share their final working code... and only tell that they have solved the question.

Thanks!

Marco you are RIGHT !

The example is just wrong! And never got fixed.

Instead of   set status = adapter.%Open("R")

it should be set status = adapter.Open("R")

This are 2 differnet methods with total different incompatible parameters. 

it is good practice to close the file after use by  do adapter.Close() 

The problem with the CSV SQL procedure is that it doesn't take care of the masked delimiters.

if the file for the above sample would contain a line (if the masking character is the very common and usual ")

4711,"Peter, Paul and Mery","Sample",undecided,500

the 2. Part is only read as Peter (at least on Caché 2017.2 and IRIS 2018.1.2 so atm. the only chance when the data doesn't play nicely you have to implement the CSV reading yourself (which is much slower)