AutoHotkey Homepage AutoHotkey Community
Let's help each other out
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Database functions ex: FileWriteLine
Goto page 1, 2  Next
 
Post new topic   Reply to topic    AutoHotkey Community Forum Index -> Wish List
View previous topic :: View next topic  
Author Message
Payam



Joined: 07 Apr 2004
Posts: 58

PostPosted: Wed Jun 30, 2004 10:08 am    Post subject: Database functions ex: FileWriteLine Reply with quote

FileWriteLine - be able to append to a specified line of a text file (maybe even with the option of at the beginning or end of the line)

FileDeleteLine - delete a specific line in a text file


These, primarily the former, would allow more flexibility in storing and changing data (in a text database for example).

As an example, lets say you have a comma delimited text file, you could then use ahk to modify a value in the middle of the file (instead of just being able to append to the bottom of the file).

Thanks Chris!
Back to top
View user's profile Send private message Send e-mail MSN Messenger
Chris
Site Admin


Joined: 02 Mar 2004
Posts: 10450

PostPosted: Wed Jun 30, 2004 12:20 pm    Post subject: Reply with quote

These features will probably never be built-in because:
1) They are too rarely used (others are welcome to convince me otherwise).
2) They require the text file to be recreated (at least in the case of inserting, not necessarily deleting). Recreating a text file can be easily scripted, and with almost the same performance in a script as it would be if I were to build in the function. This is because disk IO is so much slower than the CPU overhead of the operation:

Code:
; Delete specified line from the file:
SetBatchLines, -1  ; Probably makes script as fast as any program for a disk intensive operation.
line_to_delete = 15
Loop, read, Text DB.txt, New Text DB.txt
{
     if a_index <> %line_to_delete%
          FileAppend, %A_LoopReadLine%`n
}
FileMove, New Text DB.txt, Text DB.txt, 1

Almost the exact same technique as above could be used to append some text to a line in the middle of the file:
Code:
Loop, read, Text DB.txt, New Text DB.txt
{
     if a_index <> %line_to_append_to%
          FileAppend, %A_LoopReadLine%`n
     else
          FileAppend, %A_LoopReadLine%`,The text to append.`n
}
FileMove, New Text DB.txt, Text DB.txt, 1


Admittedly, there are ways to program the above operations so that an intermediate file is not needed (INI files probably do this). However, I do not think these methods help performance much, if at all. All they do is avoid the need to have temporarily double the amount of disk space available during the operation.
Back to top
View user's profile Send private message Send e-mail
Chris
Site Admin


Joined: 02 Mar 2004
Posts: 10450

PostPosted: Wed Jun 30, 2004 2:11 pm    Post subject: Reply with quote

When using the above, be sure to have a backup of the file (at least during testing), because the script will overwrite the original with the new version. If something goes wrong during the process (e.g. disk full or bad sector), the entire file could be lost.

Also, I realized after posting that you do get a boost in performance when avoiding the temporary file. So would anyone else envision a realistic use for inserting/modifying/deleting specific lines in a text file?

I try to avoid adding commands that are used by only a tiny fraction of users, since they increase the size of the program and the memory it requires -- not to mention cluttering up the help file with something that potentially 99.99% of users would not find useful.
Back to top
View user's profile Send private message Send e-mail
beardboy



Joined: 02 Mar 2004
Posts: 444
Location: SLC, Utah

PostPosted: Wed Jun 30, 2004 4:11 pm    Post subject: Reply with quote

Chris,

I would use this feature, but I use a lot of text files as database type files for batch jobs, and I know that is rare.

thanks,
beardboy
Back to top
View user's profile Send private message Send e-mail Visit poster's website AIM Address Yahoo Messenger MSN Messenger
Chris
Site Admin


Joined: 02 Mar 2004
Posts: 10450

PostPosted: Wed Jun 30, 2004 6:50 pm    Post subject: Reply with quote

But how often do you know the line number of the target line? Perhaps you would have an index file containing that info? Or perhaps it would be more appropriate to optionally delete a line based on a keyword that it contains? I guess the most versatile thing would be to have a subroutine that is called automatically for every line in the file. That subroutine could check the contents of the line and indicate whether it should be modified, deleted, or inserted-before. However, that's getting pretty complex and it seems that the examples I posted are actually simpler than this.
Back to top
View user's profile Send private message Send e-mail
beardboy



Joined: 02 Mar 2004
Posts: 444
Location: SLC, Utah

PostPosted: Wed Jun 30, 2004 9:06 pm    Post subject: Reply with quote

Chris,

I'm not saying that the feature should be added, just that I would most likely use it. I currently do a Loop and read the contents of the file and use FileAppend to re-write the file. Like the examples you gave.

thanks,
beardboy
Back to top
View user's profile Send private message Send e-mail Visit poster's website AIM Address Yahoo Messenger MSN Messenger
Chris
Site Admin


Joined: 02 Mar 2004
Posts: 10450

PostPosted: Wed Jun 30, 2004 10:20 pm    Post subject: Reply with quote

I should clarify: I'm asking for info about what parameters the command would take if it existed. It seems to me that in most cases you wouldn't know the line number of the target line beforehand. You'd have to have a file-reading loop just to determine this. Or alternatively, if not given the line number, what info would the command be given instead?

Also, how often is it that more than one line would need to be deleted/modified/inserted? If often, the loop technique currently used probably performs better than the command would (since the command must delete/modify/insert only one line at a time, and must rescan and rebuild the file each time).
Back to top
View user's profile Send private message Send e-mail
Payam



Joined: 07 Apr 2004
Posts: 58

PostPosted: Fri Jul 02, 2004 9:54 am    Post subject: Reply with quote

Chris, thank you - I can now more or less do what I need.

The main reason I thought this feature would be useful is for csv files for example.

Lets say for simplicity I have a db file of fruit names and their costs.

I wanted to lets say increase the price of oranges and apples by $1,etc or add a third paramter to it (like quantity available as the next field separated by a comma).

Nevertheless I can now accomplish it using the method you suggested.
Back to top
View user's profile Send private message Send e-mail MSN Messenger
Guest






PostPosted: Fri Jul 09, 2004 4:35 am    Post subject: Reply with quote

I think these option are related to the ability to write scripts on the fly a expansion of this ability would be...

FileWriteStart ('various options')

Blah, Blah, Blah...

FileWriteEnd ('various options')

FileWriteto ('various options')

The user could then cut put down what he wanted and forward that 2 a file. Of course there would have to be something for carriage return and line. Or prehabs an options that assumes that for you.

FileWriteStart
#1 Blah, blah, blah, @CR
#2 Blah, blah, blah, @CR
FileWriteEnd
Back to top
Chris
Site Admin


Joined: 02 Mar 2004
Posts: 10450

PostPosted: Fri Jul 09, 2004 1:25 pm    Post subject: Reply with quote

Rajat suggested something similar and I think it would be useful. There's an item on the to-do list to support a line continuation character. By combining that with the technique of assigning to a variable first, the need to escape commas is avoided, though you would still have to escape percent signs:
Code:
line =
     _This is the first line.`n
     _This is the second line, with literal comma.`n
FileAppend, %line%, %TargetFile%


Does that seem like it would work okay?
Back to top
View user's profile Send private message Send e-mail
Guest






PostPosted: Sun Jul 11, 2004 11:31 am    Post subject: Reply with quote

That would defintely improve the situation.
Back to top
daonlyfreez



Joined: 16 Mar 2005
Posts: 738
Location: Berlin

PostPosted: Tue Jul 12, 2005 3:42 pm    Post subject: Reply with quote

Here are some includeable functions that might be useful...

Important: I use the #-sign to differentiate between included functions/variables and the scripts own.

The includeable functions still use a temporary file, which overwrites the source file (based on the original snippets provided here by Chris).

Any errors resulting are therefore AT YOUR OWN RISK

file.ahk

Code:
/* *** #File_Len ********************

Returns the number of lines in a file

Settings:

aFile = pathto\yourfile.txt

Example:

aFileLen := #File_Len(aFile)
msgbox, %aFileLen%

Original Source:

Chris (http://www.autohotkey.com)

*/
#File_Len(aFile)
{
   #Main_SpeedMax()
   Loop, Read, %aFile%
       #File_Len = %A_Index%
   #Main_SpeedRestore()
   return #File_Len
}

/* *** #File_WriteLine ********************

Writes a string to a specific line in a file, with options

Settings:

aString = a text to insert
aFile = pathto\yourfile.txt
aLineNr = the line nr to insert into
theOption = choose from one of the following:
- r = replaces the whole existing line
- e = inserts the string at the end of the existing line
- s = inserts the string at the start of the existing line
- #(a number) = inserts the string at position # in the existing line
- d = delete the line, don't insert anything (FileDeleteLine)

Example:

aFile = C:\aPath\aFile.txt
#File_WriteLine("write this string to a file",aFile,14,"s")

Original Source:

Chris (http://www.autohotkey.com/forum/viewtopic.php?t=417)

*/
#File_WriteLine(aString,aFile,aLineNr,x)
{
   #Main_SpeedMax()
   Loop, read, %aFile%, %aFile%.tmp
   {
      if a_index <> %aLineNr%
           FileAppend, %A_LoopReadLine%`n
      else if x = r
         FileAppend, %aString%`n
      else if x = e
         FileAppend, %A_LoopReadLine%%aString%`n
      else if x = s
         FileAppend, %aString%%A_LoopReadLine%`n
      else if x is integer
      {
         aLineLen := StrLen(A_LoopReadLine)
         remLineLen = %aLineLen%
         remLineLen -= %aLineNr%
         StringLeft, beforeString, A_LoopReadLine, %x%
         StringMid, afterString, A_LoopReadLine, %aLineLen%, %remLineLen%, L
         FileAppend, %beforeString%%aString%%afterString%`n
      }
      else if x = d
         FileAppend,
      else
         #Main_Error("The option you provided is not valid",ERRORLEVEL,A_LineNumber,A_LineFile)
   }
   FileMove, %aFile%.tmp, %aFile%, 1
   #Main_SpeedRestore()
}


And here the used snippets from my main include file:

main.ahk

Code:
#Main_SpeedMax()
{
   global #prevBL
   #prevBL = %A_BatchLines%
   SetBatchLines = -1
}

#Main_SpeedRestore()
{
   global #prevBL
   SetBatchLines, %#prevBL%
}

#Main_Error(aMessage,aCaptEL,aLineNr,aScript)
{
   MsgBox, 0, *** ERROR! ***, Message:`n`n%aMessage%`n`nErrorLevel: %aCaptEL%`n`nScript:`n`n%aScript%`n`nLine Nr: %aLineNr%
   Pause, on
   MsgBox, 1, Script Paused!, The script %aScript% was paused.`n`nPress 'OK' to continue or 'Cancel' to exit
   IfMsgBox, OK, Pause, off
   IfMsgBox, Cancel, Exit
}


and finally a test script/snippet:

Code:
#include C:\thepathtoyour\includefilesfolder\main.ahk
#include C:\thepathtoyour\includefilesfolder\file.ahk

; the following would insert the string "this is a test line to insert"
; into line number 11 at character position 10 in file %aFile%

aFile = %a_scriptdir%\aFile.txt
#File_WriteLine("this is a test line to insert",aFile,11,"10")


'My' includeable-functions-library is still very much a work in progress, so any comments/improvement suggestions are welcome Smile
_________________


Get your own Ron Paul 2008 userbar!
Back to top
View user's profile Send private message Send e-mail Visit poster's website AIM Address Yahoo Messenger MSN Messenger
Dragonscloud



Joined: 16 Jul 2005
Posts: 90

PostPosted: Tue Jul 26, 2005 7:55 pm    Post subject: Reply with quote

Chris wrote:


Also, how often is it that more than one line would need to be deleted/modified/inserted? If often, the loop technique currently used probably performs better than the command would (since the command must delete/modify/insert only one line at a time, and must rescan and rebuild the file each time).


I think it'd be awesome to be able to replace multiple lines in a text document, script, cascading style sheet, or what-have-you. As a for-instance:
I have a huge CSS code in a web page. I want to be able to change a certain block of code on-the fly (scrollbar colors or what-have-you)
I could include a comment within the CSS like <!-- [ScrollBar] --> For whatever blocks of code I might want to change on-the-fly without having to hunt them down in the html editor. I'd like to be able to, in an ahk script, display in an edit field that block of code or do a gui-less replace between two commented lines such as
<!-- [ScrollBar] --> <!-- [/Scrollbar] -->
In other words, the script would look for beginning and ending "bookmarks" and act on the contents in between. Read loops, etc., could probably also work within the block. Rather than having to specify a line number, the script author would specify a beginning and ending string.

(Not syntactically correct, but should convey the gist:)
BlockReplace, BeginningString, EndingString [, ReplacementText, Options]

Loop, Read, %A_ReadBlockLine%, etc....

The above is probably possible already (I'm a novice), but simplification of the process would be welcome if practical.
_________________
“yields falsehood when preceded by its quotation” yields falsehood when preceded by its quotation.
Back to top
View user's profile Send private message
Chris
Site Admin


Joined: 02 Mar 2004
Posts: 10450

PostPosted: Wed Jul 27, 2005 3:36 am    Post subject: Reply with quote

Although some new file commands such as FileWrite and FileOpen will probably get added eventually, more elaborate actions such as searching and replacing text inside a file will probably not get built in. This is because the performance of having the script do it (either via FileRead or a file-reading loop) is approximately the same as having the program do it, at least when the file is uncached. The reason for this is that disk I/O is very slow compared to the CPU. Thus, the CPU spends most of its time waiting for the disk to serve up more data.

However, if you or anyone writes useful functions that would have relatively broad appeal, they would be candidates for distribution with AutoHotkey in a "standard includes" folder. This is almost as convenient as having new built-in commands because such functions could become visibible to a script via something like #Include <FileOps.ahk>
Back to top
View user's profile Send private message Send e-mail
Thalon



Joined: 12 Jul 2005
Posts: 640

PostPosted: Thu Dec 15, 2005 9:41 am    Post subject: Reply with quote

Hmm I didn't know that the complete file has to be recreated when you have to just insert a line (terrible Confused ).

In this case I think a built-in-feature wouldn't be necessary...

My idea (in another thread) was like this:
I read a file to a variable and parse the variable for some content (because it performs much better then reading a file line by line).
Over the A_Index-Variable I would know the line-number I want to change (or insert something before). I hoped that inserting one line would perform also much better then rewriting my whole file (which can be 8+ MB in my case).

Hmm.. shit happens...

I will write a function to do this in AHK and provide it...

Thalon
_________________
AHK-Icon-Changer
AHK-IRC
deutsches Forum
SacredVault
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    AutoHotkey Community Forum Index -> Wish List All times are GMT
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You can post new topics in this forum
You can reply to topics in this forum


Powered by phpBB © 2001, 2005 phpBB Group