簡體   English   中英

從python中的多個大文件連接每n行

[英]Concatenate every n-th line from multiple large files in python

考慮以下大小不同的文件:

FILE1.TXT

sad
mad
rad
cad
saf

FILE2.TXT

er
ar
ir
lr
gr
cf

file3.txt

1
2
3
4
5
6
7
8
9

我正在尋找一種方法來連接所有文件的第二行,因此所需的輸出文件將是:

sad
er
1
rad
ir
3
saf
gr
5
7
9

我成功使用以下腳本對測試文件進行了管理:

import os    

globalList = list()

for file in os.listdir('.'):
    if file.endswith('txt'):
        with open(file, 'r') as inf:
            l = list()
            n=0
            for i, line in enumerate(inf):
                if i == n:
                    nline=line.strip()
                    l.append(nline)
                    n+=2

            globalList.append(l)

            inf.close()

ouf = open('final.txt', 'w')

for i in range(len(max(globalList, key=len))):
    for x in globalList:
        if i < len(x):
            ouf.write(x[i])
            ouf.write('\n')
        else:
            pass

ouf.close()

上面的腳本適用於小的測試文件。 但是,當我用實際文件(成百上千行的數百個文件)進行嘗試時,我的計算機很快就會耗盡內存,並且腳本崩潰。 有沒有辦法解決這個問題,即避免在RAM中存儲太多信息,而以某種方式直接將行寫入輸出文件中? 謝謝!

在python3中嘗試以下代碼:

script.py

from itertools import  zip_longest
import glob


every_xth_line = 2
files = [open(filename) for filename in glob.glob("*.txt")]

with open('output.txt', 'w') as f:
    trigger = 0
    for lines in zip_longest(*files, fillvalue=''):
        if not trigger:
            for line in lines:
                f.write(line)
        trigger = (trigger + 1) % every_xth_line

output.txt的

sad
er
1
rad
ir
3
saf
gr
5
7
9

open本身實際上可以被迭代。 zip_longest確保腳本將一直運行,直到用完了最長的文件,並且fillvalues只是作為空字符串插入。

必須使用觸發器來分離均勻和不均勻的文件,通過將every_xth_line設置為其他內容,可以通過簡單的模運算來實現更通用的解決方案。

至於可伸縮性:

我試圖生成大型文件:

cat /usr/share/dict/words > file1.txt
cat /usr/share/dict/words > file2.txt
cat /usr/share/dict/words > file3.txt

粘貼一些副本后:

68M Nov  1 13:45 file.txt
68M Nov  1 13:45 file2.txt
68M Nov  1 13:45 file3.txt

運行它:

time python3 script.py
4.31user 0.14system 0:04.46elapsed 99%CPU (0avgtext+0avgdata 9828maxresident)k
0inputs+206312outputs (0major+1146minor)pagefaults 0swaps

結果:

101M Nov  1 13:46 output.txt

我相信您想要的是這樣的東西。 請注意,我不存儲行數組,而是在需要時懶惰地讀取行。 它有助於節省內存

import os


files = [open(file) for file in os.listdir('.') if file.endswith('txt')]
with open('final.txt', 'w') as f:
    while 1:
        for file in files:
            try:
                f.write(next(f))
            except StopIteration:
                break
            if YourCounterFunction:
                break

嘗試一次閱讀每一行。 如果我們能弄清楚如何不使短路,或者我們可能沒有得到get_odd的返回

#!/usr/bin/env python3

def get_odd(f):
    x = f.readline().strip()
    if x: print(x)
    return f.readline() or ""

with open("file1.txt", 'r') as x:
    with open("file2.txt", 'r') as y:
        with open("file3.txt", 'r') as z:
            while ("" != (get_odd(x) + get_odd(y) + get_odd(z))):
                pass

我將為奇數行創建一個生成器。 然后獲取我想要的行並將其寫入文件。 這是代碼:

def numberLine():
    number = -2
    while True:
        number += 2
        yield number

def writeNewFile(files):
    with open("newFile.txt", 'w') as theFile:
        for line in numberLine():
            if files:
                for file in files:
                    try:
                        with open(file) as openFile:
                            theFile.write(openFile.readlines()[line])
                    except IndexError:
                        files.remove(file)
                        continue
            else:
                break

現在,您需要做的就是將帶有文件的列表傳遞到writeNewFile函數中! writeNewFile([file for file in os.listdir() if file.endswith('txt')])

該腳本處理任意數量的文件,並在每個文件的第二行打印直到所有文件都達到EOF。

#!/usr/bin/env python

import sys

def every_second(files):
    fds = [open(f,'r') for f in files]

    i = 0
    end = 0
    num = len(fds)
    while end < num:
        for fd in fds:
            try:
                l = fd.readline()
            except:
                continue
            if l == "":
                end += 1
                fd.close()
            elif i%2 == 0:
                sys.stdout.write(l)
        i += 1

if __name__ == '__main__':
    every_second(sys.argv[1:])

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM