SitePoint Sponsor

User Tag List

Results 1 to 21 of 21
  1. #1
    Non-Member coo_t2's Avatar
    Join Date
    Feb 2003
    Location
    Dog Street
    Posts
    1,819
    Mentioned
    1 Post(s)
    Tagged
    1 Thread(s)

    Opinions on File object

    Hey all. I wanna create a file object that will let me do the
    things you'll most commonly need to do with a file.
    The methods I have so far are:
    // open file
    open()
    // close file
    close()
    // get one line at a time, keep an internal index to keep
    // track of the lines.
    getLine()
    // set the internal index to zero; the beginning of the file
    resetLines()
    // probably just wraps the languages seek() function
    seek()
    // returns the entire file as an array
    getContents()

    I was also gonna put methods in for writing to the file.

    Maybe something like:
    // writes over the file with whatever's passed to the method
    putContents()
    // append to the end of the file
    append()
    // some other ones I ain't thought of yet....add as I go..

    I was gonna give the programmer(me) the option of creating a File
    object by either supplying a path to a file or by supplying an open filehandle.
    I figure giving them the option of using a filehandle could be useful
    because they may of opened the file some other way.


    The questions I have are:

    1. Should I offer both ways of creating a file object?
    If they create the object by supplying a path to a file they will
    also have to supply the mode for opening the file.
    But if they supply a filehandle the mode has already been set and it will
    be up to them to know which methods can be used on it. I'll throw exceptions
    if they try to do something they don't have permission to do, but don't know
    if I should give them this option in the first place.

    2. Should I provide methods for reading, writing, iterating all in one class?
    It would be convenient to have all these capabilities in one place, especially for files that have been open in 'rw' mode.
    I'm not a Java programmer but it seems, by looking at this:
    http://java.sun.com/j2se/1.4.2/docs/api/ that they use FileReader and
    FileWriter for reading and writing respectively.
    If I put all these methods in one class a large part of the object would go to waste if the file being
    worked on wasn't opened in 'rw' mode.



    What do you guys think? First of all should I allow creating of the object(s)
    using a filehandle instead of always having the object open the file itself?
    Should I break it up into two objects, one for reading and one for writing?

    Any examples I can look at?

    I'm looking at this right now:
    http://java.sun.com/docs/books/tutor...lestreams.html

    I'll probably just end up copying Java, unless you guys think putting all this
    functionality in one class isn't such a bad thing.
    I may even copy the api of the classes exactly.

    tia,
    --ed

  2. #2
    SitePoint Member
    Join Date
    Jan 2003
    Posts
    17
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    The problem I see, is you rarely if ever need all of that functionality at once, so are you gonna include your whole library just to read a file, which php does perfectly well by itself?

    I don't mean to rain on your parade, but it seems everything this object does is already built into php.

  3. #3
    SitePoint Wizard Mike Borozdin's Avatar
    Join Date
    Oct 2002
    Location
    Edinburgh, UK
    Posts
    1,743
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Damn, I was just gonna to write my own :*. Probably, we'd better to hold some competition?

  4. #4
    No. Phil.Roberts's Avatar
    Join Date
    May 2001
    Location
    Nottingham, UK
    Posts
    1,142
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    The eclipse library does a lot of that already with its FileIterator class, maybe you could create an extension of that?

  5. #5
    ********* Wizard silver trophy Cam's Avatar
    Join Date
    Aug 2002
    Location
    Burpengary, Australia
    Posts
    4,495
    Mentioned
    0 Post(s)
    Tagged
    1 Thread(s)
    I agree with Dingle, PHP handles file manipulation just nicely already. Unless you have a specific file layout for parsing or something like that, I'd just stick with PHP functions.

  6. #6
    SitePoint Zealot
    Join Date
    Jun 2003
    Location
    Middle / East TN
    Posts
    127
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    He needs to build one to become fully OO. You should go all the way, hard core OO! A file reader object is an object, which PHP functions are not, that is your advantage.
    There are 10 kinds of people in this world,
    those who can read binary and those who can't.

  7. #7
    ********* Wizard silver trophy Cam's Avatar
    Join Date
    Aug 2002
    Location
    Burpengary, Australia
    Posts
    4,495
    Mentioned
    0 Post(s)
    Tagged
    1 Thread(s)
    Or, if using a n-tierd design or something like that, he can build file manipulation functions into one of the Controllers, which may have more underlings than simply file manipulation methods.

    OOP is a way of programming, it is not the way.

  8. #8
    Non-Member
    Join Date
    Jan 2003
    Posts
    5,748
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Thinking that I would like something much like you are thinking of myself and I though also about an Iterator ?

    Would pretty much solve the problem of accessing a given line from a file, etc.

    Could perform INSERTs, UPDATEs etc as well ?

    Still thinking about how it could be implemented though, ideas folks ?

  9. #9
    ********* Wizard silver trophy Cam's Avatar
    Join Date
    Aug 2002
    Location
    Burpengary, Australia
    Posts
    4,495
    Mentioned
    0 Post(s)
    Tagged
    1 Thread(s)
    Lol, a file object accepting SQL

    Good idea, probably wouldn't be the quickest way to do things but...

  10. #10
    ********* Victim lastcraft's Avatar
    Join Date
    Apr 2003
    Location
    London
    Posts
    2,423
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    Hi...

    If you are just building a file object then you are duplicating PHP functionality, which is pretty pointless in itself, but then I am a big fan of "fun down design". It is more likely that you have some vague need for one that is just crystalising and so you thought you would see what it is like, yes? Fair enough .

    These days we are driven by need alone and so it went along the lines of first needing the reading from a file to look like a socket or a string and then reading from a file or socket to look like an iterator. Result, a file reader...
    PHP Code:
    class FileReader extends Reader {
        function 
    FileReader($filename) { ... }
        function 
    read() { ... }
        function 
    close() { ... }

    ...and a reader iterator...
    PHP Code:
    class ReaderIterator {
        function 
    ReaderIterator($reader) { ... }
        function 
    next() { ... }

    ...and for convenience a file iterator too...
    PHP Code:
    class FileIterator extends ReaderIterator {
        function 
    FileIterator($filename) {
            
    $this->ReaderIterator(new FileReader($filename));
        }

    We honestly reached this over the period of a year through necessity as we deal with a lot of input and output. But hey, we like fine grained objects!

    yours, Marcus.
    Marcus Baker
    Testing: SimpleTest, Cgreen, Fakemail
    Other: Phemto dependency injector
    Books: PHP in Action, 97 things

  11. #11
    SitePoint Evangelist
    Join Date
    Apr 2003
    Location
    Chicago, USA
    Posts
    417
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Wow I totally didn't understand that last post at all, LOL. I think I have a lot of reading to do.

  12. #12
    Non-Member coo_t2's Avatar
    Join Date
    Feb 2003
    Location
    Dog Street
    Posts
    1,819
    Mentioned
    1 Post(s)
    Tagged
    1 Thread(s)
    Quote Originally Posted by Dingle
    I don't mean to rain on your parade, but it seems everything this object does is already built into php.
    Yeah, I also was afraid that this might be overkill since at this point all I'm really doing is wrapping the functions that PHP/Perl provide.
    Actually I'm writing this code in Perl right now, while making a conscious effort to use the minimal amount of perl-centric syntax possible.
    That way creating a PHP version will be a cinch.


    Quote Originally Posted by lastcraft
    It is more likely that you have some vague need for one that is just crystalising and so you thought you would see what it is like, yes? Fair enough .
    Yeah, that probably just about sums it up.



    I'm relatively new to doing OOP, so I think I may be in a sort of stage where
    I'm trying to make an object out of everything.

    But to be honest, I'm becoming infatuated with the way OOP code looks and feels.
    It just seems to make sense to have an enviroment that completely consists of a bunch of things(objects) that can do stuff(methods), instead of having a bunch of "actions"(procedures/functions) hanging around that
    don't really belong to anything.
    It at least makes me feel like my code is more organized. And I think this perception(if that's truly all it is) can have a real impact on how I feel while
    coding the app. And if I feel better about it I'll be more motivated and thus
    more productive.

    Of course I'm also aware that most of that last paragraph could all be a bunch of hogwash.


    At any rate..

    I think another reason I was thinking of wrapping the file stuff up in an object is because
    almost all of the other parts of the little library I'm building is OO.
    So I wanted to try to maintain some level of consistency in regards to the APIs.

    I think for now I'll listen to the ones who say it's a silly idea and hold off
    on creating these classes. I really can't see any benefit, but I do see useless overhead.

    I was studying eclipse's FileIterator class and to be honest I can't even
    see the benefit of using that object. You can do the same stuff with built in functions with the same amount(or less) code. Of course I could missing something.


    PHP Code:
    <?php

    // Example in Eclipse::FileIterator.php

    $closed =  true;
    $it     =& new FileIterator('eclipse.txt');
    for ( ; 
    $it->isValid(); $it->next())
    {
       
    $line =& $it->getCurrent();
       if (
    $line == 'STOP!')
        {
            
    $closed false;
            break;
        }
        echo 
    $line"\n";
    }
    if (!
    $closed)
    {
        
    $it->close();
    }

    // Non-OO way

    $closed true;
    $fp fopen('file.txt''r');
    while (!
    feof($fp) )
    {   
        
    $line fgets($fp);
        if (
    $line == 'STOP!')
        {   
            
    $closed false;
            break;
        }
        echo 
    $line"\n";
    }    
    if (!
    $closed)
    {   
    fclose($fp);
    }

    ?>
    --ed

  13. #13
    SitePoint Zealot prefab's Avatar
    Join Date
    Jan 2003
    Location
    Belgium
    Posts
    133
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by coo_t2
    I was studying eclipse's FileIterator class and to be honest I can't even
    see the benefit of using that object. You can do the same stuff with built in functions with the same amount(or less) code. Of course I could missing something.
    I think the reason there's an FileIterator in eclipse is that it provides a standard 'interface' for handling iterations. That way you get an uniform and 100% OOP implementation. You don't have to remember how to iterate over something, the class does this for you...once you get into object composition, this can be very effective since a 'host' class can use any type of iterator to get data from for example...

    - prefab

  14. #14
    No. Phil.Roberts's Avatar
    Join Date
    May 2001
    Location
    Nottingham, UK
    Posts
    1,142
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I like using the Eclipse classes for the reason given above, I like to be able to iterate over different items yet use virtually identical syntax.

  15. #15
    Non-Member
    Join Date
    Jan 2003
    Posts
    5,748
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Umm... FileIterator ? Has anyone done this though instead of file contents, how about actual directories and files themselves ?

    Just another idea really folks no ?

  16. #16
    Non-Member coo_t2's Avatar
    Join Date
    Feb 2003
    Location
    Dog Street
    Posts
    1,819
    Mentioned
    1 Post(s)
    Tagged
    1 Thread(s)
    Quote Originally Posted by prefab
    I think the reason there's an FileIterator in eclipse is that
    it provides a standard 'interface' for handling iterations. That way you get
    an uniform and 100% OOP implementation. You don't have to remember how to
    iterate over something, the class does this for you...once you get into object
    composition, this can be very effective since a 'host' class can use any type
    of iterator to get data from for example...

    - prefab
    That makes sense.
    So based on that I would be inclined to think that if I made a File type class
    like I was thinking about, that it would only be useful if I made its API
    conform to a standard interface for iterating over stuff.

    Sheww, I think I need another book quick.


    --ed

  17. #17
    Non-Member
    Join Date
    Jan 2003
    Posts
    5,748
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    That the idea so you can then have other Iterators such as an ArrayIterator and QueryIterator etc etc ...

    I borrowed from Eclipse also; why re-invent the wheel so to speak I ask ? And there is absolutely nothing to fault Eclipse in it's design either

  18. #18
    No. Phil.Roberts's Avatar
    Join Date
    May 2001
    Location
    Nottingham, UK
    Posts
    1,142
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Dr Livingston
    Umm... FileIterator ? Has anyone done this though instead of file contents, how about actual directories and files themselves ?

    Just another idea really folks no ?
    I tried to create a DirectoryIterator class implementing the Eclipse Iterator interface, but the nature of the native directory iteration functions in PHP (both the dir() object and opendir()) didn't lend themselves to it very well. Maybe I'm just a dumbass though.

  19. #19
    SitePoint Addict been's Avatar
    Join Date
    May 2002
    Location
    Gent, Belgium
    Posts
    284
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I tried to create a DirectoryIterator class implementing the Eclipse Iterator interface, but the nature of the native directory iteration functions in PHP (both the dir() object and opendir()) didn't lend themselves to it very well.
    I've done the same thing, implementing a dir iterator, at first I had a simple DirIterator that was really just a container class for the PHP dir functions with an Eclipse Iterator interface...
    Verry soon I came to the conclusion I had a small problem; It just fetched the file/dirnames from a directory, what about filesizes and the likes, clearly some other class had to be constructed to accomodate for this...

    In the end I designed 3 classes, that worked together like Eclipse's DataFile, DataFileReader and DataFileIterator, but it is far from ideal, and has one drawback -> it stores all the entries from a directory in an array, which would probably not be the way to go if you intended on iterating over a large directory, then again, since the Eclipse DataFile* classes worked likewise, I thought I'd be ok

    I'll just post the code, leaving the comments out of it, maybe y'all can thr(/b)ash it
    PHP Code:
    class Dir
    {
        var 
    $path;
        var 
    $reader;
        var 
    $entries;
        var 
    $count;

        function 
    Dir($path, &$reader)
        {
            
    $this->path     = (substr($path, -1) == '/') ? $path $path.'/';
            
    $this->reader   =& $reader;
            
    $this->entries  = array();
            
    $this->count    = -1;
            
    $this->reader->setBasePath($this->getPath());
            
    $this->readDir();
        }

        function 
    readDir()
        {
            if (!(
    $dir = @dir$this->getPath() )))
            {
                return 
    false;
            }
            while(
    $line $dir->read())
            {
                
    $entry $this->reader->parseLine($line);
                if (
    $entry !== false)
                {
                    
    array_push($this->entries$entry);
                }
            }
            
    $dir->close();
            
    $this->count count($this->entries);
        }

        function 
    getPath()
        {
            return 
    $this->path;
        }

        function 
    getCount()
        {
            return 
    $this->count;
        }

        function &
    getEntry($index)
        {
            return 
    $this->entries[$index];
        }
    }


    define('SPOOF_DIR_STATS_DEFAULT',   1);
    define('SPOOF_DIR_STATS_ALL',       2);

    class 
    DirReader
    {
        var 
    $path;
        var 
    $statsKeys;
        var 
    $callbacks;

        function 
    DirReader()
        {
            
    $this->path '';
            
    $this->callbacks = array(
                
    'size'          => "filesize",
                
    'owner'         => "fileowner",
                
    'group'         => "filegroup",
                
    'perms'         => "fileperms",
                
    'last_modified' => "filemtime",
                
    'last_accessed' => "fileatime",
                
    'inode_created' => "fileinode",
                
    'inode_changed' => "filectime"
            
    );
            
    $this->statsKeys = array();
        }

        function 
    parseLine($line)
        {
            if (
    $line == '.' || $line == '..')
            {
                return 
    false;
            }
            return 
    $this->filter($this->getStats($line));
        }

        function 
    filter($stats)
        {
            return 
    $stats;
        }

        function 
    setBasePath($path)
        {
            
    $this->path $path;
        }

        function 
    registerStats($stats)
        {
            if (
    is_array($stats))
            {
                
    $this->statsKeys $stats;
            }
            elseif (
    $stats == SPOOF_DIR_STATS_ALL)
            {
                
    $this->statsKeys array_keys($this->callbacks);
            }
            elseif (
    $stats == SPOOF_DIR_STATS_DEFAULT)
            {
                
    $this->statsKeys = array('size');
            }
            else
            {
                
    $this->registerStats(SPOOF_DIR_STATS_DEFAULT);
            }
        }

        function 
    getStats($line)
        {
            
    $path $this->path.$line;
            
    $stats = array('name' => $line);
            for ( 
    $i=0$tot=count($this->statsKeys); $i<$tot$i++)
            {
                
    $this->doCallBack$this->statsKeys[$i], $path$stats );
            }
            return 
    $stats;
        }

        function 
    doCallBack($key$parameter, &$stats)
        {
            if (!isset(
    $this->callbacks[$key]))
            {
                return ;
            }
            eval(
                
    sprintf(
                    
    "\$stats['$key'] = %s('%s');",
                    
    $this->callbacks[$key],
                    
    $parameter
                
    )
            );
        }
    }


    class 
    DirIterator /* implements Iterator */
    {
        var 
    $dir;
        var 
    $current;
        var 
    $max;

        function 
    DirIterator( &$dir )
        {
            
    $this->dir =& $dir;
            
    $this->max $this->dir->getCount();
            
    $this->reset();
        }

        function 
    reset()
        {
            
    $this->current 0;
        }

        function 
    next()
        {
            
    $this->current++;
        }

        function 
    isValid()
        {
            return 
    $this->current $this->max;
        }

        function &
    getCurrent()
        {
            return 
    $this->dir->getEntry($this->current);
        }

    It works something like this:
    PHP Code:
    $dirPath = '/go/home/to/mama/';
    $colNames = array(
        'name'          => 'Naam',
        'size'          => 'Grootte',
        'last_modified' => 'Laatst veranderd',
        'last_accessed' => 'Laatst geraadpleegd'
    );

    $reader =& new DirReader();
    $reader->registerStats( array_keys($colNames) );
    $printer =& new DataGridPrinter( new ArrayIterator($colNames) );
    $printer->registerNumberFormat('size', 0, '', '.');
    $directory  =& new Dir($dirPath, $reader);
    ?>

    <html>
    <head>
    <title> Directory test </title>
    <link rel="stylesheet" type="text/css" href="DirectoryDataGrid.css" />
    </head>
    <body>
    Total # files: <?php echo($directory->getCount()); ?>
    <?php
    Loop
    ::run(new DirIterator($directory), $printer);
    ?>
    </body>
    </html>
    There are some things I don't like about it:
    First there's the issue of reading a whole directory structure into an array, which could open up a whole can of worms in a multi-user environment where a lot of changes are made to that specific directory...

    Second, I don't like the fact that the DirReader has a public method setBasePath() (because it has to know the full path in order to call the file stats functions...). It seems to me that the reader should get the full path by concatenating $dir->getPath() and $dir->getEntry(), but that would make the workings of the classes different from that of the DataFile* classes, in that I should use it more like this:
    PHP Code:
    $directory =& new Dir($path);
    $reader =& new DirReader($directory); 
    which doesn't make sense since I reckon you need a reader to construct the directory...

    Tertio, all that fuzz with the callbacks, and still haven't implemented a sorting system
    (I'm thinking going Decorator )

    And last, but not least, there's the QuickForm thread, the interface thread and the phppatterns iterator article (I'm probably forgetting a lot of others), which are shifting my 'firm believes' in the Eclipse Iterators.
    I really like Eclipse, let there be no doubt about that, but I'm seriously considering throwing the iterator out of it, and just implement a method next() in all object classes that need a once top-to-bottom iteration...
    Per
    Everything
    works on a PowerPoint slide

  20. #20
    SitePoint Evangelist
    Join Date
    Apr 2003
    Location
    Chicago, USA
    Posts
    417
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Couldn't you just use realpath() to get the path or whatever?

  21. #21
    Non-Member
    Join Date
    Jan 2003
    Posts
    5,748
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    PHP Code:
    realpath(basename(...));
    #
    #
    # umm... ? 


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •