KaineIHC Posted April 30, 2008 Share Posted April 30, 2008 Hi I want to search a file for a specific string, then read in a portion of the file, alter it and then write it back to the file overwriting the original portion. I have tried to use the fileread and filewrite commands but these do not allow me to write to a specific part of the file. I have seen that this is possible using _winapi_readfile and _winapi_writefile but I can't get my head around how this code works. Can anyone help? Thanks Link to comment Share on other sites More sharing options...
PsaltyDS Posted April 30, 2008 Share Posted April 30, 2008 I have seen that this is possible using _winapi_readfile and _winapi_writefile but I can't get my head around how this code works.Where did you see it? What code?I don't think you can write to the middle of a file. You would have to make the new data match the old in length byte-for-byte. Where have you seen that this is possible? Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law Link to comment Share on other sites More sharing options...
weaponx Posted April 30, 2008 Share Posted April 30, 2008 I'm trying to convert this script from VB but i'm not having much success:http://www.freevbcode.com/ShowCode.Asp?ID=1689 Link to comment Share on other sites More sharing options...
KaineIHC Posted April 30, 2008 Author Share Posted April 30, 2008 Where did you see it? What code?I don't think you can write to the middle of a file. You would have to make the new data match the old in length byte-for-byte. Where have you seen that this is possible? Hmm, maybe I was mistaken, I was looking in the help files. I was thinkning that the pointer variable in _Winapi_writefile pointed to the file on the disk but it's the position in the buffer - Doh! SorrySo is there any way of writing to a specific location in a file? I want to overwrite data at a specific point in a file, is there a way of setting the write pointer?This seems like a simple function but there doesn't seem to be a way other than reading the whole file, making the changes then writting the whole file back! Link to comment Share on other sites More sharing options...
weaponx Posted April 30, 2008 Share Posted April 30, 2008 (edited) After some testing it appears there is a limitation with _WinAPI_ReadFile that seems to make it useless in AutoIt. This function uses a byte array which I don't think is supported yet.@PsaltyDS - Any clues? I found this god awful topic about byte array implementation:http://www.autoitscript.com/forum/index.ph...;hl=byte++arrayHere is the beginning of my function:expandcollapse popup#Include <WinAPI.au3> #include <array.au3> ;Const $GENERIC_WRITE = 0x40000000 ;Const $GENERIC_READ = 0x80000000 ;Const $FILE_ATTRIBUTE_NORMAL = 0x80 ;Const $CREATE_ALWAYS = 2 ;Const $OPEN_ALWAYS = 4 Const $INVALID_HANDLE_VALUE = -1 ;$root = @DesktopDir ;Filename, creation, access ;$handle = _WinAPI_CreateFile($root & "\" & $filename, 2, 2) ReadStringFromFile(@DesktopDir & "\" & "test.txt") Func ReadStringFromFile($FileName) ;'*************************************************************** ;'PURPOSE: READS STRING DATA FROM FILE USING READFILE API ; ;'PARAMETERS: FileName: Name Of File ; ;'RETURNS: Contents of file as a string ; ;'EXAMPLE: dim sAns as String ;' sAns = ReadStringFromFile("C:\MyFile.txt") ;'************************************************************** ;On Error GoTo ErrorHandler Dim $lHandle ;As Long Dim $lSuccess ;As Long Dim $lBytesRead ;As Long Dim $lBytesToRead ;As Long Dim $bytArr[1] ;As Byte Dim $sAns ;As String $lBytesToRead = FileGetSize($FileName) ;ReDim $bytArr[$lBytesToRead] ;As Byte ;'Get a handle to file $lHandle = _WinAPI_CreateFile($FileName, 2,2) If $lHandle <> $INVALID_HANDLE_VALUE Then ConsoleWrite("File opened successfully" & @CRLF) ;'read file contents into a bytearray and convert to string $lSuccess = _WinAPI_ReadFile($lHandle, $bytArr, $lBytesToRead, $lBytesRead) If $lSuccess Then ConsoleWrite("ReadFile SUCCESSFUL" & @CRLF) Else ConsoleWrite("ReadFile FAILED" & @CRLF) EndIf ;_ArrayDisplay($bytArr) $sAns = ByteArrayToString($bytArr) ConsoleWrite($sAns) _WinAPI_CloseHandle($lHandle) Return $sAns EndIf ;ErrorHandler: EndFunc Edited April 30, 2008 by weaponx Link to comment Share on other sites More sharing options...
weaponx Posted April 30, 2008 Share Posted April 30, 2008 Perhaps ignore the last post. I found a way to use the returned byte array. expandcollapse popup#Include <WinAPI.au3> #include <array.au3> Const $INVALID_HANDLE_VALUE = -1 $result = ReadStringFromFile(@DesktopDir & "\" & "test.txt") MsgBox(0,"File contents", $result) Func ReadStringFromFile($FileName) Dim $lHandle ;As Long ;Dim $lSuccess ;As Long Dim $lBytesRead = 0;As Long Dim $lBytesToRead = 0;As Long ;Dim $bytArr[1] ;As Byte Dim $sAns = "" ;As String $lBytesToRead = FileGetSize($FileName) ;ReDim $bytArr[$lBytesToRead] ;As Byte ;'Get a handle to file $lHandle = _WinAPI_CreateFile($FileName, 2,2) If $lHandle <> $INVALID_HANDLE_VALUE Then ConsoleWrite("File opened successfully" & @CRLF) $tBuffer = DllStructCreate("char Text[" & $lBytesToRead & "]") ;'read file contents into a bytearray and convert to string $lSuccess = _WinAPI_ReadFile($lHandle, DllStructGetPtr($tBuffer), $lBytesToRead, $lBytesRead) If $lSuccess Then ConsoleWrite("ReadFile OK" & @CRLF) $sAns = DllStructGetData($tBuffer,1) Else ConsoleWrite("ReadFile FAIL" & @CRLF) EndIf _WinAPI_CloseHandle($lHandle) Return $sAns EndIf EndFunc Link to comment Share on other sites More sharing options...
PsaltyDS Posted April 30, 2008 Share Posted April 30, 2008 After some testing it appears there is a limitation with _WinAPI_ReadFile that seems to make it useless in AutoIt. This function uses a byte array which I don't think is supported yet.@PsaltyDS - Any clues? I found this god awful topic about byte array implementation:http://www.autoitscript.com/forum/index.ph...;hl=byte++arrayI created Bug Trac #50 on that, and it is listed as a Feature Request owned by Valik now. Valik was sympathetic to adding it, some day, but not as a priority based on how busy he is, and how few requirements they see for this feature. You might prod Valik with your interest and maybe it will get bumped up the priority list some. Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law Link to comment Share on other sites More sharing options...
KaineIHC Posted April 30, 2008 Author Share Posted April 30, 2008 couldnt you just use _FileReadToArray ( $sFilePath, $aArray ) ? Link to comment Share on other sites More sharing options...
weaponx Posted April 30, 2008 Share Posted April 30, 2008 couldnt you just use _FileReadToArray ( $sFilePath, $aArray ) ?Yes but I thought we were trying to tail write a file without opening it like RandallC's TailRW UDF. Link to comment Share on other sites More sharing options...
KaineIHC Posted April 30, 2008 Author Share Posted April 30, 2008 Yes but I thought we were trying to tail write a file without opening it like RandallC's TailRW UDF. Yeah I am, my response was in reply to your 1st post: "I'm trying to convert this script from VB but i'm not having much success: http://www.freevbcode.com/ShowCode.Asp?ID=1689" Sorry if I sound like a bit of a noob, er, that's cos I am - lol The code you posted just reads the file doesn't it, reading it isnt the problem I can use fileread and read it byte by byte until the point I am looking for, it's writing the data back to that same point thats the problem. Link to comment Share on other sites More sharing options...
weaponx Posted April 30, 2008 Share Posted April 30, 2008 (edited) Yeah I am, my response was in reply to your 1st post: "I'm trying to convert this script from VB but i'm not having much success: http://www.freevbcode.com/ShowCode.Asp?ID=1689" Sorry if I sound like a bit of a noob, er, that's cos I am - lol The code you posted just reads the file doesn't it, reading it isnt the problem I can use fileread and read it byte by byte until the point I am looking for, it's writing the data back to that same point thats the problem. I was only showing that function as a test, I wasn't sure if we could actually write to specific position in the file. I'm still not really sure if we can. If we could create a byte array the same same size as the file to be written, we might be able to insert the data we want written into the array and write it., kind of like a mask, it won't allow the filesize to change, just overwrite. I have doubts that WinAPI is the proper method for this. Edited April 30, 2008 by weaponx Link to comment Share on other sites More sharing options...
PsaltyDS Posted April 30, 2008 Share Posted April 30, 2008 Perhaps ignore the last post. I found a way to use the returned byte array. expandcollapse popup#Include <WinAPI.au3> #include <array.au3> Const $INVALID_HANDLE_VALUE = -1 $result = ReadStringFromFile(@DesktopDir & "\" & "test.txt") MsgBox(0,"File contents", $result) Func ReadStringFromFile($FileName) Dim $lHandle ;As Long ;Dim $lSuccess ;As Long Dim $lBytesRead = 0;As Long Dim $lBytesToRead = 0;As Long ;Dim $bytArr[1] ;As Byte Dim $sAns = "" ;As String $lBytesToRead = FileGetSize($FileName) ;ReDim $bytArr[$lBytesToRead] ;As Byte ;'Get a handle to file $lHandle = _WinAPI_CreateFile($FileName, 2,2) If $lHandle <> $INVALID_HANDLE_VALUE Then ConsoleWrite("File opened successfully" & @CRLF) $tBuffer = DllStructCreate("char Text[" & $lBytesToRead & "]") ;'read file contents into a bytearray and convert to string $lSuccess = _WinAPI_ReadFile($lHandle, DllStructGetPtr($tBuffer), $lBytesToRead, $lBytesRead) If $lSuccess Then ConsoleWrite("ReadFile OK" & @CRLF) $sAns = DllStructGetData($tBuffer,1) Else ConsoleWrite("ReadFile FAIL" & @CRLF) EndIf _WinAPI_CloseHandle($lHandle) Return $sAns EndIf EndFunc I'm not an expert in this by any means, but I don't think what you have there is technically a Byte-array. JPM and ptrex know a lot more about it than I do, and using a DLL struct was tried and rejected for working with what I understood to be "real" Byte-arrays (which I believe were binary, not char, in the context we were working with). As for writing to the middle of the file, you would still be reading the entire file into some kind of structure in memory, modifying it in memory, and then writing the whole thing back, wouldn't you? The OP seemed to want to write only to a specific location in the file, without having to re-write the unmodified data that followed, and this is part that I don't think you can do from Windows APIs or AutoIt. Perhaps with low-level disk driver stuff, I don't know. Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law Link to comment Share on other sites More sharing options...
KaineIHC Posted April 30, 2008 Author Share Posted April 30, 2008 I've just searched for tailRW and it looks like it may do what I am wanting. I'll give it a try later, thanks for your help. Link to comment Share on other sites More sharing options...
weaponx Posted April 30, 2008 Share Posted April 30, 2008 (edited) I'm not an expert in this by any means, but I don't think what you have there is technically a Byte-array. JPM and ptrex know a lot more about it than I do, and using a DLL struct was tried and rejected for working with what I understood to be "real" Byte-arrays (which I believe were binary, not char, in the context we were working with). As for writing to the middle of the file, you would still be reading the entire file into some kind of structure in memory, modifying it in memory, and then writing the whole thing back, wouldn't you? The OP seemed to want to write only to a specific location in the file, without having to re-write the unmodified data that followed, and this is part that I don't think you can do from Windows APIs or AutoIt. Perhaps with low-level disk driver stuff, I don't know. I think you are correct in saying this isn't technically a byte array. This method is no good for reading in binary data. Also _WinAPI_WriteFile doesn't know what the hell to do with the struct when you pass it back. Project status - FAILURE Edited April 30, 2008 by weaponx Link to comment Share on other sites More sharing options...
Polyphem Posted May 5, 2008 Share Posted May 5, 2008 ...reading it isnt the problem I can use fileread and read it byte by byte until the point I am looking for, it's writing the data back to that same point thats the problem. I'm just digging into this because I want to read only at specific points... found a function which "might" (dont know ) help you too.... expandcollapse popup_WinAPI_SetFilePointer($lHandle, $bytes_read_start_at) ; File-Handle as input, success changes the file-handle pointer position Func _WinAPI_SetFilePointer($hFile, $pmove = 0) Local $aResult $aResult = DllCall("Kernel32.dll", "int", "SetFilePointer", "hwnd", $hFile, "int", $pmove, "int", "NULL", "int", 0) Return SetError(_WinAPI_GetLastError(), 0, $aResult[0] <> 0) Return $aResult #cs http://msdn.microsoft.com/en-us/library/aa365541(VS.85).aspx DWORD WINAPI SetFilePointer( __in HANDLE hFile, __in LONG lDistanceToMove, __inout_opt PLONG lpDistanceToMoveHigh, __in DWORD dwMoveMethod ); Parameters hFile A handle to the file. The file handle must be created with the GENERIC_READ or GENERIC_WRITE access right. For more information, see File Security and Access Rights. lDistanceToMove The low order 32-bits of a signed value that specifies the number of bytes to move the file pointer. If lpDistanceToMoveHigh is not NULL, lpDistanceToMoveHigh and lDistanceToMove form a single 64-bit signed value that specifies the distance to move. If lpDistanceToMoveHigh is NULL, lDistanceToMove is a 32-bit signed value. A positive value for lDistanceToMove moves the file pointer forward in the file, and a negative value moves the file pointer back. lpDistanceToMoveHigh A pointer to the high order 32-bits of the signed 64-bit distance to move. If you do not need the high order 32-bits, this pointer must be set to NULL. When not NULL, this parameter also receives the high order DWORD of the new value of the file pointer. For more information, see the Remarks section in this topic. dwMoveMethod The starting point for the file pointer move. This parameter can be one of the following values. Value Meaning FILE_BEGIN The starting point is zero (0) or the beginning of the file. 0 FILE_CURRENT The starting point is the current value of the file pointer. 1 FILE_END The starting point is the current end-of-file position. 2 If the function succeeds and lpDistanceToMoveHigh is NULL, the return value is the low-order DWORD of the new file pointer. #ce EndFunc ;==>_WinAPI_SetFilePointer This post will be edited again by Polyphem: Tomorrow, 11:55 AM Link to comment Share on other sites More sharing options...
PsaltyDS Posted June 27, 2008 Share Posted June 27, 2008 (edited) I'm just digging into this because I want to read only at specific points... found a function which "might" (dont know ) help you too.... _WinAPI_SetFilePointer($lHandle, $bytes_read_start_at); File-Handle as input, success changes the file-handle pointer position Func _WinAPI_SetFilePointer($hFile, $pmove = 0) Local $aResult $aResult = DllCall("Kernel32.dll", "int", "SetFilePointer", "hwnd", $hFile, "int", $pmove, "int", "NULL", "int", 0) Return SetError(_WinAPI_GetLastError(), 0, $aResult[0] <> 0) Return $aResult EndFunc ;==>_WinAPI_SetFilePointer Where did you find your version? I like adding some error handling to the wrapper. This DLL call is also already in randallc's ApiTailRW.au3 UDF. He in turn got it from Larry: ;=============================================================================== ; ; Function Name: _FileSetPosAPI(); ( <FileHandle>, <Position in the file to read/write to/from> ) ; Description: Sets pointer position in file ; Parameter(s): $hFile - FileHandle of open (API) file ; Requirement(s): Requires AutoIT 3.2 minimum ; Return Value(s): On Success - value from SetFilePointer api;the return value is nonzero ; On Failure - ?** not set - value from SetFilePointer api;;the return value is zero ; Author(s): Larry ; ;=============================================================================== Func _FileSetPosAPI($hFile, $nPos) Local $FILE_BEGIN = 0 Local $AFSP_r = DllCall("kernel32.dll", "long", "SetFilePointer", "hwnd", $hFile, "long", $nPos, "long_ptr", 0, "long", $FILE_BEGIN) Return $AFSP_r[0] EndFunc ;==>_FileSetPosAPI Edited June 27, 2008 by PsaltyDS Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now