Seeing next character in an file

G

Grumfish

Is there a way to see the next character of an input file object without
advancing the position in the file?
 
K

Keith Jones

Is there a way to see the next character of an input file object without
advancing the position in the file?


To do this, you can do the following:

fin = file('myfile')

....

char = fin.read(1)
fin.seek(-1,1) # set the file's current position back a character

You can then write your own subclass of file, if you want, with "peek"
functionality:

class flexfile(file):
def __init__(self, fname, mode='r', bufsize=0):
file.__init__(self, fname, mode, bufsize)

def peek(self, cnt):
data = self.read(cnt)
self.seek(cnt * -1, 1)
return data

def peekline(self):
pos = self.tell()
data = self.readline()
self.seek(pos, 0)
return data
 
B

Bengt Richter

To do this, you can do the following:

fin = file('myfile')

...

char = fin.read(1)
fin.seek(-1,1) # set the file's current position back a character
Warning, though: this is very iffy on windows unless you have opened the file
in binary. E.g.,

Look at it in binary: 'Ends in windows EOL here:\r\n'

Cooked: 'Ends in windows EOL here:\n'

Now try to seek back past the apparent \n single character and one more (2)
so we can read the ':' '\n'

Hm. That's a representation of reading the last two characters in cooked mode.
Apparently the seek positioned us to read '\r\n', not a cooked ':\n'

Look at the same in binary: '\r\n'

The last two are the windows EOL. Seeking -2 in cooked mode is not positioning at ':\n'
as we can see in the binary:
':\r\n'

[...]

So if you're going to seek/tell, best to do it in binary, and deal with the platform dependent EOLs.

Regards,
Bengt Richter
 
R

Richie Hindle

[Keith]
def peek(self, cnt):
data = self.read(cnt)
self.seek(cnt * -1, 1)
return data

def peekline(self):
pos = self.tell()
data = self.readline()
self.seek(pos, 0)
return data
[Bengt]
if you're going to seek/tell, best to do it in binary, and deal with the platform dependent EOLs.

seek() works perfectly with text-mode files as long as you only seek to
places given to you by tell(). So if Keith's peek() function had used
tell() and then seek()ed (sought()? :cool: back to that point like his
peekline() does, there would be no problem.
 
R

R.Marquez

Grumfish said:
Is there a way to see the next character of an input file object without
advancing the position in the file?

Here is a little class that I use on a little html parser that I
wrote. You may be able to adjust it for your needs:

class Characters:
def __init__(self, String):
self.Characters=String
self.Char = ""
self.index = 0
self.lenght = len(self.Characters)

def GetNextChar(self):
skipchar = 1
while skipchar ==1:
try:
self.Char = self.Characters[self.index]
except IndexError:
self.Char = None
#print "End of File\n"
return None
self.index += 1
if self.Char != "\n":
skipchar = 0
return self.Char

def CheckNextChar(self):
skipchar = 1
StartChar = self.Char
StartIndex = self.index
while skipchar ==1:
try:
self.Char = self.Characters[self.index]
except IndexError:
self.Char = None
#print "End of File\n"
return None
self.index += 1
if self.Char != "\n":
skipchar = 0
self.index = StartIndex
NextChar = self.Char
self.Char = StartChar
return NextChar
 
R

Richie Hindle

[Richie]
seek() works perfectly with text-mode files as long as you only seek to
places given to you by tell(). So if Keith's peek() function had used
tell() and then seek()ed (sought()? :cool: back to that point like his
peekline() does, there would be no problem.
[Bengt]
Can you cite a C or C++ standard section that guarantees that seek/tell
will work that way in text mode? (I'm not saying there isn't one, but
I couldn't find one quickly ;-)

ANSI C, ISO/IEC 9899:1990, section 7.9.9.2: "For a text stream, either
offset shall be zero, or offset shall be a value returned by an earlier
call to the ftell function on the same stream and whence shall be
SEEK_SET."
 
B

Bengt Richter

[Richie]
seek() works perfectly with text-mode files as long as you only seek to
places given to you by tell(). So if Keith's peek() function had used
tell() and then seek()ed (sought()? :cool: back to that point like his
peekline() does, there would be no problem.
[Bengt]
Can you cite a C or C++ standard section that guarantees that seek/tell
will work that way in text mode? (I'm not saying there isn't one, but
I couldn't find one quickly ;-)

ANSI C, ISO/IEC 9899:1990, section 7.9.9.2: "For a text stream, either
offset shall be zero, or offset shall be a value returned by an earlier
call to the ftell function on the same stream and whence shall be
SEEK_SET."
Thank you. It makes sense that you could retrieve and set an underlying binary position
and decode forward with arbitrary cooking, so long as that cooking either goes character
by character and leaves the binary position to right after what it has used up, or does
the equivalent by proper binary repositioning if it grabs a chunk and doesn't use all of it
for a given cooking portion, so that the next retrieval (tell) will be valid.

I guess I must have been bitten some time in the foggy past, and never recovered trust.
Now I have enough at least to use it, though I will probably still want to write a little
verification into a unit test if I'm in finicky mode. Thanks again ;-)

BTW, is there an ANSI C spec available free on line (or an older, close-enough draft)?

Regards,
Bengt Richter
 
R

Richie Hindle

[Bengt]
BTW, is there an ANSI C spec available free on line
(or an older, close-enough draft)?

Not a complete one that I'm aware of, no, although some pieces exist at
and around http://www.cs.vsb.cz/grygarek/tuox/sources/lib/ansi/Draft_g.txt

I eventually found the seek/tell rule in a book errata at
http://herd.plethora.net/~seebs/c/c_tcr.html then confirmed the standard
and section numbers with the "Normative Changes to ISO/IEC 9899:1990"
document at http://www.lysator.liu.se/c/tc1.html

I can't remember exactly what I googled for to find those documents (and
the query has already fallen off the end of my Google Toolbar's search
history - I think I use Google too much! :cool:
 

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

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,482
Members
44,901
Latest member
Noble71S45

Latest Threads

Top