python 文件操作

对大文件做shuf的情况

在实际项目中,若遇到大文件,比如下述代码中的data.txt,是一个大小超过200G的文件,若对该文件的所有数据做洗牌(shuf),很容易造成内存崩溃,程序被强制退出。在这种情况下,可以先取出大文件行号,对行号做shuf,再将行号对应的行数据对应写入新文件 data-shuf.txt
代码如下

import numpy as np
import linecache

data=list()
cnt=0  # 用于记录行号
# 取出行号,存入data
with open('./data','r',errors='ignore') as f:
    while True:
        line = f.readline()
        cnt+=1
        data.append(cnt)
        if not line:
            data.pop() # 删除最后一个多加的行号
            break
# 对行号数据做shuf
np.random.shuffle(data)

result=open('./data-shuf.txt','w',errors='ignore')#无缓冲:buffering设置为0 有输入就写入磁盘
cnt=0 # 行号归零,重新找
for line in data:
    with open('./data','r',errors='ignore') as f:
        while True:
            sentence = f.readline()
            cnt+=1
            if cnt == line:
                result.write(sentence)
                cnt=0
                break
            else:
                sentence=""
            result.flush() # 刷新缓冲区--将缓冲区中的数据立刻写入文件,同时清空缓冲区
result.close()

open函数参数

open() 函数原型
open(file, mode=‘r’, buffering=-1, encoding=None, errors=None, newline=None, closefd=True)
参数说明
file: 要打开的文件名,需加路径(除非是在当前目录)。唯一强制参数
mode: 文件打开的模式(r/w/a)
buffering: 设置buffer(取值为0,1,>1)0代表buffer关闭 (只适用于二进制模式)1代表line buffer(只适用于文本模式),>1表示初始化的buffer大小
encoding: 返回数据的编码(一般为UTF8或GBK)
errors: 报错级别(一般为strict,ignore)若文件中出现编码格式问题,可酌情设置为ignore进行忽略
newline: 用于区分换行符(只对文本模式有效,可以取的值有None,’\n’,’\r’,’’,’\r\n’)
closefd: 传入的file参数类型(缺省为True)

扩展:在某目录下创建/写文件

下面的函数,用于在给定目录下创建文件(若文件不存在则创建)并往文件中写数据。

# example: fpath=./data/1/mydata.txt
def appendToFile(fpath, line):
    if not os.path.exists(fpath):
        f = open(fpath,'w')
        f.write(line)
        f.close()
    else:
        f = open(fpath,'a') # 往文件中追加数据,而非覆盖
        f.write(line)
        f.close()

多层目录下对文件的遍历

假设我们有如下目录结构:

a ->   b   ->   1.txt,  2.txt
       c   ->   3.txt
       d   ->   
       4.txt
       5.txt
for (root, dirs, files) in os.walk('a'):
    #第一次运行时,当前遍历目录为 a
    所以 root == 'a'
         dirs == [ 'b', 'c', 'd']
         files == [ '4.txt', '5.txt']
    
    。。。

    # 接着遍历 dirs 中的每一个目录
    b:  root  = 'a\\b'
        dirs  = []
        files = [ '1.txt', '2.txt']
    
    # dirs为空,返回
    # 遍历c
    c:  root  = 'a\\c'
        dirs  = []
        files = [ '3.txt' ]
    
    PS : 如果想获取文件的全路径,只需要 
    for f in files:
        path = os.path.join(root,f)
    
    # 遍历d
    d:  root  = 'a\\b'
        dirs  = []
        files = []

    遍历完毕,退出循环

示例代码:

# -*- coding: UTF-8 -*-
import os  #word需载入的函数
import sys
import numpy as np

path = "./data/cut_data/"
dst_path = "./data/out-unsplit.txt"
result_file = open(dst_path,"w")

print('==python3将print的内容存入文件的格式==',file=result_file)
for root, dirs, files in os.walk(path):
    for f in files:
        file_path = os.path.join(root,f)
        print("当前遍历的路径:{}".format(file_path))
        with open (file_path,"r",encoding="utf8",errors='ignore') as fr:
            lines = fr.readlines() # 读所有行
            first_line = lines[0] # 只取第一行数据
            data = first_line.split() # 以空格切分
            if len(data) == 1:
                print (file_path,file=result_file)
result_file.close()

使用dict统计文件中特征类(key)中的所有数据(value)

【情景】

  • class-data.txt文件中存放的是随机打散数据和对应的所属的类别信息,两者用\t分开,一行是一个“数据\t类别”
  • result.txt文件中存放的是对每个类别固定数量“数据\t类别”数据
# -*- coding: UTF-8 -*-
import os
import sys
import numpy as np

#统计文本中各类别的数量
dict_class={}
with open("class-data.txt",'r') as fline:
    for line in fline:
        sentence,label=line.split('\t')
        #classname=label[label.rfind('_')+1:].strip()
        if label not in dict_class:
            dict_class[label]=list()
        if len(dict_class[label])<10000:#每个类别取1w数据
            dict_class[label].append(sentence)
fline.close()

with open("result.txt",'w') as fw:
    for k in dict_class:
        for i in range(len(dict_class[k])):
            context="".join(dict_class[k][i])+"\t"+k #按行存入"数据\t类别"
            fw.write(context)
fw.close

未完,续更。。。


参考资料

[1]: 对python文件方法open的探究 https://www.cnblogs.com/rockpine/p/3228890.html
[2]: python open() 文件解码问题
https://blog.csdn.net/yboys/article/details/76033678
[3]: python中os.walk的用法
https://www.jianshu.com/p/bbad16822eab

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值