一、文件操作流程

文件以什么编码存储的,就以什么编码打开

参数:

1.文件路径

2.编码方式,encode

3.执行动作(打开方式):只读,只写,追加,读写,写读...

打开一个已经存在的文件

f = open('D:\qycache\飞碟说.txt',encoding='utf-8',mode='r')
content = f.read()
print(content)
f.close()

执行输出:

知识从未如此性感

代码解释:

变量,可以命令为f_obj,file,f_handler... 这个变量,称之为文件句柄(句柄是操作系统在生成对象时分配给对象的唯一标识)

open  windows的系统功能,也就是说open这个命令,其实就是调用系统打开文件的动作

windows 默认的编码方式:gbk,linux默认的编码方式为utf-8

f.close()  关闭文件

操作文件流程:

打开一个文件,产生一个文件句柄,对文件句柄进行操作,关闭文件

读:

r 只读,以str方式读取

rb 只读,以bytes类型读取(在非文字类的文件是,用rb。比如音频文件等)

下面一个例子

f = open('D:\qycache\飞碟说.txt',encoding='utf-8')
content = f.read()
print(content)
f.close()

默认mode不写,表示只读模式。

编码不一致是,报错

UnicodeDecodeError: 'gbk' codec can't decode byte 0xaa in position 14: illegal multibyte sequence

所以,文件以什么编码存储的,就以什么编码打开

二、文件路径

绝对路径:从根目录开始,一级一级查找知道找到文件。 比如 D:\qycache\飞碟说.txt
相对路径:在同一个文件夹下,直接写文件名即可。

相对路径举例:

f = open('天气.txt',encoding='utf-8')
content = f.read()
print(content)
f.close()

务必保证python代码和txt文件在同一文件夹下。

某些windows系统,读取文件的时候报错

[Error 22] Invalid argument: '\u202adD:\\xx.txt'

解决办法:

1.加2个斜杠,比如 D:\\xx.txt

2.前面加r ,比如 r'D:\xx.txt'

三、文件读取的5种模式

r模式有5种模式读取

第一种:全部读取出来 f.read()

f = open('天气.txt',encoding='utf-8')
content = f.read()
print(content)
f.close()

执行输出:

03月27日(今天)
晴转多云
11~27℃
西南风 1级
重度污染

第二种:一行一行的读 f.readline()

f = open('天气.txt',encoding='utf-8')
print(f.readline())
print(f.readline())
print(f.readline())
f.close()

第三种:将原文件的每一行作为一个列表的元素 f.readlines()

f = open('天气.txt',encoding='utf-8')
print(f.readlines())
f.close()

执行输出:

['03月27日(今天)\n', '晴转多云\n', '11~27℃\n', '西南风 1级\n', '重度污染']

第四种:读取一部分 f.read(n)

在r模式下,read(n) 按照字符去读取

f = open('天气.txt',encoding='utf-8')
print(f.read(3))
f.close()

执行输出:

03月

0 3 月   表示3个字符

第五种:for循环读取

f = open('天气.txt',encoding='utf-8')
for i in f:
print(i.strip())
f.close()

执行输出:

03月27日(今天)
晴转多云
11~27℃
西南风 1级
重度污染

在for循环中,每次读取一行,结束之后,内存就释放了。所以在整个for循环个过程中,始终只占用了一行内容的内存。
推荐使用第5种方式。

四、写操作

 w 文件不存在时,创建一个文件写入内容

有文件时,将原文件内容清空,再写入内容

f = open('log.txt',encoding='utf-8',mode='w')
f.write('人生苦短,我想学Python')
f.close()

wb 以bytes写入,写入的内容,必须要转换为bytes类型才可以

f = open('log.txt',mode='wb')
f.write('人生苦短,我想学Python'.encode(encoding="utf-8"))
f.close()

  

a  追加

没有文件时,创建一个文件追加内容

有文件时,直接追加内容

f = open('log2.txt',encoding='utf-8',mode='a')
f.write('666')
f.close()

r+ 读写,先读,后追加。

错误的写法

f = open('log.txt',encoding='utf-8',mode='r+')
f.write('BBB')
content = f.read()
print(content)
f.close()

执行输出,内容是空的

为什么呢?

因为光标,默认是从0开始。只要进行一个动作,光标就会移动,包括读取。
上面的代码写入时,光标移动到最后了。所以执行f.read()时,读取不到后面的内容了。

r+ 一定要先读后写,否则会错乱或者读取不到内容

w+ 先写后读

f = open('log.txt',encoding='utf-8',mode='w+')
f.write('AAA')
content = f.read()
print(content)
f.close()

执行输出,内容是空的

写完之后,光标移动到最后了。所以读取的时候,读取不到内容了。

f = open('log.txt',encoding='utf-8',mode='w+')
f.write('AAA')
print(f.tell()) #按直接去读光标位置
f.seek(0) #调整光标位置
content = f.read()
print(content)
f.close()

执行输出:

3
AAA

下面一个例子

f = open('log.txt',encoding='utf-8',mode='w+')
f.write('中国')
print(f.tell()) #按直接去读光标位置
f.seek(2) #调整光标位置
content = f.read()
print(content)
f.close()

执行输出:

6

.....

UnicodeDecodeError: 'utf-8' codec can't decode byte 0xad in position 0: invalid start byte

因为一个中文占用3字节

ftp的断点续传,需要用到光标,一定会用到tell和seek

a+ 追加读

这里不举例了

上面列举了那么多模式

用的最多的还是r和r+模式

r的5种模式中,重点掌握第5种。

其他操作方法:

truncate #截取文件
writable() #是否可写
readable() #是否可读

truncate是截取文件,所以文件的打开方式必须可写,但是不能用w或w+等方式打开,因为那样直接清空文件了,所以truncate要在r+或a或a+等模式下测试效果

f = open('log.txt',encoding='utf-8',mode='r+')
# 截取10个字节
f.truncate(3)
content = f.read()
print(content)
f.close()

执行输出:

判断是否可写

f = open('log.txt',encoding='utf-8',mode='r+')
print(f.writable())
f.close()

执行输出:

True

回收方法为:
1、f.close() #回收操作系统级打开的文件,关闭文件句柄
2、del f #回收应用程序级的变量,在python代码级别中,删除变量

为了避免忘记回收文件句柄,需要使用with open方法,代码执行完毕之后,自动关闭文件句柄

功能1:自动关闭文件句柄

with open('log.txt',encoding='utf-8') as f:
print(f.read())

功能2:一次性操作多个文件

with open('log.txt',encoding='utf-8') as f1,\
open('log1.txt',encoding='utf-8',mode='r+') as f2:
print(f1.read())
print(f2.read())

有些情况下,必须先关闭,才能执行某某动作的情况下,不能用with,这种情况比较少见。

推荐使用with open

所有的软件,不是直接在原文件修改的。
它是进行了5步操作

1.将原文件读取到内存。
2.在内存中进行修改,形成新的内容。
3.将新的字符串写入新文件。
4.将原文件删除。
5.将新文件重命名成原文件。

将log文件内容中含有张三的,替换为李四

import os
#第1步
with open('log',encoding='utf-8') as f1,\
open('log.bak',encoding='utf-8',mode='w') as f2:
content = f1.read()
#第2步
new_content = content.replace('张三','李四')
#第3步
f2.write(new_content)
#第4步
os.remove('log')
#第5步
os.rename('log.bak','log')

这种方法,不好。如果文件比较大,内存直接爆掉。因为f1.read()是将文件所有内容写入内存中。

推荐做法:

import os
#第1步
with open('log',encoding='utf-8') as f1,\
open('log.bak',encoding='utf-8',mode='w') as f2:
for i in f1:
#第3步
new_i = i.replace('张三', '李四')
#第4步
f2.write(new_i)
#第4步
os.remove('log')
#第5步
os.rename('log.bak','log')

这种方式,每次只占用一行。
所有软件,都是执行这5步的。

课后作业:

1. 文件a.txt内容:每一行内容分别为商品名字,价钱,个数。
apple 10 3
tesla 100000 1
mac 3000 2
lenovo 30000 3
chicken 10 3
通过代码,将其构建成这种数据类型:[{'name':'apple','price':10,'amount':3},{'name':'tesla','price':1000000,'amount':1}......] 并计算出总价钱。
2,有如下文件:
-------
alex是老男孩python发起人,创建人。
alex其实是人妖。
谁说alex是sb?
你们真逗,alex再牛逼,也掩饰不住资深屌丝的气质。
----------
将文件中所有的alex都替换成大写的SB。 3. 文件a1.txt内容:
文件内容:
name:apple price:10 amount:3 year:2012
name:tesla price:100000 amount:1 year:2013 通过代码,将其构建成这种数据类型:
[{'name':'apple','price':10,'amount':3},
{'name':'tesla','price':1000000,'amount':1}......]
并计算出总价钱。
4,文件a2.txt内容:
文件内容:
序号 部门 人数 平均年龄 备注
1 python 30 26 单身狗
2 Linux 26 30 没对象
3 运营部 20 24 女生多
通过代码,将其构建成这种数据类型:
[{'序号':'1','部门':Python,'人数':30,'平均年龄':26,'备注':'单身狗'},
......]
并计算出总价钱。
5,明日默写:就是第二题的代码(课上讲过)。 

 答案:

第一题

1.1先将文件内容读取出来

with open('a.txt',encoding='utf-8') as f:
for i in f:
i = i.strip()
print(i)

执行输出:

apple 10 3
tesla 100000 1
mac 3000 2
lenovo 30000 3
chicken 10 3

1.2使用空格切割成列表

with open('a.txt',encoding='utf-8') as f:
for i in f:
i = i.strip().split()
print(i)

执行输出:

['apple', '10', '3']
['tesla', '100000', '1']
['mac', '3000', '2']
['lenovo', '30000', '3']
['chicken', '10', '3']

1.3将列表的内容放入字典中,测试打印

with open('a.txt',encoding='utf-8') as f:
for i in f:
i = i.strip().split()
print({'name': i[0], 'price': i[1], 'amount': i[2]})

执行输出:

{'amount': '3', 'name': 'apple', 'price': '10'}
{'amount': '1', 'name': 'tesla', 'price': '100000'}
{'amount': '2', 'name': 'mac', 'price': '3000'}
{'amount': '3', 'name': 'lenovo', 'price': '30000'}
{'amount': '3', 'name': 'chicken', 'price': '10'}

1.4 将字典追加到一个空列表中

#总列表
li = []
with open('a.txt',encoding='utf-8') as f:
for i in f:
#默认使用空格分割
i = i.strip().split()
#将字典追加到列表中
li.append({'name': i[0], 'price': i[1], 'amount': i[2]}) print(li)

执行输出:

[{'price': '10', 'name': 'apple', 'amount': '3'}, {'price': '100000', 'name': 'tesla', 'amount': '1'}, {'price': '3000', 'name': 'mac', 'amount': '2'}, {'price': '30000', 'name': 'lenovo', 'amount': '3'}, {'price': '10', 'name': 'chicken', 'amount': '3'}]

1.5 计算总价格,最终完整代码如下:

#总列表
li = []
#总价格
the_sum = 0
with open('a.txt',encoding='utf-8') as f:
for i in f:
#默认使用空格分割
i = i.strip().split()
#将字典追加到列表中
li.append({'name': i[0], 'price': i[1], 'amount': i[2]}) #遍历列表
for i in li:
#计算总价格(单价*个数)
the_sum += int(i['price']) * int(i['amount']) print(li)
print('总价钱为: {}'.format(the_sum))

执行输出:

[{'amount': '3', 'name': 'apple', 'price': '10'}, {'amount': '1', 'name': 'tesla', 'price': '100000'}, {'amount': '2', 'name': 'mac', 'price': '3000'}, {'amount': '3', 'name': 'lenovo', 'price': '30000'}, {'amount': '3', 'name': 'chicken', 'price': '10'}]
总价钱为: 196060

老师的代码:

li = []
the_sum = 0
name_list = ['name','price','amount','year']
with open('a.txt',encoding='utf-8') as f1:
for i in f1:
l2 = i.strip().split()
dic = {}
for j in range(len(l2)):
dic[name_list[j]] = l2[j]
li.append(dic)
#遍历列表
for i in li:
#计算总价格(单价*个数)
the_sum += int(i['price']) * int(i['amount']) print(li)
print('总价钱为: {}'.format(the_sum))

执行效果同上

第2题,老师讲过,直接贴代码:

import os
with open('log.txt',encoding='utf-8') as f1,\
open('log.bak',encoding='utf-8',mode='w') as f2:
for i in f1:
new_i = i.replace('alex', 'SB')
f2.write(new_i) os.remove('log.txt')
os.rename('log.bak','log.txt')

执行代码,查看文件内容如下:

SB是老男孩python发起人,创建人。
SB其实是人妖。
谁说SB是sb?
你们真逗,SB再牛逼,也掩饰不住资深屌丝的气质。

第3题,和第1题类似

3.1直接读取文件,并取出对应的值

with open('log.txt', encoding='utf-8') as f:
for i in f:
# 默认使用空格分割
i = i.strip().split()
#使用冒号切割,获取value
name = i[0].split(':')[1]
price = i[1].split(':')[1]
amount = i[2].split(':')[1]
year = i[3].split(':')[1]
print(name,price,amount,year)

执行输出:

apple 10 3 2012
tesla 100000 1 2013

3.2将取出的内容写入字典中,并追加到总列表里面

# 总列表
li = []
with open('log.txt', encoding='utf-8') as f:
for i in f:
# 默认使用空格分割
i = i.strip().split()
#使用冒号切割,获取value
name = i[0].split(':')[1]
price = i[1].split(':')[1]
amount = i[2].split(':')[1]
year = i[3].split(':')[1]
#将字典追加到列表中
li.append({'name':name, 'price': price, 'amount': amount,'year':year}) print(li)

执行输出:

[{'name': 'apple', 'price': '10', 'year': '2012', 'amount': '3'}, {'name': 'tesla', 'price': '100000', 'year': '2013', 'amount': '1'}]

3.3遍历总列表,计算总价钱,最终代码如下

# 总列表
li = []
# 总价钱
the_sum = 0
with open('log.txt', encoding='utf-8') as f:
for i in f:
# 默认使用空格分割
i = i.strip().split()
# 使用冒号切割,获取value
name = i[0].split(':')[1]
price = i[1].split(':')[1]
amount = i[2].split(':')[1]
year = i[3].split(':')[1]
# 将字典追加到列表中
li.append({'name': name, 'price': price, 'amount': amount, 'year': year}) # 遍历总列表
for i in li:
# 计算总价钱(单价*个数)
the_sum += int(i['price']) * int(i['amount']) print(li)
print('总价钱为: {}'.format(the_sum))

执行输出:

[{'year': '2012', 'amount': '3', 'price': '10', 'name': 'apple'}, {'year': '2013', 'amount': '1', 'price': '100000', 'name': 'tesla'}]
总价钱为: 100030

老师的代码:可扩展性强,不论是横排还是竖排增加数据,都是适用

l1 = []
the_sum = 0
with open('a1.txt',encoding='utf-8') as f1:
for i in f1:
li = i.strip().split()
dic = {}
for j in li:
#使用冒号切割字符串,转成列表
l2 = j.strip().split(':')
#添加字典,l2[0]表示key,l2[1] 表示value
dic[l2[0]] = l2[1]
#将字典追加到列表中
l1.append(dic) # 遍历总列表
for i in l1:
# 计算总价钱(单价*个数)
the_sum += int(i['price']) * int(i['amount']) print(l1)
print('总价钱为: {}'.format(the_sum))

  执行输出,效果同上。

第4题

4.1 先读取文件内容

with open('log.txt', encoding='utf-8') as f:
for i in f:
i = i.strip()
print(i)

执行输出:

序号 部门 人数 平均年龄 备注
1 python 30 26 单身狗
2 Linux 26 30 没对象
3 运营部 20 24 女生多

4.2 我需要第一行内容(序号 部门 人数 平均年龄 备注),作为标题栏,放入列表中

#行数
line_num = 0
with open('log.txt', encoding='utf-8') as f:
for i in f:
i = i.strip()
#行数加1
line_num += 1
#判断行数是否等于1
if (line_num == 1):
#去除空格,使用空格切割
title = i.strip().split()
#加入标题的列表中
title_bar = [title[0],title[1],title[2],title[3],title[4]] print(title_bar)

执行输出:

['序号', '部门', '人数', '平均年龄', '备注']

4.3 将(序号 部门 人数 平均年龄 备注)里面的内容提取出来

#行数
line_num = 0
with open('log.txt', encoding='utf-8') as f:
for i in f:
i = i.strip()
#行数加1
line_num += 1
#判断行数是否等于1
if (line_num == 1):
#去除空格,使用空格切割
title = i.strip().split()
#加入标题的列表中
title_bar = [title[0],title[1],title[2],title[3],title[4]]
else:
#切割数据
split_data = i.strip().split()
#序号
id = split_data[0]
#部门
department = split_data[1]
#人数
number = split_data[2]
#平均年龄
average_age = split_data[3]
#备注
remarks = split_data[4]
#打印结果
print(id,department,number,average_age,remarks)

执行输出:

1 python 30 26 单身狗
2 Linux 26 30 没对象
3 运营部 20 24 女生多

4.4将最后一行代码print改成字典输出

#行数
line_num = 0
li = []
with open('log.txt', encoding='utf-8') as f:
for i in f:
i = i.strip()
#行数加1
line_num += 1
#判断行数是否等于1
if (line_num == 1):
#去除空格,使用空格切割
title = i.strip().split()
#加入标题的列表中
title_bar = [title[0],title[1],title[2],title[3],title[4]]
else:
#切割数据
split_data = i.strip().split()
#序号
id = split_data[0]
#部门
department = split_data[1]
#人数
number = split_data[2]
#平均年龄
average_age = split_data[3]
#备注
remarks = split_data[4]
#打印结果
print({title_bar[0]:id,title_bar[1]:department,title_bar[2]:number,title_bar[3]:average_age,title_bar[4]:remarks})

执行输出:

{'人数': '30', '备注': '单身狗', '序号': '1', '平均年龄': '26', '部门': 'python'}
{'人数': '26', '备注': '没对象', '序号': '2', '平均年龄': '30', '部门': 'Linux'}
{'人数': '20', '备注': '女生多', '序号': '3', '平均年龄': '24', '部门': '运营部'}

4.5将打印的字典,添加到总列表中,最终代码如下

#行数
line_num = 0
#总列表
li = []
with open('log.txt', encoding='utf-8') as f:
for i in f:
i = i.strip()
#行数加1
line_num += 1
#判断行数是否等于1
if (line_num == 1):
#去除空格,使用空格切割
title = i.strip().split()
#加入标题的列表中
title_bar = [title[0],title[1],title[2],title[3],title[4]]
else:
#切割数据
split_data = i.strip().split()
#序号
id = split_data[0]
#部门
department = split_data[1]
#人数
number = split_data[2]
#平均年龄
average_age = split_data[3]
#备注
remarks = split_data[4]
#将字典添加到列表中
li.append({title_bar[0]:id,title_bar[1]:department,title_bar[2]:number,title_bar[3]:average_age,title_bar[4]:remarks}) print(li)

执行输出:

[{'备注': '单身狗', '平均年龄': '26', '人数': '30', '序号': '1', '部门': 'python'}, {'备注': '没对象', '平均年龄': '30', '人数': '26', '序号': '2', '部门': 'Linux'}, {'备注': '女生多', '平均年龄': '24', '人数': '20', '序号': '3', '部门': '运营部'}]

老师的代码:可扩展性强,不论是横排还是竖排增加数据,都是适用

l1 = []
with open('a2.txt',encoding='utf-8') as f1:
#读取第一行,去除空格,使用空格切割成列表
list_name = f1.readline().strip().split()
#从第二行开始读取,因为读取一行之后,光标自动移动到下面一行。
#所以for循环不会读取到第一行
for i in f1:
dic = {}
#去除空格,以空格切割成列表
i = i.strip().split()
#遍历i
for j in range(len(i)):
#添加字典, list_name[j]表示key, i[j]表示value,比如'序号': '1'
dic[list_name[j]] = i[j]
#添加到列表中
l1.append(dic) print(l1)

执行效果同上

python 全栈开发,Day8(文件操作)的更多相关文章

  1. python全栈开发-Day7 文件处理

    python全栈开发-Day7   文件处理 一 .文件操作 一 .介绍 计算机系统分为:计算机硬件,操作系统,应用程序三部分. 我们用python或其他语言编写的应用程序若想要把数据永久保存下来,必 ...

  2. Python全栈工程师(文件操作、编码)

    ParisGabriel                每天坚持手写  一天一篇  决定坚持几年 为了梦想为了信仰     Python人工智能从入门到精通 最近简直要死了 发烧感冒 喉咙痛..... ...

  3. python全栈开发day54-mysql库操作、表操作、数据类型、完整性约束

    一.昨日内容回顾 1.mysql的安装 1).解压文件 添加环境变量bin 2).初始化mysql生成数据data文件夹: mysqld --initialize-insecure 3).mysqld ...

  4. python全栈开发-Day8 函数基础

    python全栈开发-Day8 函数 一 .引子 1. 为何要用函数之不用函数的问题 #1.代码的组织结构不清晰,可读性差 #2.遇到重复的功能只能重复编写实现代码,代码冗余 #3.功能需要扩展时,需 ...

  5. python全栈开发day62-两表操作增删改查,外键,if else模板语法

    一.今日内容总结: day62 内容回顾: 1. django有关所有命令: pip install django==1.11.14 django-admin startproject 项目名称 cd ...

  6. Python 全栈开发八 文件处理

    一.基本流程 打开文件得到文件句柄 将文件句柄赋值给一个变量 通过文件句柄对文件进行操作 关闭文件 二.基本操作 1.文件句柄 f = open("a.txt",encoding= ...

  7. Python全栈开发day8

    一.python生成/迭代器 yiled生成数据 python迭代器, 访问数据(通过next一次一次去取) 二.反射 通过字符串的形式,导入模块 通过字符串的形式,到模块中,寻找指定的函数,并执行 ...

  8. python全栈开发_day8_文件的多种读写方式及游标

    一:文件的多种读写方式 主方式:w    r    a 从方式:t     b    + 了解方式:x    u 1)按t(按照字符进行操作): with open("data_1.txt& ...

  9. python全栈开发学习_内容目录及链接

    python全栈开发学习_day1_计算机五大组成部分及操作系统 python全栈开发学习_day2_语言种类及变量 python全栈开发_day3_数据类型,输入输出及运算符 python全栈开发_ ...

  10. Python全栈开发【面向对象进阶】

    Python全栈开发[面向对象进阶] 本节内容: isinstance(obj,cls)和issubclass(sub,super) 反射 __setattr__,__delattr__,__geta ...

随机推荐

  1. Java 基础生词表

    class [klɑːs] : 类 (计算机科学); public ['pʌblɪk] : 公众的; void [vɒɪd] : 无返回类型; main [meɪn] : 主要的; static [' ...

  2. 深入理解 BFC

    W3C 规范中 BFC的定义: 浮动元素和绝对定位元素,非块级盒子的块级容器(例如 inline-blocks, table-cells, 和 table-captions),以及overflow值不 ...

  3. Linux记录-Linux 企业运维人员最常用 150 个命令

    命令 功能说明 线上查询及帮助命令 (2 个) man 查看命令帮助,命令的词典,更复杂的还有 info,但不常用. help 查看 Linux 内置命令的帮助,比如 cd 命令. 文件和目录操作命令 ...

  4. Redis和Memcached对比【转】

    Redis和Memcached对比 这两年 Redis火得可以,Redis也常常被当作 Memcached的挑战者被提到桌面上来.关于Redis与Memcached的比较更是比比皆是.然而,Redis ...

  5. Java Calendar使用总结

    JavaCalendar 类时间操作,这也许是创建和管理日历最简单的一个方案,示范代码很简单. 演示了获取时间,日期时间的累加和累减,以及比较. 原文地址:blog.csdn.NET/joyous/a ...

  6. Java线程间和进程间通信

    1 线程与线程间通信 1.1 基本概念以及线程与进程之间的区别联系 关于进程和线程,首先从定义上理解就有所不同: 进程是具有一定独立功能的程序.它是系统进行资源分配和调度的一个独立单位,重点在系统调度 ...

  7. CodeForces - 348D Turtles(LGV)

    https://vjudge.net/problem/CodeForces-348D 题意 给一个m*n有障碍的图,求从左上角到右下角两条不相交路径的方案数. 分析 用LGV算法.从(1,1)-(n, ...

  8. cdqz2017-test8-Tree(点分树)

    n个点的带点权带边权的树,设点权为a[i],边权为b[i] 一棵树有n*(n-1)/2个点对, 定义这棵树的价值为任意两点对的(a[x]^a[y])*dis(x,y) 有m次修改一个点的点权的操作 输 ...

  9. ubuntu16.04.1下安装mysql

    版本信息 ubuntu版本:16.04.1 mysql-server版本:5.7.23 安装 先查看一下apt可获取的mysql版本 ubuntu@VM-0-4-ubuntu:~$ apt searc ...

  10. Mac下使用Wine安装PowerDesigner15

    下载: (链接: https://pan.baidu.com/s/1bpEYyIV 密码: 5ymj) 安装: 1.安装Wine 参考:http://www.cnblogs.com/EasonJim/ ...