我想在文件中特定行的特定列插入一个字符串。
假设我有一个文件How was the English test?
How was the Math test?
How was the Chemistry test?
How was the test?
How was the History test?
我想通过在第4行第13行添加字符串History
来更改最后一行说with open("file.txt", "r+") as f:
# Read entire file
lines = f.readlines()
# Update line
lino = 4 - 1
colno = 13 -1
lines[lino] = lines[lino][:colno] + "History " + lines[lino][colno:]
# Rewrite file
f.seek(0)
for line in lines:
f.write(line)
f.truncate()
f.close()
。
目前我读取文件的每一行并将字符串添加到指定位置。
public interface AccountRepo extends JpaRepository<Account, Long> {
Account findByRkPptIdAndPlanId(String rkParticipantID, Long plan);
Account findOne(Long id);
Account save(Account account);
Account findByPlanIdAndParticipantId(Long planId, Long participantId); }
但我觉得我应该只需将该行添加到文件中,而无需阅读和重写整个文件。
答案 0 :(得分:2)
这可能是下面SO线程的副本
Fastest Way to Delete a Line from Large File in Python
上面是关于删除的讨论,这只是一种操作,而你的更多是一种修改。所以代码会像下面那样更新
def update(filename, lineno, column, text):
fro = open(filename, "rb")
current_line = 0
while current_line < lineno - 1:
fro.readline()
current_line += 1
seekpoint = fro.tell()
frw = open(filename, "r+b")
frw.seek(seekpoint, 0)
# read the line we want to update
line = fro.readline()
chars = line[0: column-1] + text + line[column-1:]
while chars:
frw.writelines(chars)
chars = fro.readline()
fro.close()
frw.truncate()
frw.close()
if __name__ == "__main__":
update("file.txt", 4, 13, "History ")
在一个大文件中,在更新需要发生的lineno之前不进行修改是有意义的。想象一下你有10K行的文件并且更新需要在9K发生,你的代码将加载所有9K
行不必要的内存中的数据。您拥有的代码仍然可以工作但不是最佳方式
答案 1 :(得分:1)
您可以使用以下代码:
with open("test.txt",'r+') as f:
# Read the file
lines=f.readlines()
# Gets the column
column=int(input("Column:"))-1
# Gets the line
line=int(input("Line:"))-1
# Gets the word
word=input("Word:")
lines[line]=lines[line][0:column]+word+lines[line][column:]
# Delete the file
f.seek(0)
for i in lines:
# Append the lines
f.write(i)
答案 2 :(得分:1)
函数readlines()
读取整个文件。但它并不是必须的。它实际上从当前文件光标位置读取到结尾,在打开后恰好是0
。 (要确认这一点,请在f.tell()
语句后立即尝试with
。)如果我们接近文件末尾怎么办?
编写代码的方式意味着您对文件内容和布局的一些先验知识。你能在每条线上设置任何限制吗?例如,根据您的示例数据,我们可能会说保证行数为27个字节或更少。让我们把它绕到32,以获得2-ness&#34;并尝试从文件末尾搜索向后。
# note the "rb+"; need to open in binary mode, else seeking is strictly
# a "forward from 0" operation. We need to be able to seek backwards
with open("file.txt", "rb+") as f:
# caveat: if file is less than 32 bytes, this will throw
# an exception. The second parameter, 2, says "from end of file"
f.seek(-32, 2)
last = f.readlines()[-1].decode()
此时代码只读取文件的最后32个字节。 1 readlines()
(在字节级别)将查找行结束字节(在Unix中,{ {1}}或\n
或字节值10),并返回之前和之后。拼写出来:
0x0a
至关重要的是,在UTF-8编码下,通过利用UTF-8属性可以很好地工作,在编码非ASCII字节时,128字节以下的ASCII字节值不。换句话说,确切的字节>>> last = f.readlines()
>>> print( last )
[b'hemistry test?\n', b'How was the test?']
>>> last = last[-1]
>>> print( last )
b'How was the test?'
(或\n
)仅作为换行符出现,而不是作为字符的一部分出现。如果您使用的是非UTF-8编码,则需要检查代码假设是否仍然存在。
另一个注意事项:给定示例数据,32字节是任意的。更现实和典型的值可能是512,1024或4096.最后,将它放回到一个工作示例:
0x0a
请注意,不需要with open("file.txt", "rb+") as f:
# caveat: if file is less than 32 bytes, this will throw
# an exception. The second parameter, 2, says "from end of file"
f.seek(-32, 2)
# does *not* read while file, unless file is exactly 32 bytes.
last = f.readlines()[-1]
last_decoded = last.decode()
# Update line
colno = 13 -1
last_decoded = last_decoded[:colno] + "History " + last_decoded[colno:]
last_line_bytes = len( last )
f.seek(-last_line_bytes, 2)
f.write( last_decoded.encode() )
f.truncate()
。 f.close()
语句自动处理。
1 迂腐将正确地指出,计算机和操作系统可能至少读取了512字节,如果不是4096字节,则与磁盘或内存页面大小有关。
答案 3 :(得分:1)
这个答案只会循环遍历文件一次,只会在插入后写入所有内容。如果插入的末尾几乎没有开销,那么插入开头的位置并不比完整的读写更糟糕。
def insert(file, line, column, text):
ln, cn = line - 1, column - 1 # offset from human index to Python index
count = 0 # initial count of characters
with open(file, 'r+') as f: # open file for reading an writing
for idx, line in enumerate(f): # for all line in the file
if idx < ln: # before the given line
count += len(line) # read and count characters
elif idx == ln: # once at the line
f.seek(count + cn) # place cursor at the correct character location
remainder = f.read() # store all character afterwards
f.seek(count + cn) # move cursor back to the correct character location
f.write(text + remainder) # insert text and rewrite the remainder
return # You're finished!
答案 4 :(得分:0)
我不确定您是否在更改文件以包含“历史记录”这个词时遇到问题,或者您是否想知道如何只重写文件的某些部分,而不必重写整个文件。
如果您遇到一般问题,这里有一些简单的代码可以使用,只要您知道要更改的文件中的行。只需更改程序的第一行和最后一行,即可相应地读写语句。
fileData="""How was the English test?
How was the Math test?
How was the Chemistry test?
How was the test?""" # So that I don't have to create the file, I'm writing the text directly into a variable.
fileData=fileData.split("\n")
fileData[3]=fileData[3][:11]+" History"+fileData[3][11:] # The 3 referes to the line to add "History" to. (The first line is line 0)
storeData=""
for i in fileData:storeData+=i+"\n"
storeData=storeData[:-1]
print(storeData) # You can change this to a write command.
如果您想知道如何将特定的“部分”更改为文件,而不重写整个内容,那么(据我所知)这是不可能的。
假设您有一个说Ths is a TEST file.
的文件,并且您想要更正它以说This is a TEST file.
;你在技术上会改变17个字符并在最后添加一个字符。您正在将“s”更改为“i”,将第一个空格更改为“s”,将“i”(从“is”)更改为空格等...当您向前移动文本时。
计算机实际上不能在其他字节之间插入字节。它只能移动数据,以腾出空间。
答案 5 :(得分:-1)
不幸的是,你的感受在这里误导了你。文件的设计不容易修改。简单地在文件中添加一行并不简单。
这看似简单的根源可能是你文件的心智模型。最有可能你使用的比喻是一张纸。 (在文件中将文件可视化为GUI中的文件),在一张纸上有足够的空白区域来插入东西,只修改一行似乎很简单,你只需擦除&#34;测试?&#34;然后写&#34;历史测试?&#34;额外的字符只是表示线条稍长一些,并且该线条上的空白区域较少。没有其他线路需要触及,简单.....
不幸的是,一张纸与文本文件的真实情况完全不同。文本文件本质上是一长串字符(位组),换行符只是另一个字符(通常由/n
表示,所以它看起来更像是:
&#34;英语测试怎么样?\ n数学测试怎么样?\ n化学测试怎么样?\ n测试怎么样?\ n编程测试怎么样?&#34;
这就是大多数语言中的文本变量称为字符串的原因。文件中没有空间用于插入&#34;历史记录以适应&#34;
插入后的字符不能滑动;它们在磁盘上有固定位置,因此在插入后插入需要读取的每个字符,并将它们写入磁盘上的新位置。
这可以归结为,因为你必须扩展文件并在编辑后重写所有内容,这不值得做。除非你处理可能不适合ram的大量文本文件。
方式更简单,效率更低这似乎效率低下,但这是计算机做得好的事情。如果您想提高RAM效率,可以逐行读取批量操作。
请参阅实际代码的其他多个示例,我的答案目的是解决为什么将文本插入文件看起来像对文件的一个简单的小操作,但实际上并不是。