Re: Write to a certain line of a file [message #78956] |
Thu, 19 January 2012 11:02  |
David Fanning
Messages: 11724 Registered: August 2001
|
Senior Member |
|
|
Michael Galloy writes:
> You are essentially treating the file as a binary file where you have
> more options, but also more responsibility for keeping things straight.
>
> Sure, this would work in the case where the new output has the exact
> same length in bytes as the old output, but if not everything is going
> to get screwed up. You could rewrite the file after the point of
> insertion to fix this, but how much is it worth it to get around writing
> this file?
I was curious how long it would take to re-write a 10000 line ASCII file
after replacing a line in it. Answer: 0.014 seconds!
Here is the code I used.
;----------------------------------------------------------- ----
; Create a random set of strings.
LENGTH=10000
len = Round(Scale_Vector(Randomu(-3L, LENGTH), 10, 60))
file = StrArr(LENGTH)
FOR j=0,N_Elements(len)-1 DO BEGIN
str = Byte(Scale_Vector(RandomU(seed, len[j]), 97, 122))
space = Fix(randomu(seed, len[j]/5 > 1) * len[j] > 2)
str[space] = 32B
file[j] = String(str)
ENDFOR
; Write the random strings to a file.
OpenW, lun, 'test_ascii_file.txt', /Get_Lun
FOR j=0, LENGTH-1 DO PrintF, lun, file[j]
Free_Lun, lun
; Replace line 50 with 'The dog ate my homework!'
start = Systime(1)
lines = File_Lines('test_ascii_file.txt')
OpenR, lun, 'test_ascii_file.txt', /Get_Lun
strings = StrArr(lines)
strings[49] = 'The dog ate my homework!'
Free_Lun, lun
OpenW, lun, 'test_ascii_file_1.txt'
FOR j=0,N_Elements(strings)-1 DO PrintF, lun, strings[j]
Free_Lun, lun
Print, 'Time to rewrite file: ', systime(1) - start
END
;---------------------------------------------------
Cheers,
David
--
David Fanning, Ph.D.
Fanning Software Consulting, Inc.
Coyote's Guide to IDL Programming: http://www.idlcoyote.com/
Sepore ma de ni thui. ("Perhaps thou speakest truth.")
|
|
|
Re: Write to a certain line of a file [message #78957 is a reply to message #78956] |
Thu, 19 January 2012 09:49   |
Michael Galloy
Messages: 1114 Registered: April 2006
|
Senior Member |
|
|
On 1/19/12 9:43 AM, Mark Piper wrote:
> On 1/19/2012 5:18 AM, Brian J. Daniel wrote:
>> I haven't done this, but POINT_LUN may do what you want. You'd need
>> to know the number of bytes per line. You will still have to read the
>> entire line, change the bit you want to change, move the LUN back to
>> the beginning of the line, and rewrite it.
>>
>> OpenR, LUN, filename, /Get_Lun
>> Point_Lun, LUN, line_number * bytes_per_line
>> tmp=''
>> ReadF, LUN, tmp
>> ; change the line as you see fit
>> new_line = tmp + 'changed line!'
>> Point_Lun, LUN, line_number * bytes_per_line
>> PrintF, LUN, new_line
>> Free_Lun, LUN
>>
>> Code is UNTESTED!
>
> To add to Brian's idea, if you have a text file, use SKIP_LUN with the
> LINES keyword set. A crude example:
>
> pro replace_line_ex
> compile_opt idl2
>
> f0 = 'ascii.txt'
> f1 = 'ascii-1.txt'
> file_copy, file_which(f0), f1, /overwrite
>
> nskip = 7
> line = ''
> replacement = 'My dog has fleas.'
>
> openu, u, f1, /get_lun
> skip_lun, u, nskip, /lines
> point_lun, -u, mark
> readf, u, line
> nchars = strlen(line)
> point_lun, u, mark
> printf, u, replacement, format='(a-' + strtrim(nchars,2) + ')'
> free_lun, u
> end
>
> Diff 'ascii.txt' in the example/data directory of the IDL distro with
> 'ascii-1.txt' in your working directory.
You are essentially treating the file as a binary file where you have
more options, but also more responsibility for keeping things straight.
Sure, this would work in the case where the new output has the exact
same length in bytes as the old output, but if not everything is going
to get screwed up. You could rewrite the file after the point of
insertion to fix this, but how much is it worth it to get around writing
this file?
Mike
--
Michael Galloy
www.michaelgalloy.com
Modern IDL, A Guide to Learning IDL: http://modernidl.idldev.com
Research Mathematician
Tech-X Corporation
|
|
|
Re: Write to a certain line of a file [message #78958 is a reply to message #78957] |
Thu, 19 January 2012 08:43   |
Mark Piper
Messages: 198 Registered: December 2009
|
Senior Member |
|
|
On 1/19/2012 5:18 AM, Brian J. Daniel wrote:
> I haven't done this, but POINT_LUN may do what you want. You'd need
> to know the number of bytes per line. You will still have to read the
> entire line, change the bit you want to change, move the LUN back to
> the beginning of the line, and rewrite it.
>
> OpenR, LUN, filename, /Get_Lun
> Point_Lun, LUN, line_number * bytes_per_line
> tmp=''
> ReadF, LUN, tmp
> ; change the line as you see fit
> new_line = tmp + 'changed line!'
> Point_Lun, LUN, line_number * bytes_per_line
> PrintF, LUN, new_line
> Free_Lun, LUN
>
> Code is UNTESTED!
To add to Brian's idea, if you have a text file, use SKIP_LUN with the
LINES keyword set. A crude example:
pro replace_line_ex
compile_opt idl2
f0 = 'ascii.txt'
f1 = 'ascii-1.txt'
file_copy, file_which(f0), f1, /overwrite
nskip = 7
line = ''
replacement = 'My dog has fleas.'
openu, u, f1, /get_lun
skip_lun, u, nskip, /lines
point_lun, -u, mark
readf, u, line
nchars = strlen(line)
point_lun, u, mark
printf, u, replacement, format='(a-' + strtrim(nchars,2) + ')'
free_lun, u
end
Diff 'ascii.txt' in the example/data directory of the IDL distro with
'ascii-1.txt' in your working directory.
mp
|
|
|
Re: Write to a certain line of a file [message #78959 is a reply to message #78958] |
Thu, 19 January 2012 04:18   |
Brian Daniel
Messages: 80 Registered: July 2009
|
Member |
|
|
I haven't done this, but POINT_LUN may do what you want. You'd need
to know the number of bytes per line. You will still have to read the
entire line, change the bit you want to change, move the LUN back to
the beginning of the line, and rewrite it.
OpenR, LUN, filename, /Get_Lun
Point_Lun, LUN, line_number * bytes_per_line
tmp=''
ReadF, LUN, tmp
; change the line as you see fit
new_line = tmp + 'changed line!'
Point_Lun, LUN, line_number * bytes_per_line
PrintF, LUN, new_line
Free_Lun, LUN
Code is UNTESTED!
|
|
|
|
|
|
Re: Write to a certain line of a file [message #78963 is a reply to message #78962] |
Wed, 18 January 2012 12:05   |
natha
Messages: 482 Registered: October 2007
|
Senior Member |
|
|
If the file is an ascii file you can read the file, modify the content
and then rewrite everything.
content=STRARR(FILE_LINES(file))
OPENR, lun, file, /GET_LUN
READU, lun, content
FREE_LUN, lun
;; then u modify the content
content[i]='new content'
;; rewrite everything
OPENW, lun, file, /GET_LUN
PRINTF, lun, content
FRRE_LUN, lun
Cheers,
nara
|
|
|
Re: Write to a certain line of a file [message #79048 is a reply to message #78957] |
Fri, 20 January 2012 08:21  |
Mark Piper
Messages: 198 Registered: December 2009
|
Senior Member |
|
|
On 1/19/2012 10:49 AM, Michael Galloy wrote:
>
> You are essentially treating the file as a binary file where you have
> more options, but also more responsibility for keeping things straight.
>
> Sure, this would work in the case where the new output has the exact
> same length in bytes as the old output, but if not everything is going
> to get screwed up. You could rewrite the file after the point of
> insertion to fix this, but how much is it worth it to get around writing
> this file?
>
>
> Mike
Ah, nuts! Yeah, I understand. I guess it's moot anyway because, as David
has shown, it's trivial to read/replace/rewrite a text file.
mp
|
|
|