![]() |
![]() | ![]() | ![]() | ![]() | ![]() | ![]() | ![]() |
| Welcome to Windows Vista Forums. Our forum is dedicated to helping you find solutions with any problems, errors or issues you are experiencing with Windows Vista. The Vista forum also covers news and updates and has an extensive Windows Vista tutorial section that covers a wide range of tips and tricks. |
| |||||||
![]() |
| |
| | #1 (permalink) |
| | search and replace in binary file I'm trying to do a search and replace in a binary file, which is a user-specific file used by a web-conferencing application. I'm trying to preset some config settings that cause errors when the app is started using the default settings. I've edited the file manually (in Notepad) to confirm the overall idea works. The changes I need to make to the file are regular text edits, with the exception of one character, which I'm not sure if it's a return character, tab, etc. Looks like I can't attach files here, so best I can do is describe it: the non-text character looks like an open rectangle. First I get the name of the logged in user so that data can be used for building the path to the user-specific file I'm trying to edit. After that I've tried 2 different approaches: reading through my file a line at a time, and also splitting it into an array. Both of these return only a single character, which is one of the funky rectangle characters, which is the first thing in the file. Based on what I've read online, there are some possible binary conversion options, although I'm not at all clear on how these would work. At any rate, here's the code I have: Option Explicit ' declare variables Dim objNetwork, objWMIService, objComputer, objFSO, objTextFile Dim colComputer Dim strComputer, strUser, strUserProfilePath, strNextLine, strFileText Dim arrTokens, aDataFile Dim nF ' set constants Const ForReading = 1 Const ForWriting = 2 Set objNetwork = CreateObject("Wscript.Network") strComputer = "." Set objNetwork = CreateObject("WScript.Network") Set objWMIService = GetObject("winmgmts:" _ & "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2") Set colComputer = objWMIService.ExecQuery _ ("Select * from Win32_ComputerSystem") ' for each logged in user (there should only be 1), ' parse the string (ADMINS\username) to get just the username For Each objComputer in colComputer strUser = objComputer.UserName arrTokens = split(strUser, "\") strUser = arrTokens(1) Next ' plug strUser into path to UserProfiles.dat so we can edit the file strUserProfilePath = "C:\Documents and Settings\" & strUser & "\Application Data\Web Meeting\" ' check if UserProfiles.dat exists; if it does, open it and read through it Set objFSO = CreateObject("Scripting.FileSystemObject") ' check if file exists; if it does, open it If objFSO.FileExists(strUserProfilePath & "UserProfiles.dat") Then Set objTextFile = objFSO.OpenTextFile(strUserProfilePath & "UserProfiles.dat", ForReading) ' read the whole file If Not objTextFile.AtEndOfStream Then strFileText = objTextFile.ReadAll ' split file into an array aDataFile = Split(strFileText, vbCrLf) ' loop through each item in array, write out the lines For nF = 0 To UBound(aDataFile) WScript.Echo nF & ": " & strFileText Next End If 'OPTIONAL METHOD FOR DEALING WITH BINARY FILE, ' BUT GAVE SAME RESULT AS SPLITTING THE ARRAY ' loop through file, read and write it one line at a time ' Do Until objTextFile.AtEndOfStream ' strNextLine = objTextFile.ReadLine ' WScript.Echo strNextLine ' WScript.Echo " " ' Loop End If ' (if file exists) WScript.Quit I'd obviously need to throw in some search/replace functionality, but I have working code to do that. First hurdle is trying to figure out if there's a way to deal with the binary file in a way that vbs understands it. |
My System Specs![]() |
| | #2 (permalink) |
| | Re: search and replace in binary file "Tony Logan" <TonyLogan@xxxxxx> wrote in message news:6D9CB9E9-DB42-458F-9F9C-1E54D3E2DDDB@xxxxxx Quote: > I'm trying to do a search and replace in a binary file, which is a > user-specific file used by a web-conferencing application. I'm trying to > preset some config settings that cause errors when the app is started > using > the default settings. > > I've edited the file manually (in Notepad) to confirm the overall idea > works. The changes I need to make to the file are regular text edits, with > the exception of one character, which I'm not sure if it's a return > character, tab, etc. Looks like I can't attach files here, so best I can > do > is describe it: the non-text character looks like an open rectangle. > > First I get the name of the logged in user so that data can be used for > building the path to the user-specific file I'm trying to edit. > > After that I've tried 2 different approaches: reading through my file a > line > at a time, and also splitting it into an array. Both of these return only > a > single character, which is one of the funky rectangle characters, which is > the first thing in the file. > > Based on what I've read online, there are some possible binary conversion > options, although I'm not at all clear on how these would work. > > At any rate, here's the code I have: > > Option Explicit > > ' declare variables > Dim objNetwork, objWMIService, objComputer, objFSO, objTextFile > Dim colComputer > Dim strComputer, strUser, strUserProfilePath, strNextLine, strFileText > Dim arrTokens, aDataFile > Dim nF > > ' set constants > Const ForReading = 1 > Const ForWriting = 2 > > > Set objNetwork = CreateObject("Wscript.Network") > > strComputer = "." > Set objNetwork = CreateObject("WScript.Network") > Set objWMIService = GetObject("winmgmts:" _ > & "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2") > Set colComputer = objWMIService.ExecQuery _ > ("Select * from Win32_ComputerSystem") > ' for each logged in user (there should only be 1), > ' parse the string (ADMINS\username) to get just the username > For Each objComputer in colComputer > strUser = objComputer.UserName > arrTokens = split(strUser, "\") > strUser = arrTokens(1) > Next > > ' plug strUser into path to UserProfiles.dat so we can edit the file > strUserProfilePath = "C:\Documents and Settings\" & strUser & > "\Application > Data\Web Meeting\" > > ' check if UserProfiles.dat exists; if it does, open it and read through > it > Set objFSO = CreateObject("Scripting.FileSystemObject") > ' check if file exists; if it does, open it > If objFSO.FileExists(strUserProfilePath & "UserProfiles.dat") Then > Set objTextFile = objFSO.OpenTextFile(strUserProfilePath & > "UserProfiles.dat", ForReading) > ' read the whole file > If Not objTextFile.AtEndOfStream Then > strFileText = objTextFile.ReadAll > ' split file into an array > aDataFile = Split(strFileText, vbCrLf) > ' loop through each item in array, write out the lines > For nF = 0 To UBound(aDataFile) > WScript.Echo nF & ": " & strFileText > Next > End If > > 'OPTIONAL METHOD FOR DEALING WITH BINARY FILE, > ' BUT GAVE SAME RESULT AS SPLITTING THE ARRAY > ' loop through file, read and write it one line at a time > ' Do Until objTextFile.AtEndOfStream > ' strNextLine = objTextFile.ReadLine > ' WScript.Echo strNextLine > ' WScript.Echo " " > ' Loop > End If ' (if file exists) > > WScript.Quit > > > I'd obviously need to throw in some search/replace functionality, but I > have > working code to do that. First hurdle is trying to figure out if there's a > way to deal with the binary file in a way that vbs understands it. > then you'll have to leave it at that: Searching and Replacing text in text files is fine with VB Script, in binary files it is not. However, if you do it just the right way then you can still do it. AFAIK the method is undocumented and probably unsupported. However, before you go down this track you should ascertain if your file is a text or a binary file. Get yourself a proper binary viewer/editor so that you can examine your file properly! XVI32.exe is one - it's free here: www.chmaas.handshake.de. |
My System Specs![]() |
| | #3 (permalink) |
| | Re: search and replace in binary file It's not difficult to handle "binary files". You just have to be careful how you handle Chr(0). If you don't have any null characters (Chr(0)) then you can safely treat it as a text file. There's really no difference. It's just that VBS sees a null as the end of a string, so if you just try to read the whole file out as a textstream you only get up to the first null. To handle nulls and binary files in general you can use this class that uses only VBS and Textstream: www.jsware.net/jsware/scripts.php5#bints If you don't have to worry about nulls then you don't need any special treatment. Non-alphanumeric characters are not a problem. If you need to figure out a particular character, like your open rectangle, you can do it with script. Just write a script like the following and copy/paste your character in the inputbox to get the ascii value. r = InputBox("Enter 1 character.", "Asc conversion") MsgBox Asc(r) You can then use that value with Replace, Split, etc: s = Replace(s, Chr(9), "") |
My System Specs![]() |
| | #4 (permalink) |
| | Re: search and replace in binary file "mayayana" <mayaXXyana@xxxxxx> wrote in message news:%23FkPz93QJHA.4008@xxxxxx Quote: > It's not difficult to handle "binary files". You just have > to be careful how you handle Chr(0). If you don't have > any null characters (Chr(0)) then you can safely treat > it as a text file. There's really no difference. It's just > that VBS sees a null as the end of a string, so if you > just try to read the whole file out as a textstream you only > get up to the first null. I read what you write but I wonder why it is that the following code will happily read up to the end of the file, regardless of any null characters? And why it correctly locates the first letter "a" (which I manually positioned well after the first null)? const sInputName = "c:\Input.bin" const sOutputName = "c:\Output.bin" Set oFSO = CreateObject("Scripting.FileSystemObject") Set oInputFile = oFSO.GetFile(sInputName) Set oOutputFile = oFSO.OpenTextFile(sOutputName, 2, True) Set oData = oInputFile.OpenAsTextStream sString = oData.Read(oInputFile.Size) wscript.echo "The first null character occurs at position " & instr(sString, chr(0)) wscript.echo "The first letter ""a"" occurs at position " & instr(sString, "a") wscript.echo "Number of bytes processed: " & len(sString) oOutputFile.Write(sString) oData.Close oOutputFile.Close |
My System Specs![]() |
| | #5 (permalink) |
| | Re: search and replace in binary file That's what I mean about being careful. If you use Read(x) it will read x number of characters. But if you use ReadAll it will only read up to the first null. (I didn't know that InStr could read past a null in VBS.) My impression is that the whole FSO was a fairly simple thing written at a time when providing file operations for script seemed very luxurious, since VBS hadn't been anything more than a simple IE DOM language to start with. They weren't trying to block binary file ops. They just didn't bother to deal with it. They were making a few basic file IO functions "for dummies", throwing together a package of odds and ends (like FSO and COM object usage) to satisfy the growing interests of admins and others who wanted something more up-to-date, more GUI-ish, than simple console command-line functions that dated back to DOS days. And they tacked those odds and ends onto the existing web scripting language. As a result, the "tradition" of identifying the end of a string with a null character is a partial, willy nilly obstacle in VBS operations. That's why I wrote a class; to take those weaknesses of Textstream and VBS out of the picture by writing all of the basic functions one wants to have with binary files, in straight VBS, while sidestepping the null character problems. Another limitation with FSO is that people using a DBCS (double byte character set) codepage (Chinese, Japanese and Korean) don't have a 1-to-1 correspondence between bytes and characters. Since Textstream is meant to read and write text, that makes binary ops more challenging in those oriental languages. But for the other 4-odd billion of us, there are just the minimal obstacles related to null characters. Quote: > I read what you write but I wonder why it is that the following code will > happily read up to the end of the file, regardless of any null characters? > And why it correctly locates the first letter "a" (which I manually > positioned well after the first null)? > > const sInputName = "c:\Input.bin" > const sOutputName = "c:\Output.bin" > Set oFSO = CreateObject("Scripting.FileSystemObject") > Set oInputFile = oFSO.GetFile(sInputName) > Set oOutputFile = oFSO.OpenTextFile(sOutputName, 2, True) > Set oData = oInputFile.OpenAsTextStream > sString = oData.Read(oInputFile.Size) > wscript.echo "The first null character occurs at position " & Quote: > chr(0)) > wscript.echo "The first letter ""a"" occurs at position " & instr(sString, > "a") > wscript.echo "Number of bytes processed: " & len(sString) > oOutputFile.Write(sString) > oData.Close > oOutputFile.Close > > |
My System Specs![]() |
![]() |
| Thread Tools | |
| |
Similar Threads | ||||
| Thread | Forum | |||
| Binary search and replace | General Discussion | |||
| Search and Replace text file very slow | PowerShell | |||
| Replace Start Menu Search with 3rd Party Search | General Discussion | |||
| Read and search through a binary file | PowerShell | |||
| Search and replace in a text file? | PowerShell | |||