9

I want to read in a list of numbers from a file as chars one char at a time to check what that char is, whether it is a digit, a period, a + or -, an e or E, or some other char...and then perform whatever operation I want based on that. How can I do this using the existing code I already have? This is an example that I have tried, but didn't work. I am new to python. Thanks in advance!

    import sys

    def is_float(n):
        state = 0
        src = ""
        ch = n
        if state == 0:
            if ch.isdigit():
                src += ch
                state = 1
                ...

    f = open("file.data", 'r')
    for n in f:
        sys.stdout.write("%12.8e\n" % is_float(n))
Harley Jones
  • 167
  • 6
  • 20
  • 1
    do you really need to _read_ one byte at a time, or merely _process_ one line at a time? Reading one byte at a time will be much slower than reading one line or the whole file at a time. You can still have the option of stepping over the data one character at a time. – Bryan Oakley Sep 01 '14 at 20:05
  • Yes, I need to use the bottom three lines of code to read the file. The part I am unsure about is using that to read it in one char at a time. I need to check each char one at a time in the function is_float. – Harley Jones Sep 02 '14 at 01:32
  • related: http://stackoverflow.com/questions/1035340/reading-binary-file-in-python – jfs Sep 08 '14 at 18:50

3 Answers3

53

Here is a technique to make a one-character-at-a-time file iterator:

from functools import partial

with open("file.data") as f:
    for char in iter(partial(f.read, 1), ''):
        # now do something interesting with the characters
        ...
  • The with-statement opens the file and unconditionally closes it when you're finished.
  • The usual way to read one character is f.read(1).
  • The partial creates a function of zero arguments by always calling f.read with an argument of 1.
  • The two argument form of iter() creates an iterator that loops until you see the empty-string end-of-file marker.
Raymond Hettinger
  • 216,523
  • 63
  • 388
  • 485
2

In fact it's much easier. There is a nice utility in itertools, that's often neglected. ;-)

for character in itertools.chain.from_iterable(open('file.data')):
    process(character)
Veky
  • 2,646
  • 1
  • 21
  • 30
  • Note that this actually reads one line at a time, but merely *processes* character by character. Not necessarily a problem but worth mentioning. – zondo Jul 02 '17 at 11:40
  • You're correct, but no sane method _really_ reads character by character from the magnet. There are at least three layers of buffering involved, maybe more. Adding one more layer doesn't really matter IMO. :-) – Veky Jul 04 '17 at 04:51
1

for x in open() reads lines from a file. Read the entire file in as a block of text, then go through each character of the text:

import sys

def is_float(n):
    state = 0
    src = ""
    ch = n
    if state == 0:
        if ch.isdigit():
            src += ch
            state = 1
            ...

data = open("file.data", 'r').read()
for n in data: # characters
    sys.stdout.write("%12.8e\n" % is_float(n))
johntellsall
  • 14,394
  • 4
  • 46
  • 40
  • Ok, I see. How would I read each character from data then? I would do this inside of the is_float() function, correct? – Harley Jones Sep 02 '14 at 01:34