ordenar - leer columna de un archivo en python
¿Cómo cambiar los bytes en un archivo? (2)
Para abrir un archivo en modo binario, usa el open("filena.me", "rb")
. Nunca utilicé el comando personalmente, pero eso debería proporcionarle la información que necesita.
Estoy haciendo un programa de encriptación y necesito abrir el archivo en modo binario para acceder a caracteres que no sean ascii y no imprimibles, necesito verificar si el carácter de un archivo es letra, número, símbolo o carácter no imprimible. Eso significa que tengo que verificar 1 por 1 si los bytes (cuando se decodifican en ascii) coinciden con cualquiera de estos caracteres:
{^9,dzEV=Q4ciT+/s};fnq3BFh% #2!k7>YSU<GyD/I]|OC_e.W0M~ua-jR5lv1wA`@8t*xr''K"[P)&b:g$p(mX6Ho?JNZL
Creo que podría codificar estos caracteres arriba en binario y luego compararlos con bytes. No se como hacer esto.
PD: Perdón por malos malentendidos en inglés y binarios. (Espero que sepas a qué me refiero con bytes, quiero decir personajes en modo binario como este):
/x01/x00/x9a/x9c/x18/x00
Hay dos tipos principales de cadenas en Python: cadenas de bytes (una secuencia de bytes) que representan datos binarios y cadenas Unicode (una secuencia de puntos de código Unicode) que representan texto legible por humanos. Es simple convertir uno en otro (☯):
unicode_text = bytestring.decode(character_encoding)
bytestring = unicode_text.encode(character_encoding)
Si abre un archivo en modo binario, por ejemplo, ''rb''
entonces file.read()
devuelve una cadena de bytes
(tipo de bytes
):
>>> b''A'' == b''/x41'' == chr(0b1000001).encode()
True
Hay varios métodos que se pueden usar para clasificar bytes:
métodos de cadena como
bytes.isdigit()
:>>> b''1''.isdigit() True
constantes de cadena como
string.printable
>>> import string >>> b''!'' in string.printable.encode() True
expresiones regulares como
/d
>>> import re >>> bool(re.match(br''/d+$'', b''123'')) True
funciones de clasificación en el módulo
curses.ascii
p. ej.,curses.ascii.isprint()
>>> from curses import ascii >>> bytearray(filter(ascii.isprint, b''123'')) bytearray(b''123'')
bytearray
es una secuencia mutable de bytes: a diferencia de una cadena de bytes, puede cambiarla in situ, por ejemplo, para minúsculas cada 3er byte que esté en mayúsculas:
>>> 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_'')
Aviso: b''ad''
son minúsculas, pero b''_''
sigue siendo el mismo.
Para modificar un archivo binario en el lugar, puede usar el módulo mmap
, por ejemplo, para minúsculas de la cuarta columna en cada línea en ''file''
:
#!/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
Nota: las API de Python 2 y 3 difieren en este caso. El código usa Python 3.
Entrada
ABCDE1
FGHIJ
ABCDE
FGHI
Salida
ABCDE1
FGHiJ
ABCDE
FGHi
Aviso: la cuarta columna se convirtió en minúsculas en las líneas 2 y 4.
Normalmente, si desea cambiar un archivo: lee desde el archivo, escribe modificaciones en un archivo temporal y, en caso de éxito, mueve el archivo temporal en el lugar del archivo original:
#!/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)
Entrada
abc
def
ABC
DEF
Salida
def
ghi
ABC
DEF
Para convertir la salida, configure caesar_shift = -3
.