Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Parse text file into Listview

141 views
Skip to first unread message

Matt Williamson

unread,
Feb 20, 2004, 4:30:50 PM2/20/04
to
I'm having trouble figuring out how to Parse a text file into a listview
efficiently.

I want to create the column headers and fill the listview based upon the
data in the file.

I know I've read some threads in the past that dealt with this, but I can't
seem to find them now.

The data in the textfile is in this format:

Other stuff here
Other stuff here

Name Pid Pri Thd Hnd Mem User Time Kernel Time Elapsed
Time
Idle 0 0 1 0 16 0:00:00.000 1411:17:29.515
1414:04:04.116
System 2 8 53 203 216 0:00:00.000 0:34:02.246
1414:04:04.116
smss 29 11 6 30 20 0:00:00.090 0:00:00.120
1414:04:04.116

I want to use the first line starting with "Name" as my column headers. The
problem is how to get User Time, Kernel Time and Elapsed Time to be their
own header. Right now, I'm just using split on the spaces to create the
column headers, but this won't work. I need a way to re-delimit that line so
the output is something like:

Name,Pid,Pri,Thd,Hnd,Mem,User Time,Kernel Time,Elapsed Time

But I'm at a loss at to how to accomplish it. All of my experiments with
Replace() have yet to yeild anything that works.

Here is the code I have written so far just for reference:

Dim ffile As Long, sLine As String
Dim clmX As ColumnHeader, itmX As ListItem
Dim sClmHeads() As String, bStart As Boolean
Dim i As Long, sListData() As String

ffile = FreeFile

Open "c:\Temp\Test Directory\prcss.tmp" For Input As #ffile
Do While Not EOF(ffile)
Line Input #ffile, sLine
If Not InStr(1, sLine, "Name") = 0 Then ' need to make this better
'Need code here to reformat that line
sClmHeads = Split(sLine) 'split on spaces
For i = LBound(sClmHeads) To UBound(sClmHeads)
If Not Len(sClmHeads(i)) = 0 Then
Set clmX = lvProcesses.ColumnHeaders.Add(, , sClmHeads(i))
Debug.Print i & " - " & sClmHeads(i)
End If
Next
bStart = True
End If
If bStart Then
sListData = Split(sLine)
Set itmX = lvProcesses.ListItems.Add(, , sListData(0))
Debug.Print sLine
For i = LBound(sListData) To UBound(sListData)
If Not Len(sListData(i)) = 0 Then
Debug.Print "# " & i & " - " & Trim(sListData(i))
End If
'itmX.SubItems(i + 1) = sListData(i)
Next
End If
Loop

Close #ffile

End Sub

TIA

Matt


Jim Edgar

unread,
Feb 20, 2004, 5:38:40 PM2/20/04
to

"Matt Williamson" <ih8...@spamsux.org> wrote in message
news:%23BQrki$9DHA...@TK2MSFTNGP12.phx.gbl...

Here's a hack:

Dim strTmp As String

strTmp = "Name Pid Pri Thd Hnd Mem User Time Kernel Time Elapsed Time"
strTmp = Replace(strTmp, " ", ",")
strTmp = Replace(strTmp, ",Time", " Time")

HTH,

Jim Edgar


Randy Birch

unread,
Feb 20, 2004, 6:17:19 PM2/20/04
to
Option Explicit

Private Sub Command1_Click()

Dim hfile As Long
Dim tmp As String
Dim buff() As String
Dim headers() As String
Dim cnt As Long
Dim cnt2 As Long
Dim firstindex As Long
Dim itmx As ListItem
Dim linedata() As String

'get all data into string
hfile = FreeFile
Open "d:\prcss.tmp" For Input As hfile
tmp = Input$(LOF(hfile), hfile)
Close #hfile

'create an array member for each line
buff() = GetArrayData(tmp)

'find the column header string
firstindex = FindItemInArray(buff(), "Name")

If firstindex > -1 Then

'three headers have spaces (User Time,
'Kernel Time, Elapsed Time), so there is no
'1-to-1 correlation between the number of
'distinct (space-delimited) items in the
'header string and the number of actual
'data points in each subsequent line.
'To work around this we replace those extra
'spaces in those three caption titles with a
'character we can locate and replace later
'to allow spaces to now delimit the items
FixSplitHeaderCaptions buff(firstindex)

'make array of each header item
headers() = Split(buff(firstindex), " ")

'create headers, using Replace() to
'undo the 'Fix' applied for the multi-word
'captions
For cnt = LBound(headers()) To UBound(headers())
With ListView1
.ColumnHeaders.Add , , Replace$(headers(cnt), "%", " ")
End With
Next cnt

'now create the data, starting with the
'line following the header
For cnt = (firstindex + 1) To UBound(buff())

'again, split that line on the spaces
linedata() = Split(buff(cnt), " ")

'and add ...
With ListView1
Set itmx = .ListItems.Add(, , linedata(0))

'subitems are easy using a loop
For cnt2 = 1 To 8
itmx.SubItems(cnt2) = linedata(cnt2)
Next cnt2

End With

'prevent reusing previous data
Erase linedata()

Next cnt

Else
MsgBox "error determining start of header data"
End If

'done!

End Sub


Private Function GetArrayData(buff) As String()

'compress spaces in the line to leave
'each items separated by 1 space, and
'split the array using space as the delimiter.
Dim b() As String

buff = Replace(buff, " ", " ")
buff = Replace(buff, " ", " ")
buff = Replace(buff, " ", " ")
buff = Replace(buff, " ", " ")
buff = Replace(buff, " ", " ")
buff = Replace(buff, " ", " ")
buff = Replace(buff, " ", " ")

b = Split(buff, vbNewLine)
GetArrayData = b

End Function

Private Function FindItemInArray(b() As String, sItem As String) As String

Dim cnt As Long

For cnt = LBound(b()) To UBound(b())
Print b(cnt)
If InStr(b(cnt), sItem) Then

FindItemInArray = cnt
Exit Function
End If

Next
'since arrays are 0=based, must use a
'negative number to indicate failure
FindItemInArray = -1

End Function

Private Sub FixSplitHeaderCaptions(x As String, Optional b)

'cheezy hack department - replace the
'space in the caption with a char not
'used in the string
x = Replace(x, "User Time", "User%Time")
x = Replace(x, "Kernel Time", "Kernel%Time")
x = Replace(x, "Elapsed Time", "Elapsed%Time")

End Sub


--

Randy Birch
MVP Visual Basic
http://vbnet.mvps.org/
Please respond only to the newsgroups so all can benefit.


"Matt Williamson" <ih8...@spamsux.org> wrote in message

news:#BQrki$9DHA...@TK2MSFTNGP12.phx.gbl...
: I'm having trouble figuring out how to Parse a text file into a listview

:
:


Randy Birch

unread,
Feb 20, 2004, 6:22:30 PM2/20/04
to
I like Jim's solution better than my 'Fix' hack ... the Fix routine can be
deleted and the call replaced with this:

buff(firstindex) = Replace(buff(firstindex), " Time", "%Time")

Jim Edgar

unread,
Feb 20, 2004, 6:31:56 PM2/20/04
to

"Jim Edgar" <djedga...@cox.net> wrote in message
news:OO99JJA%23DHA...@TK2MSFTNGP10.phx.gbl...

Looking at your code again it appears that you may have multiple spaces
between column headers. If you do then you can add the following code
to get rid of extra spaces:

' Replace double-spaces with a single space
While InStr(strTmp, " ") > 0
strTmp = Replace(strTmp, " ", " ")
Wend
' Trim leading and trailing spaces
strTmp = Trim(strTmp)

Jim Edgar

Bob O`Bob

unread,
Feb 21, 2004, 2:32:50 AM2/21/04
to
Randy Birch wrote:

> buff = Replace(buff, " ", " ")
> buff = Replace(buff, " ", " ")
> buff = Replace(buff, " ", " ")
> buff = Replace(buff, " ", " ")
> buff = Replace(buff, " ", " ")
> buff = Replace(buff, " ", " ")
> buff = Replace(buff, " ", " ")

A couple of years back, I got interested in this sort of replacement expression
stuff, and did some actual research into trying to make it more efficient.
As you might guess, there are more efficient patterns than simplistic ones
like the above.

What you've got there I would refer to, in my own LIFO notation, as
(2, 3, 4, 5, 6, 7, 8) and that's effective to reduce-to-one any number
of target characters up to 11,366 in seven passes. Not bad.

But if, for example, you'd modify it to (2, 2, 4, 7, 22, 232),
it would successfully reduce up to 53,590 while making one pass fewer.
Actually, that's (2, 2|3, 3|4, 6|7, 21|22, 231|232) in my notation,
since the indicated alternatives don't make any difference in the result.

And if you like seven passes, then (2, 2, 5, 5, 16, 120, 7259) is good
for more than half a million (I ran out of patience testing it).
Of course you'd probably want to avoid trying to put thousands or even
hundreds of spaces into a literal string in your code,
so it might look something like this:

buff = Replace(buff, Space(7259), " ")
buff = Replace(buff, Space(120), " ")


buff = Replace(buff, " ", " ")
buff = Replace(buff, " ", " ")
buff = Replace(buff, " ", " ")
buff = Replace(buff, " ", " ")
buff = Replace(buff, " ", " ")

I don't know if anyone else enjoys "puzzles" like finding the most effective
combinations of how many spaces to replace, but I did. Maybe one day I'll
pick it up again and come up with a more efficient way to test than just
a brute force loop.


Bob
--
looking for work again <http://obob.com/bob/resume/>

Larry Serflaten

unread,
Feb 21, 2004, 7:05:30 AM2/21/04
to
"Bob O`Bob" <filt...@yahoogroups.com> wrote

>
> A couple of years back, I got interested in this sort of replacement expression
> stuff, and did some actual research into trying to make it more efficient.
> As you might guess, there are more efficient patterns than simplistic ones
> like the above.
<...>

> I don't know if anyone else enjoys "puzzles" like finding the most effective
> combinations of how many spaces to replace, but I did. Maybe one day I'll
> pick it up again and come up with a more efficient way to test than just
> a brute force loop.

I would be interested in hearing the logic you used to arrive at those values.
In my timed tests, I also found using larger values helps and have offered
something similar to:

count = 1024
Do While count > 1
test = Space$(count)
Do While InStr(data, test)
data = Replace(data, test, " ")
Loop
count = count \ 4
Loop


Your combination of 2, 2, 4, 7, 22, 232 is completely unintuitive, so
I wonder if you arrived at that mathemetically, or by trial and error?

LFS


Randy Birch

unread,
Feb 21, 2004, 9:47:25 AM2/21/04
to
Yes, this was just one means to the end, and not the most elegant. And I
can see where coding such as to reduce the spaces to values that are
multiples of other numbers would introduce some efficiency.

--

Randy Birch
MVP Visual Basic
http://vbnet.mvps.org/
Please respond only to the newsgroups so all can benefit.


"Bob O`Bob" <filt...@yahoogroups.com> wrote in message
news:403709...@yahoogroups.com...

Bob O`Bob

unread,
Feb 21, 2004, 11:32:24 AM2/21/04
to
Larry Serflaten wrote:

> Your combination of 2, 2, 4, 7, 22, 232 is completely unintuitive, so
> I wonder if you arrived at that mathemetically, or by trial and error?

The latter.
In fact, I spent a lot of my "fun" time back then
puzzling over just what kind of algorithm
could be written to seek them.

Larry Serflaten

unread,
Feb 21, 2004, 1:25:00 PM2/21/04
to
"Bob O`Bob" <filt...@yahoogroups.com> wrote

> > I wonder if you arrived at that mathemetically, or by trial and error?


>
> The latter.
> In fact, I spent a lot of my "fun" time back then
> puzzling over just what kind of algorithm
> could be written to seek them.


A quick look provided this....

Private Sub Form_Load()
Dim units As New Collection
Dim i, r, vlu, s

For i = 1 To 99999

r = i
For Each vlu In units
s = 0
Do While (r > 1) And (r >= vlu)
r = r - vlu ' Spaces removed
s = s + 1 ' Added back by Replace
Loop
r = r + s
Next

If r > 1 Then ' Save for next value
Debug.Print i
If units.Count Then
units.Add i, , 1
Else
units.Add i
End If
End If
Next

End Sub


But I see you were able to get more for less :-)
That might be fun for a little challenge one day....

LFS


Bob O`Bob

unread,
Feb 21, 2004, 4:04:42 PM2/21/04
to
Larry Serflaten wrote:

> But I see you were able to get more for less :-)
> That might be fun for a little challenge one day....

It might.
By the way, code <> algorithm.

I can't make heads or tails of the code you posted, and I very much doubt
more than a few others will even try. What I was looking for would be more like
a *verbal* description of some method to derive sets of reduction factors.

Joe "Nuke Me Xemu" Foster

unread,
Feb 21, 2004, 6:21:56 PM2/21/04
to
"Bob O`Bob" <filt...@yahoogroups.com> wrote in message <news:403709...@yahoogroups.com>...

> I don't know if anyone else enjoys "puzzles" like finding the most effective
> combinations of how many spaces to replace, but I did. Maybe one day I'll
> pick it up again and come up with a more efficient way to test than just
> a brute force loop.

That seems an awful lot like the quest for the perfect shell-sort
increment sequence.

--
Joe Foster <mailto:jlfoster%40znet.com> Sacrament R2-45 <http://www.xenu.net/>
WARNING: I cannot be held responsible for the above They're coming to
because my cats have apparently learned to type. take me away, ha ha!


Bob O`Bob

unread,
Feb 21, 2004, 8:07:17 PM2/21/04
to
Joe "Nuke Me Xemu" Foster wrote:
>
> "Bob O`Bob" <filt...@yahoogroups.com> wrote in message <news:403709...@yahoogroups.com>...
>
> > I don't know if anyone else enjoys "puzzles" like finding the most effective
> > combinations of how many spaces to replace, but I did. Maybe one day I'll
> > pick it up again and come up with a more efficient way to test than just
> > a brute force loop.
>
> That seems an awful lot like the quest for the perfect shell-sort
> increment sequence.

Yep. About like that.
But you know ... some o' them lilys just look better gilt.

Larry Serflaten

unread,
Feb 22, 2004, 1:11:05 AM2/22/04
to
"Bob O`Bob" <filt...@yahoogroups.com> wrote
> By the way, code <> algorithm.
>
> I can't make heads or tails of the code you posted,

It runs through the number of spaces to test (1 to 99999)
using a collection to hold the sequence of values it uses to
reduce X number of spaces to just 1. It mimics the Replace
function by removing some number of spaces:

r = r - vlu ' Spaces removed

and replacing them with 1 space.

s = s + 1 ' Added back by Replace

Basically it tests each number and if it hasn't got what it needs
to reduce the value to 1, then it stores that number as the
next number in the sequence. As you indicated, the sequence
2, 2, 4, 7, 22, 232 is good up to 53,590. 53,591 can't be gotten
by that group, so the algorithm I used would add 53591 as the
next number in the sequence. That's good up to 107,180 where
my algorithm would find it can't get to 107,181 so it would add
that as the next value in the sequence.

As I stated, your was more compact than gets generated by
my algorithm: 2, 3, 5, 11, 29, 83, 245, 721, etc...
So no doubt it could stand improvement. Perhaps I should look
for the largest factor of the value that is unreachable, instead of
the using value itself.....

Using that largest factor method I get:

2, 3, 3, 5, 13, 121, 9841

Which seemed to work well for over 3 million before I decided to
stop testing. Thats seems to have some promise to it ;-)

LFS


LFS

Larry Serflaten

unread,
Feb 22, 2004, 2:14:56 AM2/22/04
to
"Larry Serflaten" <serf...@usinternet.com> wrote

> Using that largest factor method I get:
>
> 2, 3, 3, 5, 13, 121, 9841
>
> Which seemed to work well for over 3 million before I decided to
> stop testing. Thats seems to have some promise to it ;-)


FWIW, I optimized the algorithm for speed to test it even further and
found that sequence was good up to 20 million, where I stopped again.
It took about 5 minutes on my 650 Mhz processor, if you have a
multi gigahertz machine you might let it go farther. Here is the code:

Have fun!
LFS


Private Sub Form_Load()
Dim seq As Collection
Dim vlu As Variant
Dim i&, spaces&, rpl&, fac As Long

' The sequence of numbers
Set seq = New Collection

For i = 1 To 20000000

' Number of spaces to try to reduce to 1
spaces = i

For Each vlu In seq

' calc how many full occurances
rpl = (spaces \ vlu)

' Remove full occurances
spaces = spaces - (rpl * vlu)

' Add back 1 space for each full occurance removed
spaces = spaces + rpl

Next


' Check to see if it was reduced to 1
If spaces <> 1 Then

If seq.Count = 0 Then

' First value is just added (it will be 2)
seq.Add i
Debug.Print i

Else

' Find the largest factor
fac = LF(i)

' Insert in sorted order (DESC)
For vlu = 1 To seq.Count
If fac > seq(vlu) Then
seq.Add fac, , vlu
Debug.Print fac
Exit For
End If
Next

End If ' seq.Count

End If ' spaces <> 1

' A friendly DoEvents...
If (i Mod 50000) = 0 Then DoEvents

Next

' List sequence
Debug.Print
For Each vlu In seq
Debug.Print vlu
Next


End Sub


Private Function LF(ByVal Num As Long)
Dim i As Long
' Returns largest factor of Num

Debug.Print " ^ Was good up to:", Num - 1
DoEvents

For i = Num \ 2 To 2 Step -1
If (Num Mod i) = 0 Then
LF = i


Exit Function
End If
Next

LF = Num

End Function

Larry Serflaten

unread,
Feb 22, 2004, 8:41:41 AM2/22/04
to
"Larry Serflaten" <serf...@usinternet.com> wrote

>
> 2, 3, 3, 5, 13, 121, 9841

The next number in the sequence is 64570081.
Who can list the one following that? (Be prepared to
change data types. With that last number added,
the sequence covers all combinations up to at
least 2GB! ;-)

LFS


Larry Serflaten

unread,
Feb 22, 2004, 9:38:28 AM2/22/04
to
"Joe "Nuke Me Xemu" Foster" <j...@bftsi0.UUCP> wrote

> > I don't know if anyone else enjoys "puzzles" like finding the most effective
> > combinations of how many spaces to replace, but I did.
>

> That seems an awful lot like the quest for the perfect shell-sort
> increment sequence.

I have found a combination of 8 numbers that solves this problem up
to 2 GB. (2, 3, 3, 5, 13, 121, 9841, 64570081) Now I need a place to
use it, so, I am going to apply it (in my own special way) to the shell sort
problem.

The shell sort picks a sequence of gaps, and sorts the sub-lists generated
by breaking up an array by that gap amount. It will pick a gap value (G) and
start at position 0 and sort the sub-list where each item is G elements apart.
It then starts over at postion 1, and sorts that sub-list with a gap of G. It
continues to start at 2, 3, 4, ... to G-1, sorting all the sub-lists generated.
It then picks a different value for the gap, and repeats the process. The
trick is to pick an efficient gap value sequence. (The perfect sequence)

The comb sort uses a similar technique, but it only starts at position 0
and uses decreasing gap values until it eventually gets to a gap value of 1
which completes the sort. In 1991, Box and Lacey found reducing the
gap values by dividing them by 1.3 gave the best results. (FWIW)

I am going to try a combo of the two, just to see how it fairs. I will use
decreasing gap values, and apply that to the shell sort, but I will not be
sorting all the sub-lists from 1 to G-1 as the shell sort does. Instead of
picking a gap value, and sorting the sub-lists starting at positions 0, 1, 2,
3, ... all the way to G-1, I will increment the sub-list sorting using the next
lower number in the sequence.

With an intitial gap value of 121 (followed by 13, 5, and 3), I am going to
sort the sub-list starting at position 0 followed by another sub-list sort
that starts at position 13, then 26, then 39, 52, 65, ... etc. until I get to 121.

Then I will use a new gap value of 13 and increment the start positions by 5
(the next number in the sequence) such that gap 13 sorts will start at positions
0, 5, and 10. And finally gap 5 sub-list sorts will be started at positions
0 and 3.

You'll note I did not go all the way down to an increment or gap value of 1.
The list is not quite sorted yet, but, because of the last sorts where the
gap was 5, the values can be out of place by no more than 4 positions.
(I am thinking they can be no more than 3 positions out, but I haven't
proved it) To catch that last little bit, I will use 1 pass of a modified
bubble sort.

I am going to develop this just to build the algorithm, hopefully I'll be
able to talk Howard Kaikow into adding it to his timed trials to see how
it fairs.... :-)

LFS

Bonj

unread,
Feb 22, 2004, 9:49:45 AM2/22/04
to
To the OP: Ignore this fool and his wrong theories.


"Randy Birch" <rgb_rem...@mvps.org> wrote in message
news:eATYZmI%23DHA...@TK2MSFTNGP10.phx.gbl...

Bonj

unread,
Feb 22, 2004, 9:50:29 AM2/22/04
to
That code is an absolute load of shite.

"Randy Birch" <rgb_rem...@mvps.org> wrote in message

news:eUY5weA%23DHA...@TK2MSFTNGP10.phx.gbl...

Bonj

unread,
Feb 22, 2004, 9:50:07 AM2/22/04
to
Irreverent wanker.

"Randy Birch" <rgb_rem...@mvps.org> wrote in message

news:%23J6KqhA%23DHA...@TK2MSFTNGP10.phx.gbl...

Larry Serflaten

unread,
Feb 22, 2004, 12:18:43 PM2/22/04
to
"JasonTik" <Do...@Mail.Me> wrote
> Just curious, How did you find these numbers?
> What algorithm did you use?
> Did you write a program to find them?
> Can I see the source?

Check the rest of this thread, I did post it as a follow-on
to one of my own messages....

LFS


Stefan Berglund

unread,
Feb 22, 2004, 3:12:04 PM2/22/04
to
On Sat, 21 Feb 2004 13:04:42 -0800, Bob O`Bob
<filt...@yahoogroups.com> wrote:
in <4037C7...@yahoogroups.com>

>Larry Serflaten wrote:
>
>> But I see you were able to get more for less :-)
>> That might be fun for a little challenge one day....
>
>It might.
>By the way, code <> algorithm.
>
>I can't make heads or tails of the code you posted, and I very much doubt
>more than a few others will even try. What I was looking for would be more like
>a *verbal* description of some method to derive sets of reduction factors.
>
>
>
> Bob

Bob-

If you're interested check out this thread and in particular the
responses from the mathematicians Steve Kass and Delbert Glass.

<#w1WEr25...@TK2MSFTNGP09.phx.gbl>

Bob O`Bob

unread,
Feb 22, 2004, 4:55:22 PM2/22/04
to
Stefan Berglund wrote:

> If you're interested check out this thread and in particular the
> responses from the mathematicians Steve Kass and Delbert Glass.
>
> <#w1WEr25...@TK2MSFTNGP09.phx.gbl>


Hahahaaaa.
So I'm not the only puzzle nutcase who's looked into it.

Actually, it's possible I helped inspire some of that, since my work in the
realm was done in January 2002 and I asked a *lot* of people what they
thought of it (principally puzzle-solving friends and friends-of-friends)

At first, I just looped several times through a simple
replace(target, space(2), space(1))
then it occurred to me to do something more clever like
for i = 5 to 0 step -1
replace(target, space(max(2,2^i)), space(1)
next
which 'unrolls' to a more straightforward
replace(target, space(32), space(1))
replace(target, space(16), space(1))
replace(target, space(8), space(1))
replace(target, space(4), space(1))
replace(target, space(2), space(1))
replace(target, space(2), space(1))

...but then somehow it occurred to me there might be more efficient choices,
and off I went.

Here's some of my notes, from 08jan02:
====================
best 1 step
3:(2)
best 2 step
5:(2,2)
5:(2,3)
best 3 step
11:(2,2,3)
11:(2,2,4)
11:(2,3,3)
11:(2,3,4)
best 4 step
41:(2,2,3,6)
41:(2,2,3,7)
41:(2,2,4,6)
41:(2,2,4,7)
41:(2,3,3,6)
41:(2,3,3,7)
41:(2,3,4,6)
41:(2,3,4,7)
best? 5 step
461:(2, 2|3, 3|4, 6|7, 21|22)

best? 6 step
53591:(2, 2|3, 3|4, 6|7, 21|22, 231|232)

7 step
> 500000:(2, 2, 5, 5, 16, 120, 7259)
====================

Those numbers on the left represent the first failure of a given set.
I find some of it quite curious, like the myriad ways to get to exactly
40 in four steps, but no four-step can do every possible value up to 41.
I proved that much to myself by brute-force testing all alternatives,
but I never did think up a better way to test.

0 new messages