Login | |
|
 |
How do I? byte array converted to long, to date... - 12/9/2006 4:51:40 PM
|
|
 |
|
| |
bofaboy
Posts: 16
Score: 0
Joined: 12/9/2006
Status: offline
|
Howdy, I've got an array of ASCII string data in a log file file that I want to pull out and input to SQL for an application I monitor.. The problem is that the date coded in the file is a byte arraythat needs to be converted to a long int (seconds since epoch) 68,116,53,22,0,0,17,36 --ascii character codes data and I want to create a date out of it... in Perl, I have prototyped the following code (if it helps): $foo = pack("c8",68,116,53,22,0,0,17,36); #pack up the character/byte string $foo2 = unpack("N",$foo); #convert the packed data structure to a long integer $foo2 += 32768; #add 32768 because it seems as though the timing is slightly off for this application print "foo2 = ".$foo2."\n"; #output the long int print "foo2: " .scalar(localtime($foo2))."\n"; #output the date output: foo2 = 1148499222 foo2: Wed May 24 12:33:42 2006 ------------------- in my VB coding, I've tried this... thisvar = Asc(68) & Asc(116) & Asc(53)& Asc(22) & Asc(0) & Asc(0) & Asc(17) & Asc(36) foo2 = CLng(thisvar) -- should equal 1148466454 ---- ERRORS here.. foo2 = foo2 + 32768 'should equal 1148499222 print "foo2 (i) = "& foo2 print "foo2: (d) = " & DateAdd("s", foo2, "01/01/1970 00:00:00") output: C:\Perl\Scripts\cdate.vbs(3, 1) Microsoft VBScript runtime error: Type mismatch: 'CLng'
|
|
| |
|
|
|
 |
RE: How do I? byte array converted to long, to date... - 12/10/2006 3:35:11 AM
|
|
 |
|
| |
TNO
Posts: 1397
Score: 16
Joined: 12/18/2004
From: thenewobjective.com
Status: offline
|
could you explain what pack/unpack is in Perl? What does it do? I'm sure we can get an equivalent
_____________________________
To iterate is human, to recurse divine. -- L. Peter Deutsch
|
|
| |
|
|
|
 |
RE: How do I? byte array converted to long, to date... - 12/10/2006 3:45:00 AM
|
|
 |
|
| |
bofaboy
Posts: 16
Score: 0
Joined: 12/9/2006
Status: offline
|
sure: Basically it takes the array of unsigned chars (denoted by the C8 -- 8 unsigned chars), and coreces it to a binary structure.. then the unpack takes that binary structure and converts it to a "long in network order" denoted by the "N". I hope that this excerpt helps.. I'm not sure of exactly what it does beyond that explanation (and the following excerpt) excerpt from: http://www.cs.cmu.edu/People/rgs/pl-exp-conv.html pack(TEMPLATE,LIST) Takes an array or list of values and packs it into a binary structure, returning the string containing the structure. The TEMPLATE is a sequence of characters that give the order and type of values, as follows: A An ascii string, will be space padded. a An ascii string, will be null padded. c A signed char value. C An unsigned char value. s A signed short value. S An unsigned short value. i A signed integer value. I An unsigned integer value. l A signed long value. L An unsigned long value. n A short in "network" order. N A long in "network" order. f A single-precision float in the native format. d A double-precision float in the native format. p A pointer to a string. v A short in "VAX" (little-endian) order. V A long in "VAX" (little-endian) order. x A null byte. X Back up a byte. @ Null fill to absolute position. u A uuencoded string. b A bit string (ascending bit order, like vec()). B A bit string (descending bit order). h A hex string (low nybble first). H A hex string (high nybble first). Each letter may optionally be followed by a number which gives a repeat count. With all types except "a", "A", "b", "B", "h" and "H", the pack function will gobble up that many values from the LIST. A * for the repeat count means to use however many items are left. The "a" and "A" types gobble just one value, but pack it as a string of length count, padding with nulls or spaces as necessary. (When unpacking, "A" strips trailing spaces and nulls, but "a" does not.) Likewise, the "b" and "B" fields pack a string that many bits long. The "h" and "H" fields pack a string that many nybbles long. Real numbers (floats and doubles) are in the native machine format only; due to the multiplicity of floating formats around, and the lack of a standard "network" representation, no facility for interchange has been made. This means that packed floating point data written on one machine may not be readable on another - even if both use IEEE floating point arithmetic (as the endian-ness of the memory representation is not part of the IEEE spec). Note that perl uses doubles internally for all numeric calculation, and converting from double -> float -> double will lose precision (i.e. unpack("f", pack("f", $foo)) will not in general equal $foo). Examples: $foo = pack("cccc",65,66,67,68); # foo eq "ABCD" $foo = pack("c4",65,66,67,68); # same thing $foo = pack("ccxxcc",65,66,67,68); # foo eq "AB\0\0CD" $foo = pack("s2",1,2); # "\1\0\2\0" on little-endian # "\0\1\0\2" on big-endian $foo = pack("a4","abcd","x","y","z"); # "abcd" $foo = pack("aaaa","abcd","x","y","z"); # "axyz" $foo = pack("a14","abcdefg"); # "abcdefg\0\0\0\0\0\0\0" $foo = pack("i9pl", gmtime); # a real struct tm (on my system anyway) sub bintodec { unpack("N", pack("B32", substr("0" x 32 . shift, -32))); }The same template may generally also be used in the unpack function. unpack(TEMPLATE,EXPR) Unpack does the reverse of pack: it takes a string representing a structure and expands it out into an array value, returning the array value. (In a scalar context, it merely returns the first value produced.) The TEMPLATE has the same format as in the pack function. Here's a subroutine that does substring: sub substr { local($what,$where,$howmuch) = @_; unpack("x$where a$howmuch", $what); } and then there's sub ord { unpack("c",$_[0]); } In addition, you may prefix a field with a %<number> to indicate that you want a <number>-bit checksum of the items instead of the items themselves. Default is a 16-bit checksum. For example, the following computes the same number as the System V sum program: while (<>) { $checksum += unpack("%16C*", $_); } $checksum %= 65536;
|
|
| |
|
|
|
 |
RE: How do I? byte array converted to long, to date... - 12/10/2006 5:05:21 AM
|
|
 |
|
| |
TNO
Posts: 1397
Score: 16
Joined: 12/18/2004
From: thenewobjective.com
Status: offline
|
The quick answer is that vbscript has nothing close to pack and unpack......and doesn't handle binary arrays very easily this will take a bit of time to figure out a workaround.
_____________________________
To iterate is human, to recurse divine. -- L. Peter Deutsch
|
|
| |
|
|
|
 |
RE: How do I? byte array converted to long, to date... - 12/10/2006 5:35:21 AM
|
|
 |
|
| |
TNO
Posts: 1397
Score: 16
Joined: 12/18/2004
From: thenewobjective.com
Status: offline
|
What do each of these fields represent? Maybe there is a way to avoid using an activeX control 68,116,53,22,0,0,17,36
_____________________________
To iterate is human, to recurse divine. -- L. Peter Deutsch
|
|
| |
|
|
|
 |
RE: How do I? byte array converted to long, to date... - 12/10/2006 7:07:29 AM
|
|
 |
|
| |
bofaboy
Posts: 16
Score: 0
Joined: 12/9/2006
Status: offline
|
if there's an ActiveX control that will help, I'd love to work with it. That is, if by ActiveX control, you mean COM object -- I think that we're speaking the same language here!? I've worked with a lot of COM objects in VBScript and perl -- if you can point me in the right direction, I could play with it as well. The numbers purely are a byte array that together, convert to seconds since epoch.. (00:00:00 1/1/1970).. In the byte form, they represent nothing. The application that creates this file, successfully converts the data to time after reading the log file, and I want to as well, so I can take the data and store it in a SQL Server, along with Windows Server Eventlogs (that I already capture) so that I can look at the errors/warnings from the application as well while verifying the Eventlogs daily from multiple servers, and acknowledge warnings/errors in a single source. It would be a great help to my company to get this information for all the sites that manage this application (~10 sites). The log file I am parsing doesn't have CRLF line endings for each log entry, and I've been relegated to parsing 188-byte null padded lines of data to extract the various data components (so, I started looking at the data as numbers, so I could see the NULLS (0s)... and try to extrapolate the data from it -- from there I noticed that the only place that was left to look at for the date was position 5-12 in the 188-byte line, so I started playing with the data and found a perl solution that correctly identified the date that the application showed for that log entry... I tested it on a few other date entries as well, and claimed success.. Only then to realize getting the same stuff to work in VB was the bigger task. I'd love to just do it in perl, but I can't as the other sites have no expertise in perl and if I die, or get hit by the proverbial bus, no one can support my application.... and well, management likes VBScript. I can PM you a test log file if you want to see it in action.. but it's an undocumented log file, and there's no programmatic access to dump it to a text file from the application, so I'm parsing ASCII and non-ASCII data out of it. I originally gave you the short version of the problem I am encountering, because I thought where the data came from was trivial.. They store the date as 8 of the 188-bytes in each line of the log file. this section is where I was getting the numbers from.. ignore how I currently store it.. it's a placeholder for when I get the originally posted script to work correctly. if x >= 5 and x <= 12 Then DateStr = DateStr & character End If here's the full code for pulllogfile.vbs... Const forReading = 1 Const adTypeText = 2 Const adTypeBinary = 1 log_file = "c:\temp\\logfile.txt" 'open files 'Create Stream object Set objStream = CreateObject("ADODB.Stream") 'Open the stream And write text/string data To the object objStream.CharSet = "US-ASCII" objStream.Type = adTypeText objStream.Open objStream.LoadFromFile log_file x = 0 'x is your position in the 188-byte line y = 0 'y is your log entry line number z = 0 'z is your counter to determine if you're finished based on number of bytes being less than the size of the file. do while z < objStream.Size x = x + 1 character = objStream.ReadText(1) if y > 0 Then 'ignore the first line FullStr = FullStr & "-" & Asc(character) if x >= 5 and x <= 12 Then DateStr = DateStr & character End If if x >= 13 and x <= 44 Then if Asc(character) >= 32 and Asc(character) < 128 Then Source = Source & character End If End If if x >= 45 and x <=77 Then if Asc(character) >= 32 and Asc(character) < 128 Then Typ = Typ & character End If End If if x = 80 Then if Asc(character) = 1 Then SuccessFailure = "Success" ElseIf Asc(character) = 0 Then SuccessFailure = "Warning" ElseIf Asc(character) = 2 Then SuccessFailure = "Failure" End If End If if x >= 89 and x <=108 Then if Asc(character) >= 32 and Asc(character) < 128 Then Area = Area & character End If End If if x >= 109 and x <=187 Then if Asc(character) >= 32 and Asc(character) < 128 Then Message = Message & character End If End If End If z = z + 1 if x = 187 Then y = y + 1 x = 0 WScript.Echo UDate(CInt(DateStr)) & " -- " & SuccessFailure & " -- " & Source & " -- " & Typ & " -- " & Area & " -- " & Message WScript.Echo WScript.Echo FullStr FullStr = "" TimeStr = "" Source = "" Status = "" Typ = "" DateStr = "" Area = "" Message = "" End If Loop function UDate(intTimeStamp) UDate = DateAdd("s", intTimeStamp, "01/01/1970 00:00:00") end function
< Message edited by bofaboy -- 12/11/2006 5:27:14 AM >
|
|
| |
|
|
|
 |
RE: How do I? byte array converted to long, to date... - 12/10/2006 7:32:58 AM
|
|
 |
|
| |
TNO
Posts: 1397
Score: 16
Joined: 12/18/2004
From: thenewobjective.com
Status: offline
|
Yep, ActiveX <---> COM. There are a few nasty workarounds to would work with the data, but its looks to be around a good 60 lines of code and pretty complex in comparison to PERL in this regard. Maybe one of my colleagues here know of a way to manipulate the bytearray using an inherent COM API, but until that time I'll keep up the search. One thng I do know is that .NET has a method of handling bytearrays easily......And I'm 80% certain that using a PowerShell script you could indirectly access it, as for using it.....not quite sure at this point
_____________________________
To iterate is human, to recurse divine. -- L. Peter Deutsch
|
|
| |
|
|
|
 |
RE: How do I? byte array converted to long, to date... - 12/10/2006 7:36:06 AM
|
|
 |
|
| |
TNO
Posts: 1397
Score: 16
Joined: 12/18/2004
From: thenewobjective.com
Status: offline
|
Heres a link to a component that may help: http://www.voodoofiles.com/20765/ActiveX_ByteArray_object_for_ASP/Net.html not too sure of its legitimacy though
_____________________________
To iterate is human, to recurse divine. -- L. Peter Deutsch
|
|
| |
|
|
|
 |
RE: How do I? byte array converted to long, to date... - 12/10/2006 4:31:13 PM
|
|
 |
|
| |
TNO
Posts: 1397
Score: 16
Joined: 12/18/2004
From: thenewobjective.com
Status: offline
|
Since vbscript is defined to store its numbers as 8-byte IEEE floating-point types, it looks like ehvbs is trying to use base 256....That gives me an idea
_____________________________
To iterate is human, to recurse divine. -- L. Peter Deutsch
|
|
| |
|
|
|
 |
RE: How do I? byte array converted to long, to date... - 12/10/2006 7:31:34 PM
|
|
 |
|
| |
TNO
Posts: 1397
Score: 16
Joined: 12/18/2004
From: thenewobjective.com
Status: offline
|
68,116,53,22,0,0,17,36 I this data what is in the Log file? Or is this after it was converted from what it was? If so, what does the raw data line look like. (The more I look into this, the more unlikely it is that vbscript can do it. Javascript can barely do it by using bit-shifting and modulus division, but its befuddling my brain doing it)
_____________________________
To iterate is human, to recurse divine. -- L. Peter Deutsch
|
|
| |
|
|
|
 |
RE: How do I? byte array converted to long, to date... - 12/11/2006 5:29:39 AM
|
|
 |
|
| |
TNO
Posts: 1397
Score: 16
Joined: 12/18/2004
From: thenewobjective.com
Status: offline
|
I'm gonna have to use one of my life lines Regis....maybe my fellow moderators would lend a hand on this one. So if I'm understanding this right, this is what is happening? 68,116,53,22,0,0,17,36 <----Is this a Byte Array or ASCII Array? Means nothing by itself... (8 bytes?) $foo = pack("c8",68,116,53,22,0,0,17,36) <----What does $foo equal now? It should be a string of binary correct? $foo2 = unpack("N",$foo); <---Convert the binary string into a number (32 bit? 16 bit?) $foo2 should now equal 1148466454 base 10?
_____________________________
To iterate is human, to recurse divine. -- L. Peter Deutsch
|
|
| |
|
|
|
 |
RE: How do I? byte array converted to long, to date... - 12/11/2006 5:33:49 AM
|
|
 |
|
| |
ebgreen
Posts: 5246
Score: 31
Joined: 7/12/2005
Status: online
|
"the numbers are ascii character codes of the data in the file... so, it's extremely easy to convert between the two... letters or numbers." 0 does not correspond to any valid char in ASCII.
_____________________________
"... when you are good and crazy, oooh, oooh, oooh, the sky is the limit!" - The Tick Goog places to start:http://www.visualbasicscript.com/m_24727/tm.htm http://www.visualbasicscript.com/m_47117/tm.htm
|
|
| |
|
|
|
|
|