<p>Python中有两种主要的字符串类型:表示二进制数据的bytestrings(字节序列)和表示人类可读文本的Unicode字符串(Unicode码位序列)。把一个转换成另一个很简单(☯)公司名称:</p>
<pre><code>unicode_text = bytestring.decode(character_encoding)
bytestring = unicode_text.encode(character_encoding)
</code></pre>
<p>如果以二进制模式打开文件,例如<code>'rb'</code>,则<code>file.read()</code>返回bytestring(<code>bytes</code>类型):</p>
^{pr2}$
<hr/>
<p>有几种方法可用于对字节进行分类:</p>
<ul>
<li><p>字符串方法,如<code>bytes.isdigit()</code>:</p>
<pre><code>>>> b'1'.isdigit()
True
</code></pre></li>
<li><p>字符串常量,如<code>string.printable</code></p>
<pre><code>>>> import string
>>> b'!' in string.printable.encode()
True
</code></pre></li>
<li><p>正则表达式,如<code>\d</code></p>
<pre><code>>>> import re
>>> bool(re.match(br'\d+$', b'123'))
True
</code></pre></li>
<li><p><code>curses.ascii</code>模块中的分类函数,例如<code>curses.ascii.isprint()</code></p>
<pre><code>>>> from curses import ascii
>>> bytearray(filter(ascii.isprint, b'123'))
bytearray(b'123')
</code></pre></li>
</ul>
<p><code>bytearray</code>是一个可变的字节序列-与bytestring不同,您可以就地更改它,例如,每三个大写字节都要小写:</p>
<pre><code>>>> import string
>>> a = bytearray(b'ABCDEF_')
>>> uppercase = string.ascii_uppercase.encode()
>>> a[::3] = [b | 0b0100000 if b in uppercase else b
... for b in a[::3]]
>>> a
bytearray(b'aBCdEF_')
</code></pre>
<p>注意:<code>b'ad'</code>是小写的,但是<code>b'_'</code>保持不变。在</p>
<hr/>
<p>要想就地修改二进制文件,可以使用<code>mmap</code>模块,例如,在<code>'file'</code>中每隔一行将第4列小写:</p>
<pre><code>#!/usr/bin/env python3
import mmap
import string
uppercase = string.ascii_uppercase.encode()
ncolumn = 3 # select 4th column
with open('file', 'r+b') as file, \
mmap.mmap(file.fileno(), 0, access=mmap.ACCESS_WRITE) as mm:
while True:
mm.readline() # ignore every other line
pos = mm.tell() # remember current position
if not mm.readline(): # EOF
break
if mm[pos + ncolumn] in uppercase:
mm[pos + ncolumn] |= 0b0100000 # lowercase
</code></pre>
<p>注意:python2和3api在本例中有所不同。代码使用python3。在</p>
<h3>输入</h3>
<pre><code>ABCDE1
FGHIJ
ABCDE
FGHI
</code></pre>
<h3>输出</h3>
<pre><code>ABCDE1
FGHiJ
ABCDE
FGHi
</code></pre>
<p>注意:第4列在第2行和第4行变为小写。在</p>
<hr/>
<p>通常,如果要更改文件:读取文件,将修改写入临时文件,成功后将临时文件移到原始文件的位置:</p>
<pre><code>#!/usr/bin/env python3
import os
import string
from tempfile import NamedTemporaryFile
caesar_shift = 3
filename = 'file'
def caesar_bytes(plaintext, shift, alphabet=string.ascii_lowercase.encode()):
shifted_alphabet = alphabet[shift:] + alphabet[:shift]
return plaintext.translate(plaintext.maketrans(alphabet, shifted_alphabet))
dest_dir = os.path.dirname(filename)
chunksize = 1 << 15
with open(filename, 'rb') as file, \
NamedTemporaryFile('wb', dir=dest_dir, delete=False) as tmp_file:
while True: # encrypt
chunk = file.read(chunksize)
if not chunk: # EOF
break
tmp_file.write(caesar_bytes(chunk, caesar_shift))
os.replace(tmp_file.name, filename)
</code></pre>
<h3>输入</h3>
<pre><code>abc
def
ABC
DEF
</code></pre>
<h3>输出</h3>
<pre><code>def
ghi
ABC
DEF
</code></pre>
<p>要转换回输出,请设置<code>caesar_shift = -3</code>。在</p>