Need help with writefile line ranges within extensive file

A

Alpha Blue

Hi Everyone,

I have the following file that I started to work on:

class EuiiiReader

def initialize(writefile,filename)
@writefile = writefile
@filename = filename
@provnum = /^\d{1,4}\=\{/
end

def readfile
File.open(@filename, "r") do |infile|
@linenumarray = []
while (line = infile.gets)
if (line =~ @provnum)
linenum = $.
@linenumarray += [linenum]
end
end
end
end

def writefile
open(@writefile, "w") { |f|
f.puts "Verifying File..."
f.puts "================="
File.open(@filename, "r") do |infile|
while (line = infile.gets)
# Need help here
# @linenumarray contains all of the starting file lines
# I need to output the lines + 8 lines after each one listed in
the array to an output file
f.puts "Something to do here"
end
end
}
end
end

k = EuiiiReader.new('compare.txt', 'Italy_alternate.eu3')
k.readfile
k.writefile

=============

Here is my issue. I'm still trying to get better with utilizing Ruby in
various situations. Since I read a lot of files and love file readers,
I thought I would concentrate on this.

I have a simple saved game file from Europa Universallis III which
contains approximately 850,000 lines. The saved game file is currently
corrupt and I believe I know the issue and need to have a more permanent
fix in place for if it happens again.

The file will look something similar in certain segments:

....

1={
flags={
}
variables={
}
name="Stockholm"
owner="SCA"
controller="SCA"
core="SWE"
core="SCA"
culture=swedish

....

My class above starts with reading the entire file and locating province
number lines for 1={, 2={, etc. etc. to say 1894={. When it finds these
lines, it stores the line numbers into an array called @linenumarray.
This is done in the readfile method.

In the writefile method, I need to output to file the line and the next
8 lines after it for every line number stored in the array. So, the
file would be written to:

Verifying File...
=================
1={
flags={
}
variables={
}
name="Stockholm"
owner="SCA"
controller="SCA"
core="SWE"
2={
flags={
}
variables={
}
name="Stockholm"
owner="SCA"
controller="SCA"
core="SWE"
etc....

My problem is I don't know how to pull the line number from the array
and attach another 8 lines to it. The commented section in the
writefile method is where the placement should occur.

Again, as this is a learning process for me, whatever best practices
should be used instead of what I've written would also be greatly
appreciated. I want to make sure I simplify and expand upon my
knowledge and not do things incorrectly. As ruby is a wonderful
language with many ways of achieving an end result, I might be taking a
more sloppy approach and for that I apologize.

Any help would be greatly appreciated.

Thanks,
 
J

Jesús Gabriel y Galán

Hi Everyone,

I have the following file that I started to work on:

class EuiiiReader

=A0def initialize(writefile,filename)
=A0 =A0@writefile =3D writefile
=A0 =A0@filename =3D filename
=A0 =A0@provnum =3D /^\d{1,4}\=3D\{/
=A0end

=A0def readfile
=A0 =A0File.open(@filename, "r") do |infile|
=A0 =A0 =A0@linenumarray =3D []
=A0 =A0 =A0while (line =3D infile.gets)
=A0 =A0 =A0 =A0if (line =3D~ @provnum)
=A0 =A0 =A0 =A0 =A0linenum =3D $.
=A0 =A0 =A0 =A0 =A0@linenumarray +=3D [linenum]
=A0 =A0 =A0 =A0end
=A0 =A0 =A0end
=A0 =A0end
=A0end

=A0def writefile
=A0 =A0open(@writefile, "w") { |f|
=A0 =A0 =A0f.puts "Verifying File..."
=A0 =A0 =A0f.puts "=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D"
=A0 =A0 =A0File.open(@filename, "r") do |infile|
=A0 =A0 =A0 =A0while (line =3D infile.gets)
=A0 =A0 =A0 =A0# Need help here
=A0 =A0 =A0 =A0# @linenumarray contains all of the starting file lines
=A0 =A0 =A0 =A0# I need to output the lines + 8 lines after each one list= ed in
the array to an output file
=A0 =A0 =A0 =A0f.puts "Something to do here"
=A0 =A0 =A0 =A0end
=A0 =A0 =A0end
=A0 =A0}
=A0end
end

k =3D EuiiiReader.new('compare.txt', 'Italy_alternate.eu3')
k.readfile
k.writefile

=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D

Here is my issue. =A0I'm still trying to get better with utilizing Ruby i= n
various situations. =A0Since I read a lot of files and love file readers,
I thought I would concentrate on this.

I have a simple saved game file from Europa Universallis III which
contains approximately 850,000 lines. =A0The saved game file is currently
corrupt and I believe I know the issue and need to have a more permanent
fix in place for if it happens again.

The file will look something similar in certain segments:

....

1=3D{
=A0 =A0flags=3D{
=A0 =A0}
=A0 =A0variables=3D{
=A0 =A0}
=A0 =A0name=3D"Stockholm"
=A0 =A0owner=3D"SCA"
=A0 =A0controller=3D"SCA"
=A0 =A0core=3D"SWE"
=A0 =A0core=3D"SCA"
=A0 =A0culture=3Dswedish

....

My class above starts with reading the entire file and locating province
number lines for 1=3D{, 2=3D{, etc. etc. to say 1894=3D{. =A0When it find= s these
lines, it stores the line numbers into an array called @linenumarray.
This is done in the readfile method.

In the writefile method, I need to output to file the line and the next
8 lines after it for every line number stored in the array. =A0So, the
file would be written to:

Verifying File...
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
1=3D{
=A0 =A0flags=3D{
=A0 =A0}
=A0 =A0variables=3D{
=A0 =A0}
=A0 =A0name=3D"Stockholm"
=A0 =A0owner=3D"SCA"
=A0 =A0controller=3D"SCA"
=A0 =A0core=3D"SWE"
2=3D{
=A0 =A0flags=3D{
=A0 =A0}
=A0 =A0variables=3D{
=A0 =A0}
=A0 =A0name=3D"Stockholm"
=A0 =A0owner=3D"SCA"
=A0 =A0controller=3D"SCA"
=A0 =A0core=3D"SWE"
etc....

My problem is I don't know how to pull the line number from the array
and attach another 8 lines to it. =A0The commented section in the
writefile method is where the placement should occur.

Again, as this is a learning process for me, whatever best practices
should be used instead of what I've written would also be greatly
appreciated. =A0I want to make sure I simplify and expand upon my
knowledge and not do things incorrectly. =A0As ruby is a wonderful
language with many ways of achieving an end result, I might be taking a
more sloppy approach and for that I apologize.

Any help would be greatly appreciated.

Thanks,

I don't know if you need the line numbers for anything else, or if you
actually need to read the file and calculate things and then write as
a separate method, but if that's not the case you can do this in a
single pass through the infile:

irb(main):033:0> File.open("resulteuiii.txt", "w") do |f|
irb(main):034:1* File.open("dataeuiii.txt") do |infile|
irb(main):035:2* while (line =3D infile.gets)
irb(main):036:3> if line =3D~ /^\d{1,4}\=3D\{/
irb(main):037:4> f.puts line
irb(main):038:4> 8.times {f.puts infile.gets}
irb(main):039:4> end
irb(main):040:3> end
irb(main):041:2> end


Hope this helps,

Jesus.
 
A

Alpha Blue

Thanks mate - I appreciate the short fix.

I ended up having to do a lot more with the file and change it so I can
spot issues in certain areas. So, I've rebuilt and adapted it as such:

class EuiiiReader

def initialize(writefile,filename)
@writefile = writefile
@filename = filename
@provnum = /^\d{1,4}\=\{/
@owner = /owner\=/
@controller = /controller\=/
end

def readfile
File.open(@filename, "r") do |infile|
@linenumarray = []
while (line = infile.gets)
if (line =~ @provnum)
linenum = $.
@linenumarray += [linenum]
end
end
end
end

def printmode(arg,match)
if arg =~ match
return true
end
end

def writefile
open(@writefile, "w") { |f|
f.puts "Verifying File..."
f.puts "================="
g = File.open(@filename, "r")
a = g.readlines
@linenumarray.each do |segment|
badowner = 0
badcontroller = 0
f.puts "Line number #{segment} and #{a[segment - 1]}"
if a[segment+5] =~ @owner || a[segment+6] =~ @owner ||
a[segment+7] =~ @owner
f.puts printmode(a[segment+5],@owner) ? a[segment+5] : '' if
a[segment+5] =~ @owner
f.puts printmode(a[segment+6],@owner) ? a[segment+6] : '' if
a[segment+6] =~ @owner
f.puts printmode(a[segment+7],@owner) ? a[segment+7] : '' if
a[segment+7] =~ @owner
else
badowner = 1
end
if a[segment+6] =~ @controller || a[segment+7] =~ @controller ||
a[segment+8] =~ @controller
f.puts printmode(a[segment+6],@controller) ? a[segment+6] : ''
if a[segment+6] =~ @controller
f.puts printmode(a[segment+7],@controller) ? a[segment+7] : ''
if a[segment+7] =~ @controller
f.puts printmode(a[segment+8],@controller) ? a[segment+8] : ''
if a[segment+8] =~ @controller
else
badcontroller = 1
end
if (badowner + badcontroller) == 1
f.puts 'FOUND a mismatch for owner/controller'
if badowner == 1
f.puts 'Owner not found'
else
f.puts 'Controller not found'
end
elsif (badowner + badcontroller) == 2
f.puts 'No Owners or Controllers for Province'
else
#
end
end
}
end
end

k = EuiiiReader.new('compare.txt', 'Italy_alternate.eu3')
k.readfile
k.writefile
 
J

Jesús Gabriel y Galán

Thanks mate - I appreciate the short fix.

I ended up having to do a lot more with the file and change it so I can
spot issues in certain areas. =A0So, I've rebuilt and adapted it as such:

=A0 =A0 =A0g =3D File.open(@filename, "r")
=A0 =A0 =A0a =3D g.readlines

Here you are not closing the file.

Use a =3D File.readlines(@filename)

instead.

Jesus.
 
A

Alpha Blue

Jesús Gabriel y Galán said:
Here you are not closing the file.

Use a = File.readlines(@filename)

instead.

Jesus.

Thanks mate - appreciate it. I'm cleaning it up now.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,037
Messages
2,570,371
Members
47,015
Latest member
vorix28193

Latest Threads

Top