如何在Python中从文件中读取数字?

72

我想从文件中读取数字并将其存储到二维数组中。

文件内容:

  • 包含w,h的行
  • h行,每行包含w个以空格分隔的整数

例如:

4 3
1 2 3 4
2 3 4 5
6 7 8 9

你卡在某个特定的地方了吗?看一下http://docs.python.org/tutorial/inputoutput.html#methods-of-file-objects(我不是这里的那个投票反对者) - Jacob
但是有一个示例可以逐行读取文件,而不是作为数字。 - kravemir
你的问题缺乏对文件内容和期望输出的清晰描述。 - mac
@Miro 获取行是第一步,然后你需要使用类似split()的方法来操作字符串。你说你是Python的新手,所以我猜你想学点东西,但如果你只是在这里找答案,你不会学到很多。而且,这看起来像是作业。 - Jacob
2
但在C++中,您逐个读取数字,在那里将字符串拆分为数字,因此我不知道从哪里开始。 - kravemir
显示剩余2条评论
6个回答

104
假设您没有多余的空格:
with open('file') as f:
    w, h = [int(x) for x in next(f).split()] # read first line
    array = []
    for line in f: # read rest of lines
        array.append([int(x) for x in line.split()])

你可以将最后的for循环压缩成一个嵌套的列表推导式:

with open('file') as f:
    w, h = [int(x) for x in next(f).split()]
    array = [[int(x) for x in line.split()] for line in f]

3
值不是以字符串形式存储的吗? - ascobol
2
+1: 这是一个很棒的回答,你巧妙地使用了readlineline in f ,我对此给予高度评价。干杯。 - machine yearning
@Jean-ClaudeArbaut 如果你这样做,可能会在当前版本的CPython上工作,但是你已经超出了API规范。其他Python实现或未来的Python版本可以自由地实现不同的行为。 - Sven Marnach
@SvenMarnach,Python3文档中有相同的句子吗?我没找到。 - user6015398
2
@Jean-ClaudeArbaut 不,你是对的。在Python 3中,你可以自由地混合使用next(f)f.readline(),因为next()实际上是使用readline()实现的,并且缓冲区被移动到一个单独的类中,该类用于从文件读取的所有机制。感谢您指出这一点。我现在记得几年前读过它,但当我写下先前的评论时,它已经从我的脑海中滑落了。 - Sven Marnach
显示剩余6条评论

19
对我而言,这种看似简单的问题正是Python所擅长的。特别是如果你之前使用过C++等语言,那么简单的文本解析可能会让你十分头疼,你会真正感受到Python可以提供的功能单元化的解决方案。我会用一些内置函数和生成器表达式来保持它非常简单。
你需要使用open(name, mode), myfile.readlines(), mystring.split(), int(myval), 然后你可能想以Pythonic的方式将它们组合起来使用一些生成器。
# This opens a handle to your file, in 'r' read mode
file_handle = open('mynumbers.txt', 'r')
# Read in all the lines of your file into a list of lines
lines_list = file_handle.readlines()
# Extract dimensions from first line. Cast values to integers from strings.
cols, rows = (int(val) for val in lines_list[0].split())
# Do a double-nested list comprehension to get the rest of the data into your matrix
my_data = [[int(val) for val in line.split()] for line in lines_list[1:]]

在这里查找生成器表达式它们可以将您的代码简化为离散的功能单元!想象一下在C++中用4行做同样的事情...它会是一个怪物。特别是列表生成器,当我还是C ++用户时,我总是希望有像那样的东西,并经常最终构建自定义函数来构造我想要的每种类型的数组。


我认为这个不起作用。cols, rows = (int(val) for val in '4 3\n') 不会达到你想要的效果。同样,对于 [int(val) for val in line] 也是一样的,因为 line 将会是类似 '1 2 3 4\n' 的东西。 - Jason R. Coombs
@Jason:是的,抱歉我的原始代码中有几个错误,但主要思路是正确的。已在上面进行了更正。我想这就是迭代开发的用途! :) - machine yearning
3
在 OP 提到的这种简单情况中,使用 C++ 版本虽然代码会稍微长一些,但并不像你所说的那样“庞大”。可以使用 fscanf() 或 streams 以及 vector<vector<int>>(甚至是 int[][])来读取和解析文件。而在这个过程中,C++ 可以提供更多关于内存管理的控制。 - dolphin
2
实际上,ifstreams比fscanf更容易处理,因为fscanf是C函数,而不是C++函数。如果你只是在C++中解析文本,并且有任何比建议的Python解决方案更复杂的东西,那么显然你做错了什么。 - Andrej

6

不确定为什么需要w,h。如果这些值确实是必需的,并且意味着只应读取指定数量的行和列,则可以尝试以下操作:

output = []
with open(r'c:\file.txt', 'r') as f:
    w, h  = map(int, f.readline().split())
    tmp = []
    for i, line in enumerate(f):
        if i == h:
            break
        tmp.append(map(int, line.split()[:w]))
    output.append(tmp)

1
有趣的方法,同时包含标题数据,我甚至没有想到。完整性加1...但有点冗长/难以阅读 :) - machine yearning
1
谢谢)我创建了一个扩展解决方案,逐行迭代并为所有w、h的出现创建列表。然而,最佳答案已经被选中))) - Artsiom Rudzenka

2

可以同时使用Python2(例如Python 2.7.10)和Python3(例如Python 3.6.4)。

with open('in.txt') as f:
  rows,cols=np.fromfile(f, dtype=int, count=2, sep=" ")
  data = np.fromfile(f, dtype=int, count=cols*rows, sep=" ").reshape((rows,cols))

另一种方法是同时使用Python2(例如Python 2.7.10)和Python3(例如Python 3.6.4),对于复杂矩阵,请参见下面的示例(只需将int更改为complex)。

with open('in.txt') as f:
   data = []
   cols,rows=list(map(int, f.readline().split()))
   for i in range(0, rows):
      data.append(list(map(int, f.readline().split()[:cols])))
print (data)

我更新了代码,这种方法适用于任意数量和任何类型的矩阵(intcomplexfloat),在初始的in.txt文件中。

该程序作为一个应用程序产生矩阵乘法。可以在python2中使用,如果要在python3中使用,请进行以下更改。

print to print()

并且

print "%7g" %a[i,j],    to     print ("%7g" %a[i,j],end="")

脚本:

import numpy as np

def printMatrix(a):
   print ("Matrix["+("%d" %a.shape[0])+"]["+("%d" %a.shape[1])+"]")
   rows = a.shape[0]
   cols = a.shape[1]
   for i in range(0,rows):
      for j in range(0,cols):
         print "%7g" %a[i,j],
      print
   print      

def readMatrixFile(FileName):
   rows,cols=np.fromfile(FileName, dtype=int, count=2, sep=" ")
   a = np.fromfile(FileName, dtype=float, count=rows*cols, sep=" ").reshape((rows,cols))
   return a

def readMatrixFileComplex(FileName):
   data = []
   rows,cols=list(map(int, FileName.readline().split()))
   for i in range(0, rows):
      data.append(list(map(complex, FileName.readline().split()[:cols])))
   a = np.array(data)
   return a

f = open('in.txt')
a=readMatrixFile(f)
printMatrix(a)
b=readMatrixFile(f)
printMatrix(b)
a1=readMatrixFile(f)
printMatrix(a1)
b1=readMatrixFile(f)
printMatrix(b1)
f.close()

print ("matrix multiplication")
c = np.dot(a,b)
printMatrix(c)
c1 = np.dot(a1,b1)
printMatrix(c1)

with open('complex_in.txt') as fid:
  a2=readMatrixFileComplex(fid)
  print(a2)
  b2=readMatrixFileComplex(fid)
  print(b2)

print ("complex matrix multiplication")
c2 = np.dot(a2,b2)
print(c2)
print ("real part of complex matrix")
printMatrix(c2.real)
print ("imaginary part of complex matrix")
printMatrix(c2.imag)

我将采用作为输入文件的 in.txt

4 4
1 1 1 1
2 4 8 16
3 9 27 81
4 16 64 256
4 3
4.02 -3.0 4.0
-13.0 19.0 -7.0
3.0 -2.0 7.0
-1.0 1.0 -1.0
3 4
1 2 -2 0
-3 4 7 2
6 0 3 1
4 2
-1 3
0 9
1 -11
4 -5

以及 complex_in.txt

3 4
1+1j 2+2j -2-2j 0+0j
-3-3j 4+4j 7+7j 2+2j
6+6j 0+0j 3+3j 1+1j
4 2
-1-1j 3+3j
0+0j 9+9j
1+1j -11-11j
4+4j -5-5j

输出结果如下:

Matrix[4][4]
     1      1      1      1
     2      4      8     16
     3      9     27     81
     4     16     64    256

Matrix[4][3]
  4.02     -3      4
   -13     19     -7
     3     -2      7
    -1      1     -1

Matrix[3][4]
     1      2     -2      0
    -3      4      7      2
     6      0      3      1

Matrix[4][2]
    -1      3
     0      9
     1    -11
     4     -5

matrix multiplication
Matrix[4][3]
  -6.98      15       3
 -35.96      70      20
-104.94     189      57
-255.92     420      96

Matrix[3][2]
    -3     43
    18    -60
     1    -20

[[ 1.+1.j  2.+2.j -2.-2.j  0.+0.j]
 [-3.-3.j  4.+4.j  7.+7.j  2.+2.j]
 [ 6.+6.j  0.+0.j  3.+3.j  1.+1.j]]
[[ -1. -1.j   3. +3.j]
 [  0. +0.j   9. +9.j]
 [  1. +1.j -11.-11.j]
 [  4. +4.j  -5. -5.j]]
complex matrix multiplication
[[ 0.  -6.j  0. +86.j]
 [ 0. +36.j  0.-120.j]
 [ 0.  +2.j  0. -40.j]]
real part of complex matrix
Matrix[3][2]
      0       0
      0       0
      0       0

imaginary part of complex matrix
Matrix[3][2]
     -6      86
     36    -120
      2     -40

2
为了简化回答,这里有一个程序,它从文件中读取整数并对它们进行排序。
f = open("input.txt", 'r')

nums = f.readlines()
nums = [int(i) for i in nums]

读取文件的每一行,将每个字符串转换为数字

nums.sort()

排序数字

f.close()

f = open("input.txt", 'w')
for num in nums:
    f.write("%d\n" %num)

f.close()

写回它们 就是这么简单,希望能帮到你。

1
我能想到的最短的是:

with open("file") as f:
    (w, h), data = [int(x) for x in f.readline().split()], [int(x) for x in f.read().split()]

您可以将 (w, h) 和数据分开,如果这样看起来更整洁。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接