BlackFlag Posted June 30, 2021 Share Posted June 30, 2021 I seem to have two modes when using Autoit. No problems what-so-ever most of the time or being completely baffled over something that seems to be easy. Luckily, the baffled part only seems happens once every two years or so. What I am trying to do. I have a file that includes a vessel name and part of its assigned serial number. Reduced, this is what I am using: $whatthe=FileOpen("C:\QUAD Manager Accounts\__ ADVANTAGE\__ ADVANTAGE.128",16) $readthefile=FileRead($whatthe) $apple=BinaryToString($readthefile,1) MsgBox(1,"Hope",$apple) $testtxt=fileopen("C:\QUAD Manager Accounts\__ ADVANTAGE\__ ADVANTAGE.test",2) FileWrite($testtxt,$apple) When I run this, it does read return the vessel name (in this case the good ship F/V Advantage) but never the serial number. I am assuming that I am not parsing the file correctly but I cannot figure out how to do it. Link to comment Share on other sites More sharing options...
Nine Posted June 30, 2021 Share Posted June 30, 2021 Upload the source file so we can take a look “They did not know it was impossible, so they did it” ― Mark Twain Spoiler Block all input without UAC Save/Retrieve Images to/from Text Monitor Management (VCP commands) Tool to search in text (au3) files Date Range Picker Virtual Desktop Manager Sudoku Game 2020 Overlapped Named Pipe IPC HotString 2.0 - Hot keys with string x64 Bitwise Operations Multi-keyboards HotKeySet Recursive Array Display Fast and simple WCD IPC Multiple Folders Selector Printer Manager GIF Animation (cached) Screen Scraping Multi-Threading Made Easy Link to comment Share on other sites More sharing options...
BlackFlag Posted June 30, 2021 Author Share Posted June 30, 2021 Find it attached. The name is __Advantage and the serial number should be (I think, the vessel sank in 2010 and the paper file has been archived) 285 __ ADVANTAGE.128 Link to comment Share on other sites More sharing options...
TheXman Posted July 1, 2021 Share Posted July 1, 2021 (edited) Since you didn't provide the record layout of the binary data, which would ordinarily be required, the script below makes the following assumptions: The name of the vessel is a null-terminated char string, starting at offset 0x00 (0), and is no longer than 32 bytes. The serial number is a little-endian uint (32-bit unsigned integer), starting at offset 0x20 (32) If the script doesn't work with other records/files, then you need to supply a record layout or make the necessary modifications yourself. Finally, this is just one of many ways that it could be done. #include <Constants.au3> example() Func example() Local $hFile Local $tByteBuffer = DllStructCreate("byte data[128]"), _ $tRecord = DllStructCreate("char vessel[32]; uint serialNo", DllStructGetPtr($tByteBuffer)) ;Open the file $hFile = FileOpen("__ ADVANTAGE.128", $FO_BINARY) If $hfile = -1 Then Exit MsgBox($MB_ICONERROR + $MB_TOPMOST, "ERROR", "Unable to open file") ;Read the binary data from the file & close the file $tByteBuffer.data = FileRead($hfile) FileClose($hfile) ;Display fields ConsoleWrite("Vessel = " & $tRecord.vessel & @CRLF) ConsoleWrite("Serial = " & $tRecord.serialNo & @CRLF) EndFunc Console output: Vessel = __ ADVANTAGE Serial = 285 Edited July 1, 2021 by TheXman Changed serial number from a word to a uint JockoDundee 1 CryptoNG UDF: Cryptography API: Next Gen jq UDF: Powerful and Flexible JSON Processor | jqPlayground: An Interactive JSON Processor Xml2Json UDF: Transform XML to JSON | HttpApi UDF: HTTP Server API | Roku Remote: Example Script About Me How To Ask Good Questions On Technical And Scientific Forums (Detailed) | How to Ask Good Technical Questions (Brief) "Any fool can know. The point is to understand." -Albert Einstein "If you think you're a big fish, it's probably because you only swim in small ponds." ~TheXman Link to comment Share on other sites More sharing options...
JockoDundee Posted July 1, 2021 Share Posted July 1, 2021 @TheXman, your use of DllStructs without any corresponding DllCall is edifying.* Curious, apart from using them with DllCalls or to sort a binary overlay (as in this case), do you find it useful to create structs just to use as standalone data structures? Are there any downsides to that? *Apology to BlackFlag for the off-topic Code hard, but don’t hard code... Link to comment Share on other sites More sharing options...
TheXman Posted July 1, 2021 Share Posted July 1, 2021 (edited) I don't associate DllStructs with DllCalls. I only associate DllStructs with binary data/records. If I need to work with well-defined binary data/records, then I usually use DllStructs. Sometimes I will just parse out the fields with BinaryMid() functions, but I find it cleaner and easier to maintain structs. At the moment, I can't think of any downsides to using structs to work with binary data. On the other hand, I can think of at least a couple on downsides to using BinaryMid() instead of DllStructs, which mostly involve having to calculate and manage offsets as well as the additional functions necessary to do some of the data type conversions. I forgot to mention that I also think of DllStructs if I need to work with data pointers. Edited July 1, 2021 by TheXman JockoDundee 1 CryptoNG UDF: Cryptography API: Next Gen jq UDF: Powerful and Flexible JSON Processor | jqPlayground: An Interactive JSON Processor Xml2Json UDF: Transform XML to JSON | HttpApi UDF: HTTP Server API | Roku Remote: Example Script About Me How To Ask Good Questions On Technical And Scientific Forums (Detailed) | How to Ask Good Technical Questions (Brief) "Any fool can know. The point is to understand." -Albert Einstein "If you think you're a big fish, it's probably because you only swim in small ponds." ~TheXman Link to comment Share on other sites More sharing options...
RTFC Posted July 1, 2021 Share Posted July 1, 2021 Agree with @TheXman, DllStructs are absolutely the way to access and (re)interpret binary data. However, an important caveat is the alignment of its data members. By default, AutoIt uses 8 bytes with #pragma pack directive, which can produce all manner of unexpected misinterpretations due to undesired/unexpected shifts (note that member type size may change depending on processor architecture, e.g., ptrs and handles in x86 vs x64). To prevent this, I always explicitly align in any struct definition (simply add "align #;" prior to the first data member definition, with # = number of bytes to align each member on), which serves as a note to self (and others reading the code) and may significantly speed up I/O when dealing with large binary data sets. JockoDundee and TheDcoder 2 My Contributions and Wrappers Spoiler BitMaskSudokuSolver BuildPartitionTable CodeCrypter CodeScanner DigitalDisplay Eigen4AutoIt FAT Suite HighMem MetaCodeFileLibrary OSgrid Pool RdRand SecondDesktop SimulatedAnnealing Xbase I/O Link to comment Share on other sites More sharing options...
JockoDundee Posted July 1, 2021 Share Posted July 1, 2021 @TheXman, @RTFC: What you guys are saying makes sense, thx. OTOH, I’m not sure I’ve made myself totally clear. Basically because you are referring to “interpret[ing]” and “well-defined records” etc. And I agree there. But I am also talking about just for internal variable storage - as a way to compensate for there being no direct support for structs in AutoIt. tl dr; I just want to use them so that I can dot notation in my program - and not necessarily as an interface to some predefined binary record. Does that make sense? Code hard, but don’t hard code... Link to comment Share on other sites More sharing options...
RTFC Posted July 1, 2021 Share Posted July 1, 2021 (edited) 4 hours ago, JockoDundee said: Does that make sense? Sure. One way to think of structs is as a single database record with named fields containing a fixed-order, fixed-width combination of desired variable types. Dot notation would be one way of accessing the contents of a specific field (DllStructGet/SetData being another). I guess I was thinking more of (numeric) offset-based access from a pointer to the struct. Another cool feature of structs is that any part (or the entire struct) can be remapped (by parsing the 2nd, optional ptr parameter (obtained with DllStructGetPtr) to a second DllStructCreate call) using a different struct definition, which can for example be used to achieve the equivalent of reinterpret_cast<new type> in C++. Edited July 1, 2021 by RTFC JockoDundee 1 My Contributions and Wrappers Spoiler BitMaskSudokuSolver BuildPartitionTable CodeCrypter CodeScanner DigitalDisplay Eigen4AutoIt FAT Suite HighMem MetaCodeFileLibrary OSgrid Pool RdRand SecondDesktop SimulatedAnnealing Xbase I/O Link to comment Share on other sites More sharing options...
JockoDundee Posted July 1, 2021 Share Posted July 1, 2021 4 hours ago, RTFC said: Another cool feature of structs is that any part (or the entire struct) can be remapped… Much like removable drawers in an IKEA wardrobe RTFC 1 Code hard, but don’t hard code... Link to comment Share on other sites More sharing options...
BlackFlag Posted July 2, 2021 Author Share Posted July 2, 2021 TheXman Thank you, I plugged it into the program I was writing and it worked like a charm. I'll spend a couple of days next week understanding how it works. I have two or three other projects that DllStructCreate could be very useful in. Link to comment Share on other sites More sharing options...
JockoDundee Posted July 3, 2021 Share Posted July 3, 2021 @BlackFlag, mark his post as the solution to increase its visibility… Code hard, but don’t hard code... 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