Python의 파일에서 한 번에 한 문자를 읽는 방법은 무엇입니까?


답변:


89
with open(filename) as f:
  while True:
    c = f.read(1)
    if not c:
      print "End of file"
      break
    print "Read a character:", c

41
이것은 한 번에 한 바이트를 읽는 것이므로 ASCII가 아닌 인코딩에서는 실패하지 않습니까?
David Chouinard 2013 년

3
질문과 답변은 혼란스러운 문자와 바이트 개념입니다. 파일이 Ascii 및 기타 여러 문자 인코딩과 같은 문자 당 단일 바이트 인 경우 예, 단일 바이트 크기의 청크를 읽어 단일 문자를 읽습니다. 그렇지 않으면 인코딩에 문자 당 단일 바이트 이상이 필요한 경우 다음과 같습니다. 단일 문자가 아닌 단일 바이트를 읽는 것입니다.
Basel Shishani 2013 년

2
맞습니다. 따라서 나는 자주 result = open(filename).read()읽고 한 result글자 씩 읽습니다 .
Shiva

3
David Chouinard의 질문에 :이 스 니펫은 UTF-8 인코딩의 파일을 사용하여 Python 3에서 올바르게 작동합니다. 예를 들어 Windows-1250 인코딩 파일이있는 경우 첫 번째 줄을 다음으로 변경하십시오. with open(filename, encoding='Windows-1250') as f:
SergO

1
그리고 SergO에 추가하기 위해 open(filename, "r")vs open(filename, "rb")는 반복 횟수가 다를 수 있습니다 (적어도 Python 3에 대해 이야기). "r"모드 c는 적절한 특수 문자에 맞으면 여러 바이트를 읽을 수 있습니다.
dcc310 2017

40

먼저 파일을 엽니 다.

with open("filename") as fileobj:
    for line in fileobj:  
       for ch in line: 
           print ch

동의합니다, 이것은 그것에 대해 더 파이썬적인 방법으로 보입니다. 비 ASCII 인코딩도 처리하지 않습니까?
Ron7 nov.

16
파일을 한 번에 한 문자 씩 읽을 수있는 한 가지 이유는 파일이 너무 커서 메모리에 맞지 않기 때문입니다. 그러나 위의 대답은 각 줄이 메모리에 맞을 수 있다고 가정합니다.
CS

Python 3과 일치하도록 수정했습니다.

16

나는 받아 들여진 대답을 좋아한다 : 그것은 간단하고 일을 끝낼 것이다. 또한 대체 구현을 제공하고 싶습니다.

def chunks(filename, buffer_size=4096):
    """Reads `filename` in chunks of `buffer_size` bytes and yields each chunk
    until no more characters can be read; the last chunk will most likely have
    less than `buffer_size` bytes.

    :param str filename: Path to the file
    :param int buffer_size: Buffer size, in bytes (default is 4096)
    :return: Yields chunks of `buffer_size` size until exhausting the file
    :rtype: str

    """
    with open(filename, "rb") as fp:
        chunk = fp.read(buffer_size)
        while chunk:
            yield chunk
            chunk = fp.read(buffer_size)

def chars(filename, buffersize=4096):
    """Yields the contents of file `filename` character-by-character. Warning:
    will only work for encodings where one character is encoded as one byte.

    :param str filename: Path to the file
    :param int buffer_size: Buffer size for the underlying chunks,
    in bytes (default is 4096)
    :return: Yields the contents of `filename` character-by-character.
    :rtype: char

    """
    for chunk in chunks(filename, buffersize):
        for char in chunk:
            yield char

def main(buffersize, filenames):
    """Reads several files character by character and redirects their contents
    to `/dev/null`.

    """
    for filename in filenames:
        with open("/dev/null", "wb") as fp:
            for char in chars(filename, buffersize):
                fp.write(char)

if __name__ == "__main__":
    # Try reading several files varying the buffer size
    import sys
    buffersize = int(sys.argv[1])
    filenames  = sys.argv[2:]
    sys.exit(main(buffersize, filenames))

내가 제안하는 코드는 본질적으로 받아 들인 대답과 동일한 아이디어입니다. 파일에서 주어진 바이트 수를 읽습니다. 차이점은 먼저 좋은 데이터 청크를 읽은 다음 (4006은 X86의 좋은 기본값이지만 1024 또는 8192, 페이지 크기의 배수를 시도 할 수 있음) 해당 청크에있는 문자를 산출한다는 것입니다. 하나씩.

내가 제시하는 코드는 더 큰 파일의 경우 더 빠를 수 있습니다. 예를 들어, 톨스토이가 쓴 전쟁과 평화의 전체 텍스트를 보자 . 다음은 내 타이밍 결과입니다 (OS X 10.7.4를 사용하는 Mac Book Pro; so.py는 내가 붙여 넣은 코드에 지정한 이름입니다).

$ time python so.py 1 2600.txt.utf-8
python so.py 1 2600.txt.utf-8  3.79s user 0.01s system 99% cpu 3.808 total
$ time python so.py 4096 2600.txt.utf-8
python so.py 4096 2600.txt.utf-8  1.31s user 0.01s system 99% cpu 1.318 total

이제 : 버퍼 크기를 4096보편적 인 진실로 받아들이지 마십시오 . 다른 크기 (버퍼 크기 (바이트) 대 벽 시간 (초))에 대해 얻은 결과를보십시오.

   2 2.726 
   4 1.948 
   8 1.693 
  16 1.534 
  32 1.525 
  64 1.398 
 128 1.432 
 256 1.377 
 512 1.347 
1024 1.442 
2048 1.316 
4096 1.318 

보시다시피, 당신은 더 일찍 이득을 볼 수 있습니다 (그리고 제 타이밍은 매우 정확하지 않을 것입니다); 버퍼 크기는 성능과 메모리 간의 균형입니다. 기본값 4096은 합리적인 선택이지만 항상 그렇듯이 먼저 측정하십시오.


9

Python 자체가 대화 형 모드에서이를 지원할 수 있습니다.

>>> help(file.read)
Help on method_descriptor:

read(...)
    read([size]) -> read at most size bytes, returned as a string.

    If the size argument is negative or omitted, read until EOF is reached.
    Notice that when in non-blocking mode, less data than what was requested
    may be returned, even if no size parameter was given.

6
나는 그 감정에 동의하지만 아마도 이것이 OP에 대한 의견으로 더 적합할까요?
Mike Boers 2010-06-07

2
그럴 수도 있지만 그 모든 텍스트가 댓글에서 지저분하게 보일 것이라고 생각합니다.
Mattias Nilsson

8

다만:

myfile = open(filename)
onecaracter = myfile.read(1)



2

이것은 또한 작동합니다.

with open("filename") as fileObj:
    for line in fileObj:  
        for ch in line:
            print(ch)

파일의 모든 행과 모든 행의 모든 ​​문자를 통과합니다.



0
f = open('hi.txt', 'w')
f.write('0123456789abcdef')
f.close()
f = open('hej.txt', 'r')
f.seek(12)
print f.read(1) # This will read just "c"

3
Stackoverflow에 오신 것을 환영합니다! 자세히 설명해야합니다. 이것이 왜 대답입니까?
davidkonrad

0

보충을 위해 vvv 매우 큰 줄이 포함 된 파일을 읽고 메모리를 손상시킬 수있는 경우 버퍼로 읽은 다음 각 문자를 산출하는 것을 고려할 수 있습니다.

def read_char(inputfile, buffersize=10240):
    with open(inputfile, 'r') as f:
        while True:
            buf = f.read(buffersize)
            if not buf:
                break
            for char in buf:
                yield char
        yield '' #handle the scene that the file is empty

if __name__ == "__main__":
    for word in read_char('./very_large_file.txt'):
        process(char)

0
#reading out the file at once in a list and then printing one-by-one
f=open('file.txt')
for i in list(f.read()):
    print(i)

이것은 저자의 질문에 답할 수 있지만 설명하는 단어와 문서 링크가 부족합니다. 원시 코드 조각은 주변에 일부 문구가 없으면 그다지 도움이되지 않습니다. 좋은 답변을 작성하는 방법이 매우 도움 이 될 수도 있습니다. 답변을 수정하십시오.
hellow

목록에 출연진이 필요하지 않습니다.
user240515

0
os.system("stty -icanon -echo")
while True:
    raw_c = sys.stdin.buffer.peek()
    c = sys.stdin.read(1)
    print(f"Char: {c}")
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.