master
/ 5.2.5 文件遍历.ipynb

5.2.5 文件遍历.ipynb @master

341084b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
d487d71
341084b
 
 
d487d71
 
 
341084b
 
 
 
d487d71
341084b
 
 
 
 
d487d71
341084b
 
 
 
 
 
 
 
 
 
 
 
 
d487d71
341084b
 
 
 
 
 
 
 
d487d71
341084b
 
 
 
 
 
 
 
d487d71
341084b
 
 
 
 
 
 
 
d487d71
341084b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
d487d71
341084b
 
 
d487d71
341084b
 
 
 
 
 
d487d71
341084b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
d487d71
341084b
d487d71
 
 
 
 
 
 
 
 
 
 
 
 
341084b
 
 
 
 
 
d487d71
341084b
 
 
 
 
d487d71
341084b
 
 
 
 
 
 
 
 
 
 
d487d71
341084b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
d487d71
341084b
 
 
 
 
 
 
 
 
 
 
 
 
d487d71
341084b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
d487d71
341084b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
d487d71
341084b
 
 
 
 
 
 
 
 
 
 
d487d71
341084b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
d487d71
341084b
 
 
 
 
 
 
 
 
 
 
d487d71
341084b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 5.8 遍历文本文件"
   ]
  },
  {
   "cell_type": "raw",
   "metadata": {},
   "source": [
    "作者:赵广辉,vasp@qq.com\n",
    "本教程版权归属于武汉理工大学赵广辉所有,仅限用于学校教学用途,未经许可,严禁用于培训、出版等除学校教学以外的任何用途。\n",
    "教学应用以及任何基于本教程的修改均应保留此段文字。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "[Who Moved My Cheese.txt](images/ch5/Who Moved My Cheese.txt)  \n",
    "\n",
    "[8.1 静夜思.txt](images/ch5/8.1 静夜思.txt)"
   ]
  },
  {
   "cell_type": "raw",
   "metadata": {},
   "source": [
    "静夜思\n",
    "床前明月光,疑是地上霜。\n",
    "举头望明月,低头思故乡。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "文本文件的内容除了我们看到的文本信息外,还有一些不可见字符,例如,在每行末会有一个换行和回车符。  \n",
    "行末常见的符号有CR/LF  \n",
    "LF是Line Feed的缩写,符号是\\n,ASCII值是10;  \n",
    "CR是Carriage Return的缩写,符号是\\r,ASCII值是13;  \n",
    "Unix/Linux/Mac系统下面,一般只用LF  \n",
    "Windows系统下面经常同时使用两个符号,CRLF,有时也只用LF。\n",
    "\n",
    "这两种符号在python中都可以用字符串的str.strip()方法去除,下面统称为换行符。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<img src=\"images/ch5/4.png\" width=\"400\"><br />\n",
    "<img src=\"images/ch5/5.png\" width=\"400\">"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "知识扩展:"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n",
    "LF:换行\n",
    "LF(Line Feed)代表“换行”,换行符(转义序列 \\n)  \n",
    "这个字符代表一行文本的结束,在 Linux 和 Mac 上,这相当于新文本行的开始。  \n",
    "\n",
    "CR:回车\n",
    "CR(Carriage Return)代表回车(转义序列\\r)  \n",
    "将光标移动到当前行的开头。\n",
    "\n",
    "打字机和回车(CR)\n",
    "将一张纸固定在称为托架的机械卷上,为设备送入一张纸。每次击键时,打字机都会使用墨水在您的纸张上打印字母,将笔架向左移动以确保键入的下一个字母会出现在前一个字母的右侧。\n",
    "\n",
    "当然,一旦当前行的空间用完,打字员就需要向下移动到纸张上的下一行。这是通过旋转滑架将纸张相对于打字机的“笔”向上移动一定距离来完成的。但是还需要重置托架(carriage),以便键入的下一个字符将与纸张的左侧边距对齐。换句话说,打字员需要某种方式将托架返回到其起始位置。而这正是回车的工作:一个金属杆连接到托架的左侧,当推动时,将托架返回到其起始位置。\n",
    "\n",
    "电传打字机和回车换行(CRLF)\n",
    "进入 20 世纪初,出现了电传打字机。基本上,它的工作方式与手动打字机相同,除了不是打印到物理纸上,而是通过传输器通过物理电线或无线电波将消息发送给接收方。\n",
    "\n",
    "虽然打印方式不同,但是同样需要使用换行符 (LF) 和回车符 (CR),而且这些设备需要同时使用换行符 (LF) 和回车符 (CR) 以允许打字员从下一行文本的开头输入。毕竟手动打字机就是这样工作的,只是它没有任何“字符”的概念,因为它是一种机械操作的设备。\n",
    "\n",
    "我们可以将 LF 和 CR 视为代表水平或垂直方向上的独立运动,而不是同时代表两者,这样更容易将其形象化。为了实现这个功能,电传打字机在一些最早的操作系统中设定了 CRLF 行尾的标准,比如流行的 MS-DOS。将CR 代表“回车”——CR 控制字符将打印头(“回车”)返回到第 0 列,而无需推进纸张。 LF 代表“换行”——LF 控制字符在不移动打印头的情况下将纸张前进一行。因此,如果您想将打印头返回到第 0 列(准备打印下一行)并推进纸张(以便在新纸上打印),则需要 CR 和 LF。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 1. 遍历输出文件"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "open()函数可以打开文件并创建一个可遍历的文件对象,可用赋值方式命名:\n",
    "f = open()  \n",
    "也可用内容管理器with...as为之命别名:  \n",
    "with open() as f:  \n",
    "两个方法都可以打开文件创建文件对象。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "f = open('images/ch5/8.1 静夜思.txt')   # f 只是为创建的文件对象起的名字,无特殊意义\n",
    "for a in f:   # 遍历文件对象,每次循环获得文件的一行,包括行末的符号\n",
    "    print(a)   # 逐行输出"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# with ...as 语句需要以冒号结尾\n",
    "\n",
    "with open('images/ch5/8.1 静夜思.txt') as fr:  # fr 只是为创建的文件对象起的名字,可理解为可读文件对象\n",
    "    for line in fr:   # 遍历文件对象,每次循环获得文件的一行,包括行末的符号\n",
    "        print(line)   # 逐行输出"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "两种方法都可以逐行输出文件内容,但注意到文件末尾有一个换行符:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print('静夜思')    # 输出静夜思后换行"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print()            # 输出一个换行"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print('\\n')        # 输出两个换行  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print('静夜思\\n')  # '静夜思\\n'相当于'静夜思'+'\\n',输出静夜思后换行再换行,即多输出一个空行"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2. 读文件时去除换行符"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2.1 字符串的str.strip()方法"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "f = open('images/ch5/Who Moved My Cheese.txt')   # f 只是为创建的文件对象起的名字,无特殊意义\n",
    "for line in f:   # 遍历文件对象,每次循环获得文件的一行,包括行末的符号\n",
    "    print(line.strip())   # 逐行输出"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# with ...as 语句需要以冒号结尾\n",
    "\n",
    "with open('/data/bigfiles/8704a285-deaf-40f3-8694-f2036f0604de.txt') as fr:  # fr 只是为创建的文件对象起的名字,可理解为可读文件对象\n",
    "    for line in fr:   # 遍历文件对象,每次循环获得文件的一行,包括行末的符号\n",
    "        print(line.strip())   # 逐行输出"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2.2 用字符串的str.replace()方法替换 "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "静夜思\n",
      "床前明月光,疑是地上霜。\n",
      "举头望明月,低头思故乡。\n"
     ]
    }
   ],
   "source": [
    "f = open('images/ch5/8.1 静夜思.txt')   # f 只是为创建的文件对象起的名字,无特殊意义\n",
    "for line in f:   # 遍历文件对象,每次循环获得文件的一行,包括行末的符号\n",
    "    print(line.replace('\\n',''))   # 将字符串中的换行符替换为空字符串"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "with open('/data/bigfiles/8704a285-deaf-40f3-8694-f2036f0604de.txt') as fr:  # fr 只是为创建的文件对象起的名字,可理解为可读文件对象\n",
    "    for line in fr:   # 遍历文件对象,每次循环获得文件的一行,包括行末的符号\n",
    "        print(line.replace(',','-'))   # 逐行输出"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2.3 定义函数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def read_txt(filename):  # 传入的带路径文件名\n",
    "    \"\"\"接收一个文件名为参数,读取文件中的数据并逐行输出。\"\"\"\n",
    "    with open(filename, 'r', encoding='utf-8') as poem:  # poem为创建的文件对象名\n",
    "        for line in poem:\n",
    "            print(line.strip())\n",
    "\n",
    "\n",
    "if __name__ == '__main__':\n",
    "    file = '/data/bigfiles/8704a285-deaf-40f3-8694-f2036f0604de.txt'  # 文件名定义变量,使函数具有通用性,传不同的文件名就可以读不同的文件\n",
    "    read_txt(file)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 3 读文件为一个字符串"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def read_txt(filename):  # 传入的带路径文件名\n",
    "    \"\"\"接收一个文件名为参数,读取文件中的数据为一个字符串,返回这个字符串。\"\"\"\n",
    "    with open(filename, 'r', encoding='utf-8') as poem:  # poem为创建的文件对象名\n",
    "        text = ''  # 空字符串\n",
    "        for line in poem:\n",
    "            text = text + line  # 当前行拼接到字符串上,保留原来的换行符\n",
    "    return text\n",
    "\n",
    "\n",
    "if __name__ == '__main__':\n",
    "    file = 'images/ch5/8.1 静夜思.txt'  # 文件名定义变量,使函数具有通用性,传不同的文件名就可以读不同的文件\n",
    "    print(read_txt(file))\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<font face='楷体' color='red' size=5> 练一练1 </font>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "修改3的程序,拼接为字符串时去掉每个行末的换行符,观察输出的结果为分析换行符的作用。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 补充你的代码\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<font face='楷体' color='red' size=5> 练一练2 </font>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "模仿3的程序,编程读取文件“Who Moved My Cheese.txt”,逐行输出。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def read_txt(filename):  # 传入的带路径文件名\n",
    "    \"\"\"接收一个文件名为参数,读取文件中的数据为一个字符串,返回这个字符串。\"\"\"\n",
    "    # 补充你的代码\n",
    "    \n",
    "    \n",
    "\n",
    "\n",
    "if __name__ == '__main__':\n",
    "    file = 'images/ch5/Who Moved My Cheese.txt'  # 文件名定义变量,使函数具有通用性,传不同的文件名就可以读不同的文件\n",
    "    print(read_txt(file))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<font face='楷体' color='red' size=5> 练一练3 </font>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "观察练一练2的输出,发现若每行要么全是中文,要么该行全是英文或数字;  \n",
    "根据这个特点,将中文和英文分别输出\n",
    "提示:  \n",
    "非中文字符x的ord(x)值均不小于 256\n",
    "一般来说每行只判断第1个字符就可以知道是中文还是英文\n",
    "但本文档中,有些中文的行是英文符号开头,这些行也会被输出,思考一下如何解决这个问题?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def read_txt(filename):  # 传入的带路径文件名\n",
    "    \"\"\"接收一个文件名为参数,读取文件中的英文为一个字符串,返回这个字符串。\"\"\"\n",
    "    # 补充你的代码\n",
    "    \n",
    "    \n",
    "\n",
    "\n",
    "if __name__ == '__main__':\n",
    "    file = 'images/ch5/Who Moved My Cheese.txt'  # 文件名定义变量,使函数具有通用性,传不同的文件名就可以读不同的文件\n",
    "    print(read_txt(file))\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def read_txt(filename):  # 传入的带路径文件名\n",
    "    \"\"\"接收一个文件名为参数,读取文件中的中文为一个字符串,返回这个字符串。\"\"\"\n",
    "    # 补充你的代码\n",
    "    \n",
    "    \n",
    "\n",
    "\n",
    "if __name__ == '__main__':\n",
    "    file = '/data/bigfiles/863798db-6d6b-4bfa-842d-d6294266be31.txt'  # 文件名定义变量,使函数具有通用性,传不同的文件名就可以读不同的文件\n",
    "    print(read_txt(file))\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}