Ecere SDK/eC Forums
http://ec-lang.org/community/
Print view

Read file by line
http://ec-lang.org/community/viewtopic.php?f=1&t=339
Page 1 of 2
Author:  samsam598 [ Sun Nov 25, 2012 8:58 pm ]
Post subject:  Read file by line

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");
   }
}             
 
Author:  jerome [ Sun Nov 25, 2012 9:40 pm ]
Post subject:  Re: Read file by line

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
Author:  samsam598 [ Sun Nov 25, 2012 9:52 pm ]
Post subject:  Re: Read file by line

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).
Author:  jerome [ Sun Nov 25, 2012 10:24 pm ]
Post subject:  Re: Read file by line

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
Author:  samsam598 [ Sun Nov 25, 2012 10:35 pm ]
Post subject:  Re: Read file by line

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.
Author:  jerome [ Sun Nov 25, 2012 10:43 pm ]
Post subject:  Re: Read file by line

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 :)
Author:  samsam598 [ Mon Nov 26, 2012 2:17 am ]
Post subject:  Re: Read file by line

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");
   }
}                                   
 
Author:  jerome [ Mon Nov 26, 2012 3:10 am ]
Post subject:  Re: Read file by line

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
Author:  samsam598 [ Mon Nov 26, 2012 4:12 am ]
Post subject:  Re: Read file by line

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
Author:  jerome [ Mon Nov 26, 2012 4:31 am ]
Post subject:  Re: Read file by line

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
All times are UTC-05:00 Page 1 of 2