【问题标题】:Python append multiple files in given order to one big filePython按给定顺序将多个文件附加到一个大文件中
【发布时间】:2011-07-27 11:05:55
【问题描述】:

我有多达 8 个单独的 Python 进程在共享文件夹中创建临时文件。然后我希望控制过程以特定顺序将所有临时文件附加到一个大文件中。在与操作系统无关的 shell 级别上执行此操作的最快方法是什么?

【问题讨论】:

标签: python file append


【解决方案1】:

只使用简单的文件 IO:

# tempfiles is a list of file handles to your temp files. Order them however you like
f = open("bigfile.txt", "w")
for tempfile in tempfiles:
    f.write(tempfile.read())

这与操作系统无关。它也相当简单,性能应该和使用其他任何东西一样好。

【讨论】:

  • 这只有在每个单独的文件都小到可以读入内存时才有效。如果您可以并行读取和写入(例如,不同的磁盘或架构允许这样),那么性能也会更差,因为您将在开始任何操作之前等待文件被读取。使用 shutil.copyfileobj 可能会更好
  • 或许应该使用二进制 I/O。
【解决方案2】:

不知道任何用于将一个文件附加到另一个文件的 shell 级命令。但是在“python 级别”附加非常容易,我猜 python 开发人员认为没有必要将它添加到库中。

解决方案取决于您要附加的临时文件的大小和结构。如果它们都足够小以至于您不介意将它们中的每一个读入内存,那么 Rafe Kettler 的答案(从他的答案中复制并在下面重复)用最少的代码完成了这项工作。

# tempfiles is an ordered list of temp files (open for reading)
f = open("bigfile.txt", "w")
for tempfile in tempfiles:
    f.write(tempfile.read())

如果无法将文件完全读入内存或者不是一个合适的解决方案,您将需要遍历每个文件并分段读取它们。如果您的临时文件包含可以单独读入内存的换行符终止的行,您可能会这样做

# tempfiles is an ordered list of temp files (open for reading)
f = open("bigfile.txt", "w")
for tempfile in tempfiles:
    for line in tempfile
        f.write(line)

或者 - 总是有效的东西 - 您可以选择缓冲区大小并逐段读取文件,例如

# tempfiles is an ordered list of temp files (open for reading)
f = open("bigfile.txt", "w")
for tempfile in tempfiles:
    while True:
        data = tempfile.read(65536)
        if data:
            f.write(data)
        else:
            break

输入/输出tutorial 有很多很好的信息。

【讨论】:

  • 想知道什么时候一种解决方案更合适,在f.write(tempfile.read())变得不合适之前文件使用了多少内存
【解决方案3】:

Rafe 的回答缺少正确的打开/关闭语句,例如

# tempfiles is a list of file handles to your temp files. Order them however you like
with open("bigfile.txt", "w") as fo:
     for tempfile in tempfiles:
          with open(tempfile,'r') as fi: fo.write(fi.read())

但是,请注意,如果要对大文件的内容进行排序,此方法不会捕获一个或多个临时文件中的最后一行具有不同 EOL 格式的实例,这会导致一些奇怪的排序结果.在这种情况下,您需要在读取临时文件行时剥离它们,然后将一致的 EOL 行写入大文件(即涉及额外的代码行)。

【讨论】:

    【解决方案4】:

    我觉得在 8 年后添加另一个答案和这么多答案有点愚蠢,但是我通过“附加到文件”标题到达这里,并没有看到附加到现有二进制文件的正确解决方案缓冲读/写。

    所以这里是做到这一点的基本方法:

    def append_file_to_file(_from, _to):
        block_size = 1024*1024
        with open(_to, "ab") as outfile, open(_from, "rb") as infile:
            while True:
                input_block = infile.read(block_size)
                if not input_block:
                    break
                outfile.write(input_block)
    

    鉴于此构建块,您可以使用:

    for filename in ['a.bin','b.bin','c.bin']:
        append_file_to_file(filename, 'outfile.bin')
    

    【讨论】:

      【解决方案5】:
      import os
      str = os.listdir("./")
      
      for i in str:
          f = open(i)
          f2 = open("temp.txt", "a")
          for line in f.readlines():
              f2.write(line)
      

      我们可以使用上面的代码从当前目录中的所有文件中读取所有内容并存储到 temp.txt 文件中。

      【讨论】:

        【解决方案6】:

        使用fileinput:

        with open("bigfile.txt", "w") as big_file:
            with fileinput.input(files=tempfiles) as inputs:
                for line in inputs:
                    big_file.write(line)
        

        这比@RafeKettler 的答案更节省内存,因为它不需要在写入big_file 之前将整个文件读入内存。

        【讨论】:

          【解决方案7】:

          试试这个。它非常快(比逐行快得多,并且不应该对大文件造成 VM 抖动),并且应该可以在任何东西上运行,包括 CPython 2.x、CPython 3.x、Pypy、Pypy3 和 Jython。它也应该与操作系统高度无关。此外,它不对文件编码做任何假设。

          #!/usr/local/cpython-3.4/bin/python3
          
          '''Cat 3 files to one: example code'''
          
          import os
          
          def main():
              '''Main function'''
              input_filenames = ['a', 'b', 'c']
          
              block_size = 1024 * 1024
          
              if hasattr(os, 'O_BINARY'):
                  o_binary = getattr(os, 'O_BINARY')
              else:
                  o_binary = 0
              output_file = os.open('output-file', os.O_WRONLY | o_binary)
              for input_filename in input_filenames:
                  input_file = os.open(input_filename, os.O_RDONLY | o_binary)
                  while True:
                      input_block = os.read(input_file, block_size)
                      if not input_block:
                          break
                      os.write(output_file, input_block)
                  os.close(input_file)
              os.close(output_file)
          
          main()
          

          我遗漏了一个(非平凡的)优化:最好不要假设一个好的块大小,而是使用一堆随机的,然后慢慢退出随机化以专注于好的块大小(有时称为“模拟退火”)。但这会带来更多的复杂性,而实际上几乎没有性能优势。

          您还可以让 os.write 跟踪其返回值并重新启动部分写入,但这仅在您期望接收(非终端)*ix 信号时才真正需要。

          【讨论】:

            【解决方案8】:

            在这段代码中,您可以指明输入/输出文件的路径和名称,它将在该路径中创建最终的大文件:

            import os
            
            dir_name = "Your_Desired_Folder/Goes_Here"    #path
            input_files_names = ["File1.txt", "File2.txt", "File3.txt"]     #input files
            file_name_out = "Big_File.txt"     #choose a name for the output file
            file_output = os.path.join(dir_name, file_name_out)
            fout = open(file_output, "w")
            
            for tempfile in input_files_names:
                inputfile = os.path.join(dir_name, tempfile)
                fin = open(inputfile, 'r')
                for line in fin:
                    fout.write(line)
            
            fin.close()    
            fout.close()
            

            【讨论】:

              【解决方案9】:

              将数据从多个文件复制到一个大文件的简单高效的方法,在此之前您需要将文件重命名为 (int),例如。 1,2,3,4...等,代码:

              #Rename Files First
              
              import os
              
              path = 'directory_name'
              files = os.listdir(path)
              i = 1
              for file in files:
                  os.rename(os.path.join(path, file), os.path.join(path, str(i)+'.txt'))
              
                  i = i+1

              # Code For Copying Data from Multiple files
              
              import os
              
              i = 1
              while i<50:
              
                  filename = i
                  for filename in os.listdir("directory_name"):
              
                      # %s is your filename # .txt is file extension 
                      f = open("%s.txt" % i,'r') 
                      fout = open("output_filename", "a")
              
                  for line in f:
                      fout.write(line)
                  i += 1

              【讨论】:

                【解决方案10】:

                Python 3 中还有 fileinput 类,非常适合这种情况

                【讨论】:

                • 如果你添加一个关于如何使用文件输入的例子会很好
                【解决方案11】:

                我正在解决类似的问题,我正在将一个文件夹中的多个文件组合成一个大文件,在同一个文件夹中,根据修改的文件进行排序 提示在代码块中的 cmets 中

                from glob import glob
                import os
                
                # Folder is where files are stored 
                # This is also where the big file will be stored
                folder = r".\test_folder"
                big_filename = r"connected.txt"
                
                # Get all files except big the file and sort by last modified
                all_files = glob(folder + "/*")
                all_files = [fi for fi in all_files if big_filename not in fi]
                all_files.sort(key=os.path.getmtime)
                
                # Get content of each file and append it to a list
                output_big_file = []
                for one_file in all_files:
                    with open(one_file, "r", encoding="utf-8") as f:
                        output_big_file.append(f.read())
                
                # Save list as a file
                save_path = os.path.join(folder, big_filename)
                with open(save_path, "w", encoding="utf-8") as f:
                    f.write("\n".join(output_big_file))
                

                【讨论】:

                • 正如目前所写,您的答案尚不清楚。请edit 添加其他详细信息,以帮助其他人了解这如何解决所提出的问题。你可以找到更多关于如何写好答案的信息in the help center
                猜你喜欢
                • 2023-03-06
                • 1970-01-01
                • 2021-08-29
                • 2021-02-09
                • 2019-04-03
                • 2020-03-19
                • 1970-01-01
                • 2019-08-15
                相关资源
                最近更新 更多