Login Page - Create Account

Support Board


Date/Time: Wed, 27 Nov 2024 22:35:52 +0000



[Programming Help] - Read & parse CSV

View Count: 2073

[2020-01-06 13:14:36]
User462086 - Posts: 196
Hi, in order to read a CSV file from disk then parse out certain fields from each line I've been trying to get 'sc.ReadFile' to work but can't seem to figure it out (code below with comments compiles fine). Stack Overflow has tons of examples for C++ but most utilize 3rd party libraries. In the past I've used 'fgets' in AmiBroker's C-based scripting language.

1) What's the best way to accomplish this in Sierra Chart?
2) If 'sc.ReadFile' is the best way, how do I get the file's text from the 'Buffer' (pointer)

Many thanks!!

Edit: using version 2028



#include "sierrachart.h"

SCDLLName("Test_ReadFile")

// support function

DWORD GetFileSize(const SCString& PathAndFileName){
  
  HANDLE File = CreateFile
          ( PathAndFileName
          , GENERIC_READ
          , FILE_SHARE_READ | FILE_SHARE_WRITE
          , NULL
          , OPEN_EXISTING
          , 0
          , NULL
          );
  
  if (File == INVALID_HANDLE_VALUE)
    return INVALID_FILE_SIZE;
  
  DWORD FileSize = ::GetFileSize(File, NULL);
  
  CloseHandle(File);
  
  return FileSize;
}

// main

SCSFExport scsf_Test_ReadFile(SCStudyInterfaceRef sc){

  SCString DebugMessage;
    // int/bool %d; float %f, %g, %e; string %s
    // DebugMessage.Format("caption : %d",var);
    // sc.AddMessageToLog(DebugMessage, 0);
  
  SCInputRef FullPath  = sc.Input[0];
  
  if (sc.SetDefaults){
    sc.GraphName = "Test_ReadFile";
    sc.AutoLoop = 0;
    FullPath.Name = "Full Path to Text File";
    FullPath.SetPathAndFileName("");
    return;
  }

  int FileHandle;

  bool FileOpened = sc.OpenFile
            ( FullPath.GetPathAndFileName()
            , n_ACSIL::FILE_MODE_OPEN_EXISTING_FOR_SEQUENTIAL_READING
            , FileHandle
            );
    
  if (FileOpened==false)
    return;
  
  DWORD BytesToRead = GetFileSize(FullPath.GetPathAndFileName());
  
  if (BytesToRead==INVALID_FILE_SIZE)
    return;
  
DebugMessage.Format( "BytesToRead : %d", BytesToRead );
sc.AddMessageToLog( DebugMessage, 0 );  
  
  char* Buffer;
  unsigned int* p_BytesRead;
  
  bool FileRead = sc.ReadFile
            ( FileHandle
            , Buffer
            , BytesToRead
            , p_BytesRead
            );
  
  if (FileRead==false)
    return;        // <- this executes = something is wrong with my 'sc.ReadFile' call
  
DebugMessage.Format( "Buffer : %s", Buffer ); // <- when the line above is removed this returns "(null)"
sc.AddMessageToLog( DebugMessage, 0 );
  
  sc.CloseFile(FileHandle);
}



Date Time Of Last Edit: 2020-01-06 13:20:20
[2020-01-06 14:16:14]
User462086 - Posts: 196
FWIW, this seems to be working as expected. Any comments/improvements welcome.


#include "sierrachart.h"

SCDLLName("Test_ReadFile")

SCSFExport scsf_Test_ReadFile(SCStudyInterfaceRef sc){

  SCString DebugMessage;
    // int/bool %d; float %f, %g, %e; string %s
    // DebugMessage.Format("caption : %d",var);
    // sc.AddMessageToLog(DebugMessage, 0);
  
  SCInputRef FullPath  = sc.Input[0];
  
  if (sc.SetDefaults){
    sc.GraphName = "Test_ReadFile";
    sc.AutoLoop = 0;
    FullPath.Name = "Full Path to Text File";
    FullPath.SetPathAndFileName("");
    return;
  }
  
  std::ifstream input(FullPath.GetPathAndFileName());
  
  for( std::string line; getline(input,line); ){
    DebugMessage.Format( "line : %s", line.c_str() );
    sc.AddMessageToLog( DebugMessage, 0 );
  }
}

[2020-01-06 17:37:28]
User907968 - Posts: 823
In the first post:
char* Buffer;
No memory is allocated to Buffer, you have simply declared Buffer as pointer to char.

You can use this function to check problem with sc.OpenFile:
sc.GetLastFileErrorCode()

Also, you could also use functions from SCString class for handling data that is read in:
ACSIL Programming Concepts: Working with SCString, Text Strings and Setting ACSIL Structure Member Name Strings

e.g.
SCString::ParseLines()
SCString::Tokenize()

Maybe some of this is helpful, or maybe you looked at these already.
[2020-01-06 23:37:48]
Sierra Chart Engineering - Posts: 104368
We have updated the documentation in regards to this. You have to allocate the Buffer and provide its size. Refer to the updated ACSIL documentation for this function.
Sierra Chart Support - Engineering Level

Your definitive source for support. Other responses are from users. Try to keep your questions brief and to the point. Be aware of support policy:
https://www.sierrachart.com/index.php?l=PostingInformation.php#GeneralInformation

For the most reliable, advanced, and zero cost futures order routing, *change* to the Teton service:
Sierra Chart Teton Futures Order Routing
[2023-06-26 09:30:12]
Zorin - Posts: 19
We have updated the documentation in regards to this

With all the utmost respect, both functions you've recommend to use - SCString::ParseLines() and SCString::Tokenize()- are very poorly documented and have no any basic examples - for example, for working with files, basic read.

The single example which I could find was from the study RequestValuesFromServerAndDraw.cpp - practically, no any comments there and it's heavily relying on using pointers (most people who are not familiar with C / C++ concepts would be rather using arrays - simpler to read & understand).

Please update the relevant documentation providing a couple of appropriate (easy enough for "copy-paste") examples so people don't have to re-invent the wheel every time when trying to read & parse something from the file.
[2023-06-26 10:08:55]
Sierra_Chart Engineering - Posts: 17198
Why is it you are using these functions? You can use the C++ standard library string class and functions. You do not have to rely upon anything Sierra Chart is providing.
Sierra Chart Support - Engineering Level

Your definitive source for support. Other responses are from users. Try to keep your questions brief and to the point. Be aware of support policy:
https://www.sierrachart.com/index.php?l=PostingInformation.php#GeneralInformation

For the most reliable, advanced, and zero cost futures order routing, use the Teton service:
Sierra Chart Teton Futures Order Routing
[2023-06-26 10:08:55]
Sierra_Chart Engineering - Posts: 17198
Why is it you are using these functions? You can use the C++ standard library string class and functions. You do not have to rely upon anything Sierra Chart is providing.
Sierra Chart Support - Engineering Level

Your definitive source for support. Other responses are from users. Try to keep your questions brief and to the point. Be aware of support policy:
https://www.sierrachart.com/index.php?l=PostingInformation.php#GeneralInformation

For the most reliable, advanced, and zero cost futures order routing, use the Teton service:
Sierra Chart Teton Futures Order Routing
[2023-06-26 10:28:08]
Zorin - Posts: 19
... you are using these functions? You can use the C++ standard library ..

Because it's your site, your functions, and they're described in SCSstring section, and code would look better and easier to read .

PS just trying to help my son - he was trying to do everything by the book & couldn't work it out.
[2023-06-27 08:07:08]
User462086 - Posts: 196
I couldn't work it out either, so started using the various forms of 'fstream' instead.

Referencing the code in the first post, replacing

char* Buffer;

with

char Buffer[BytesToRead];

results in 'Buffer' being filled with the contents of a file.

To post a message in this thread, you need to log in with your Sierra Chart account:

Login

Login Page - Create Account