对大文件做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