Read file by line

General help with the eC language.
samsam598
Posts: 212
Joined: Thu Apr 14, 2011 9:44 pm

Read file by line

Post by samsam598 »

Greetings!

Given below code,from the console when enter a file name which contains Chinese characters,the program will crashed.What should I do?Thanks!!

Code: Select all

 
import "ecere"
 
class App:Application
{
   public:
    uint16* wstring(char* str)
   {
      uint16* result=UTF8toUTF16(str,null);
      return result;
 
      //delete result;
   }
 
   void byLine(const char* filename)
   {
      File file=FileOpen(filename,read);
      while(!file.eof)
      {
         char line[1024];
         if(file.GetLine(line,1024))
         {
            printf("%s\n",line);
         }
      }
   }
   void Main()
   {
      char input[1024];
      printf("Please enter the file name:");//------->
      scanf("%[^\n]",input);//------------------------->
      byLine(input);//-->Crashed when encountered Chinese file name
      system("pause");
   }
}             
 
jerome
Site Admin
Posts: 608
Joined: Sat Jan 16, 2010 11:16 pm

Re: Read file by line

Post by jerome »

Hi Sam! Glad to see you're still around :)

First, you should check the value of file before accessing it (e.g. file.eof).

file will be null if FileOpen failed, and so this might be where the program is crashing...

Also you should 'delete' the file object once it's done with. That will both close the file handle and free the object memory.

Then I would advise against using scanf and using an Ecere dialog with an EditBox instead, if at all possible :) You can run the Ecere GUI in console mode as well, both on Windows with the Win32 console driver, and on Unix with the NCurses driver (Although the text mode might be in great need of fixes lately).

I have no idea in what format/encoding scanf is returning you that filename, I don't even recognize the format string you are using there "%[^\n]" ? What does that do? First time I see a scanf like this :)

But FileOpen expects international file names in UTF-8, like everything else in the Ecere API (not in the Windows archaic and poor choice of an encoding that is UTF-16).

Hope this helps! Let me know if you have more questions :D

Best regards,

Jerome
samsam598
Posts: 212
Joined: Thu Apr 14, 2011 9:44 pm

Re: Read file by line

Post by samsam598 »

Hi Jerome,

Thanks for the prompt response!

scanf("%[^\n]",variable) will read a line of string even if it contains whitespace,like c:\program files.----This is grom google. :D But for this thread,revising back to scanf("%s",filename) suffices.

The file I am talking about is existing in the computer and I can read successfully with ecere sdk\samples\guiAndGfx\eNotpad(.exe).fyi,it's encoding is UTF8.I think the crashed is only due to the Chinese file name,since if I rename it to an English name,it runs successfully(except the Chinese file content are mess which is another issue).
jerome
Site Admin
Posts: 608
Joined: Sat Jan 16, 2010 11:16 pm

Re: Read file by line

Post by jerome »

Hi Sam,

The file might be encoded in UTF8, but here I was talking about the filename which must also be specified in UTF8...

Did you check whether FileOpen returned a null pointer?

-Jerome
samsam598
Posts: 212
Joined: Thu Apr 14, 2011 9:44 pm

Re: Read file by line

Post by samsam598 »

Hi Jerome,

Just checked that it indeed returned null.

Code: Select all

 
if(!file) 
      {
         printf("Failed to open\n");
         exit(-1);
      } 
 
So how can I pass a Chinese character file name to byLine(...) function?Thanks.
jerome
Site Admin
Posts: 608
Joined: Sat Jan 16, 2010 11:16 pm

Re: Read file by line

Post by jerome »

You need to pass the file name as a UTF-8 encoded string.
Anything input in the Ecere GUI will automatically be encoded in UTF-8...
The values in argv[] should also work fine.

For scanf to give you UTF-8, the locale settings of the console probably have to be set correctly to be UTF8... I'm guessing if printf outputs UTF8 correctly, then scanf should input it correctly as well :)
samsam598
Posts: 212
Joined: Thu Apr 14, 2011 9:44 pm

Re: Read file by line

Post by samsam598 »

I've got it.Thanks Jerome!
Below code works pretty well.However I just want to know in the destructor (~GetInputFromUser()) whether the String str should be deleted or not.

Code: Select all

 
import "ecere"
 
class GetInputFromUser : Window
{
   caption = "Get Input From User";
   background = activeBorder;
   borderStyle = fixed;
   hasClose = true;
   size = { 488, 132 };
   anchor = { horz = -47, vert = -129 };
 
   EditBox editBox1 { this, caption = "editBox1", size = { 438, 19 }, position = { 16, 40 } };
 
  public:
 
   String str;
   property String str
   {
      set { str=CopyString(value);}
      get {return str;}
   }
   Button btnOK 
   {
      this, caption = "OK", altO, isDefault = true, size = { 74, 21 }, position = { 368, 72 };
 
      bool NotifyClicked(Button button, int x, int y, Modifiers mods)
      {
         str=editBox1.contents; 
         Destroy(0);
         return true;
      }
   };
   Button btnCancel 
   {      
      this, caption = "Cancel", escape, size = { 82, 21 }, position = { 200, 72 };
 
      bool NotifyClicked(Button button, int x, int y, Modifiers mods)
      {
 
         Destroy(0);
         return true;
      }
   };
   Label label1 { this, caption = "请输入文件名:", size = { 260, 13 }, position = { 16, 16 } };
 
   ~GetInputFromUser()
   {
      //if(str!=null) delete str;
   }
 
   bool OnPostCreate(void)
   {
      editBox1.Activate();
      return true;
   }
}
 
//Form1 form1 {};
class App:GuiApplication
{
   private:
   //GetInputFromUser dlg;
   FileDialog dlg;
   public:
   void byLine(char* filename)
   {
      File file=FileOpen(filename,read);
      if(!file) 
      {
         printf("Failed to open\n");
         exit(0);
      } 
      while(!file.eof)
      {
         char line[1024];
         if(file.GetLine(line,1024))
         {
            printf("%s\n",line);
         }
      }
      delete file;
   }
 
   bool Init()
   {
 
 
      return true;
   }
 
   void Main()
   {
      printf("Please enter the file name to open:");
      GuiApplication::Main();
      //dlg=GetInputFromUser{};
 
      dlg=FileDialog{};
      dlg.Modal();
      printf("The file you'd like to open is %s\n",dlg.filePath);
      byLine(dlg.filePath);  
      system("pause");
   }
}                                   
 
jerome
Site Admin
Posts: 608
Joined: Sat Jan 16, 2010 11:16 pm

Re: Read file by line

Post by jerome »

Hi Sam!

There is a bit of confusion in your class there regarding str...

Also, you are declaring a bunch of things as 'public', including the controls that make up the form. public members are normally meant to be accessed outside of the class.

You could for example make the 'str' property public, but you would not make both the property and the data member public as you are doing in that code. If you do have a property which allocates memory upon setting a value, you should also delete the previous value or it will leak, e.g.:

Code: Select all

private: 
   String str;
public:
   property String str
   {
      set { delete str; str=CopyString(value);}
      get {return str;}
   }
In this case, you should also free the memory in the destructor. But note that 'delete' has an implicit null check, so you should not add an extra one:

Code: Select all

 ~GetInputFromUser()
   {
      delete str;
   }
 
Finally, in your btnOK NotifyClicked where you access 'str', not that the 'this' class is the form (GetInputFromUser), and so the data member with the same name will be favored over the property, unless explicitly specified through property::. This means that your property and your CopyString() call are not being called as you would want, and so str will be pointing to memory it should not (which belongs to the EditBox). So that code should read:

Code: Select all

 Button btnOK 
   {
      this, caption = "OK", altO, isDefault = true, size = { 74, 21 }, position = { 368, 72 };
 
      bool NotifyClicked(Button button, int x, int y, Modifiers mods)
      {
         property::str=editBox1.contents; 
         Destroy(0);
         return true;
      }
   };
Hope this clarifies things :)

Regards,

Jerome
samsam598
Posts: 212
Joined: Thu Apr 14, 2011 9:44 pm

Re: Read file by line

Post by samsam598 »

Hi Jerome,

I gained a lot today and I am very :D

By the way,do we have a file selector control which can be placed in a form?
Appreciated!


Regards,
Sam
jerome
Site Admin
Posts: 608
Joined: Sat Jan 16, 2010 11:16 pm

Re: Read file by line

Post by jerome »

Hi Sam,

Take a look at the Ecere Desktop Environment project, Ecere Explorer in particular:

http://ecere.com/cgi-bin/gitweb.cgi?p=e ... e6;hb=HEAD

Regards,

Jerome
Post Reply