Python - how to read file with NUL delimited lines?

╄→尐↘猪︶ㄣ 提交于 2019-11-28 09:17:55

If your file is small enough that you can read it all into memory you can use split:

for line in f.read().split('\0'):
    print line

Otherwise you might want to try this recipe from the discussion about this feature request:

def fileLineIter(inputFile,
                 inputNewline="\n",
                 outputNewline=None,
                 readSize=8192):
   """Like the normal file iter but you can set what string indicates newline.

   The newline string can be arbitrarily long; it need not be restricted to a
   single character. You can also set the read size and control whether or not
   the newline string is left on the end of the iterated lines.  Setting
   newline to '\0' is particularly good for use with an input file created with
   something like "os.popen('find -print0')".
   """
   if outputNewline is None: outputNewline = inputNewline
   partialLine = ''
   while True:
       charsJustRead = inputFile.read(readSize)
       if not charsJustRead: break
       partialLine += charsJustRead
       lines = partialLine.split(inputNewline)
       partialLine = lines.pop()
       for line in lines: yield line + outputNewline
   if partialLine: yield partialLine

I also noticed your file has a "csv" extension. There is a CSV module built into Python (import csv). There is an attribute called Dialect.lineterminator however it is currently not implemented in the reader:

Dialect.lineterminator

The string used to terminate lines produced by the writer. It defaults to '\r\n'.

Note The reader is hard-coded to recognise either '\r' or '\n' as end-of-line, and ignores lineterminator. This behavior may change in the future.

I have modified Mark Byers's suggestion so that we could READLINE file with NUL delimited lines in Python. This approach reads a potentially large file line by line and should be more memory efficient. Here is the Python code (with comments) :

import sys

# Variables for "fileReadLine()"
inputFile = sys.stdin   # The input file. Use "stdin" as an example for receiving data from pipe.
lines = []   # Extracted complete lines (delimited with "inputNewline").
partialLine = ''   # Extracted last non-complete partial line.
inputNewline="\0"   # Newline character(s) in input file.
outputNewline="\n"   # Newline character(s) in output lines.
readSize=8192   # Size of read buffer.
# End - Variables for "fileReadLine()"

# This function reads NUL delimited lines sequentially and is memory efficient.
def fileReadLine():
   """Like the normal file readline but you can set what string indicates newline.

   The newline string can be arbitrarily long; it need not be restricted to a
   single character. You can also set the read size and control whether or not
   the newline string is left on the end of the read lines.  Setting
   newline to '\0' is particularly good for use with an input file created with
   something like "os.popen('find -print0')".
   """
   # Declare that we want to use these related global variables.
   global inputFile, partialLine, lines, inputNewline, outputNewline, readSize
   if lines: 
       # If there is already extracted complete lines, pop 1st llne from lines and return that line + outputNewline.
       line = lines.pop(0)
       return line + outputNewline
   # If there is NO already extracted complete lines, try to read more from input file.
   while True:   # Here "lines" must be an empty list.
       charsJustRead = inputFile.read(readSize)   # The read buffer size, "readSize", could be changed as you like.
       if not charsJustRead:   
          # Have reached EOF. 
          if partialLine:
             # If partialLine is not empty here, treat it as a complete line and copy and return it.
             popedPartialLine = partialLine
             partialLine = ""   # partialLine is now copied for return, reset it to an empty string to indicate that there is no more partialLine to return in later "fileReadLine" attempt.
             return popedPartialLine   # This should be the last line of input file.
          else:
             # If reached EOF and partialLine is empty, then all the lines in input file must have been read. Return None to indicate this.
             return None
       partialLine += charsJustRead   # If read buffer is not empty, add it to partialLine.
       lines = partialLine.split(inputNewline)   # Split partialLine to get some complete lines.
       partialLine = lines.pop()   # The last item of lines may not be a complete line, move it to partialLine.
       if not lines:
          # Empty "lines" means that we must NOT have finished read any complete line. So continue.
          continue
       else:
          # We must have finished read at least 1 complete llne. So pop 1st llne from lines and return that line + outputNewline (exit while loop).
          line = lines.pop(0)
          return line + outputNewline


# As an example, read NUL delimited lines from "stdin" and print them out (using "\n" to delimit output lines).
while True:
    line = fileReadLine()
    if line is None: break
    sys.stdout.write(line)   # "write" does not include "\n".
    sys.stdout.flush() 

Hope it helps.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!