鱼C论坛

 找回密码
 立即注册
查看: 1376|回复: 6

[已解决]同样的代码,读取不同的文件的时候会报错

[复制链接]
发表于 2022-3-4 18:44:38 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 小丑9 于 2022-3-4 18:46 编辑
#编写一个程序,当用户输入文件名和行数(N)后,将该文件的前N行内容打印到屏幕上。
#用户可以随意输入需要显示的行数。(如输入13:21打印第13行到第21行,输入:21打印前21行,输入21:则打印从第21行开始到文件结尾所有内容)
#这是问题


def file_view(file_name, line_num):
    if line_num.strip() == ':':
        begin = '1'
        end = '-1'

    (begin, end) = line_num.split(':')

    if begin == '':
        begin = '1'
    if end  == '':
        end = '-1'

    if begin == '1' and end == '-1':
        prompt = '的全文'
    elif begin == '1':
        prompt = '从开始到%s' % end
    elif end == '-1':
        prompt = '从%s到结束' % begin
    else:
        prompt = '从第%s行到第%s行' % (begin, end)

    print('\n文件%s%s的内容如下:\n' % (file_name, prompt))

    begin = int(begin) - 1
    end = int(end)
    lines = end - begin

    f = open(file_name)

    for i in range(begin):  # 用于消耗掉begin之前的内容
        f.readline()

    if lines < 0:
        print(f.read())
    else:
        for j in range(lines):
            print(f.readline(), end='')

    f.close()


file_name = input(r'请输入要打开的文件(C:\\test.txt):')
line_num = input('请输入需要显示的行数【格式如 13:21 或 :21 或 21: 或 : 】:')
file_view(file_name, line_num)


同样的代码,当读取的文件是数字时,不会报错,但如果是文字的话就会报错,显示下面 这个,这是为什么?

D:\Python\python.exe D:/系统/练习/作业.py
请输入要打开的文件(C:\\test.txt):国歌.txt
请输入需要显示的行数【格式如 13:21 或 :21 或 21: 或 : 】::

文件国歌.txt的全文的内容如下:

Traceback (most recent call last):
  File "D:\系统\练习\作业.py", line 44, in <module>
    file_view(file_name, line_num)
  File "D:\系统\练习\作业.py", line 34, in file_view
    print(f.read())
UnicodeDecodeError: 'gbk' codec can't decode byte 0x81 in position 8: illegal multibyte sequence

进程已结束,退出代码1



最佳答案
2022-3-4 19:48:23
本帖最后由 isdkz 于 2022-3-4 19:49 编辑
小丑9 发表于 2022-3-4 19:27
我没学编码啥的,看不懂啊,可不可以通俗易懂点


因为计算机只会跟 二进制 打交道,所以字符存到计算机里都是用特定的二进制序列来保存的,

而 二进制序列 到 字符 的对应关系就是编码,像一些普通的字符,在计算机发展初期就存在了的,

比如数字,字母等等 ascii 编码的字符,ascii 编码是最早的编码,它只需要一个字节,

不过一个字节只有 8 个 二进制位,还有 1 位用作保留位,也就是只剩下 7 位可用,

所以 ascii 只能表示 2 的 7 次方也就是 128 个字符,

这很显然对于这个世界的字符数量来说是远远不够的,

所以发展到后来的 unicode,utf-8,gbk 等编码。

计算机处理数据是以 字节 为单位的(因为早期的计算机就是 8 位的,一直发展到现在的 64 位),

所以 ascii 字符无论如何也不会乱码,也不会出现编码错误,

这就是你读取的文件都是数字时不会出现错误的原因,

而中文字符至少需要 2 个字节(gbk 编码使用 2 个字节表示中文字符,

utf-8 编码使用 3 个字节表示中文字符),

所以你就得按对应的编码格式打开文件才能正常解码,

从你的报错信息可知,gbk 无法解码你的文件,

那你就得打开文件的时候指定 utf-8 编码打开。

故对你的代码修改如下:
#编写一个程序,当用户输入文件名和行数(N)后,将该文件的前N行内容打印到屏幕上。
#用户可以随意输入需要显示的行数。(如输入13:21打印第13行到第21行,输入:21打印前21行,输入21:则打印从第21行开始到文件结尾所有内容)
#这是问题


def file_view(file_name, line_num):
    if line_num.strip() == ':':
        begin = '1'
        end = '-1'

    (begin, end) = line_num.split(':')

    if begin == '':
        begin = '1'
    if end  == '':
        end = '-1'

    if begin == '1' and end == '-1':
        prompt = '的全文'
    elif begin == '1':
        prompt = '从开始到%s' % end
    elif end == '-1':
        prompt = '从%s到结束' % begin
    else:
        prompt = '从第%s行到第%s行' % (begin, end)

    print('\n文件%s%s的内容如下:\n' % (file_name, prompt))

    begin = int(begin) - 1
    end = int(end)
    lines = end - begin

    f = open(file_name, encoding='utf-8')              # 指定编码格式为 utf-8

    for i in range(begin):  # 用于消耗掉begin之前的内容
        f.readline()

    if lines < 0:
        print(f.read())
    else:
        for j in range(lines):
            print(f.readline(), end='')

    f.close()


file_name = input(r'请输入要打开的文件(C:\\test.txt):')
line_num = input('请输入需要显示的行数【格式如 13:21 或 :21 或 21: 或 : 】:')
file_view(file_name, line_num)
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2022-3-4 19:01:34 | 显示全部楼层
本帖最后由 ba21 于 2022-3-4 20:11 编辑

000111
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-3-4 19:02:06 | 显示全部楼层
可能是编码问题,
f = open(file_name)
改成
f = open(file_name, encoding="utf-8")
试试
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-3-4 19:27:13 | 显示全部楼层
ba21 发表于 2022-3-4 19:01
文件保存是有编码的,同样你读取也要使用相应的编码读取。
使用cchardet判断字符编码(准确度高)
cchard ...

我没学编码啥的,看不懂啊,可不可以通俗易懂点
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-3-4 19:38:18 | 显示全部楼层
小丑9 发表于 2022-3-4 19:27
我没学编码啥的,看不懂啊,可不可以通俗易懂点

[b]编码可以理解为打开文件用什么语言

比如说用我们普通话去听英文,这肯定不行

又比如说用英文去听中文,也不行

python常用的编码有utf-8和gbk

utf-8一般不会出现乱码

所以把打开文件的那行改成:
f = open(file_name, encoding="utf-8")

[/b]
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-3-4 19:48:23 | 显示全部楼层    本楼为最佳答案   
本帖最后由 isdkz 于 2022-3-4 19:49 编辑
小丑9 发表于 2022-3-4 19:27
我没学编码啥的,看不懂啊,可不可以通俗易懂点


因为计算机只会跟 二进制 打交道,所以字符存到计算机里都是用特定的二进制序列来保存的,

而 二进制序列 到 字符 的对应关系就是编码,像一些普通的字符,在计算机发展初期就存在了的,

比如数字,字母等等 ascii 编码的字符,ascii 编码是最早的编码,它只需要一个字节,

不过一个字节只有 8 个 二进制位,还有 1 位用作保留位,也就是只剩下 7 位可用,

所以 ascii 只能表示 2 的 7 次方也就是 128 个字符,

这很显然对于这个世界的字符数量来说是远远不够的,

所以发展到后来的 unicode,utf-8,gbk 等编码。

计算机处理数据是以 字节 为单位的(因为早期的计算机就是 8 位的,一直发展到现在的 64 位),

所以 ascii 字符无论如何也不会乱码,也不会出现编码错误,

这就是你读取的文件都是数字时不会出现错误的原因,

而中文字符至少需要 2 个字节(gbk 编码使用 2 个字节表示中文字符,

utf-8 编码使用 3 个字节表示中文字符),

所以你就得按对应的编码格式打开文件才能正常解码,

从你的报错信息可知,gbk 无法解码你的文件,

那你就得打开文件的时候指定 utf-8 编码打开。

故对你的代码修改如下:
#编写一个程序,当用户输入文件名和行数(N)后,将该文件的前N行内容打印到屏幕上。
#用户可以随意输入需要显示的行数。(如输入13:21打印第13行到第21行,输入:21打印前21行,输入21:则打印从第21行开始到文件结尾所有内容)
#这是问题


def file_view(file_name, line_num):
    if line_num.strip() == ':':
        begin = '1'
        end = '-1'

    (begin, end) = line_num.split(':')

    if begin == '':
        begin = '1'
    if end  == '':
        end = '-1'

    if begin == '1' and end == '-1':
        prompt = '的全文'
    elif begin == '1':
        prompt = '从开始到%s' % end
    elif end == '-1':
        prompt = '从%s到结束' % begin
    else:
        prompt = '从第%s行到第%s行' % (begin, end)

    print('\n文件%s%s的内容如下:\n' % (file_name, prompt))

    begin = int(begin) - 1
    end = int(end)
    lines = end - begin

    f = open(file_name, encoding='utf-8')              # 指定编码格式为 utf-8

    for i in range(begin):  # 用于消耗掉begin之前的内容
        f.readline()

    if lines < 0:
        print(f.read())
    else:
        for j in range(lines):
            print(f.readline(), end='')

    f.close()


file_name = input(r'请输入要打开的文件(C:\\test.txt):')
line_num = input('请输入需要显示的行数【格式如 13:21 或 :21 或 21: 或 : 】:')
file_view(file_name, line_num)
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-3-4 20:09:44 | 显示全部楼层
isdkz 发表于 2022-3-4 19:48
因为计算机只会跟 二进制 打交道,所以字符存到计算机里都是用特定的二进制序列来保存的,

而 二进 ...

感谢!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-1-12 06:54

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表