2013-04-07 66 views
0

我的Caeser密碼在shell中用字符串交互工作,但是當我嘗試單獨執行加密和解密程序時,我遇到了問題,我不知道輸入不會被拆分成一個列表,但是我的加密函數中的if語句被繞過,並且默認爲未加密列表的else語句。任何建議感激。我使用Goldwasser書中的FileUtilities.py。該文件在第11章中的http://prenhall.com/goldwasser/sourcecode.zip處,但我認爲問題並非如此,但是誰知道。提前謝謝。Caeser從Python中的文件加密

#CaeserCipher.py 
class CaeserCipher: 

def __init__ (self, unencrypted="", encrypted=""): 
    self._plain = unencrypted 
    self._cipher = encrypted 
    self._encoded = "" 

def encrypt (self, plaintext): 
    self._plain = plaintext 
    plain_list = list(self._plain) 
    i = 0 
    final = [] 

    while (i <= len(plain_list)-1): 
     if plain_list[i] in plainset: 
      final.append(plainset[plain_list[i]]) 
     else: 
      final.append(plain_list[i]) 
     i+=1 
    self._encoded = ''.join(final) 
    return self._encoded 

def decrypt (self, ciphertext): 
    self._cipher = ciphertext 
    cipher_list = list(self._cipher) 
    i = 0 
    final = [] 
    while (i <= len(cipher_list)-1): 
     if cipher_list[i] in cipherset: 
      final.append(cipherset[cipher_list[i]]) 
     else: 
      final.append(cipher_list[i]) 
     i+=1 
    self._encoded = ''.join(final) 
    return self._encoded 

def writeEncrypted(self, outfile): 
    encoded_file = self._encoded 
    outfile.write('%s' %(encoded_file)) 

#encrypt.py 
from FileUtilities import openFileReadRobust, openFileWriteRobust 
from CaeserCipher import CaeserCipher 

caeser = CaeserCipher() 

source = openFileReadRobust() 
destination = openFileWriteRobust('encrypted.txt') 
caeser.encrypt(source) 
caeser.writeEncrypted(destination) 
source.close() 
destination.close() 
print 'Encryption completed.' 
+0

什麼是'plainset'(在你的'while'條件下)? – 2013-04-07 20:49:08

回答

0

這不是明顯,我認爲會有調用openFileReadRobust()後在任何source。我不知道openFileReadRobust()的規範,但它似乎不知道要打開哪個文件,除非有作爲參數給出的文件名,並且沒有一個。

因此,我懷疑source是空的,因此plain也是空的。

我建議打印出source,plaintextplain以確保它們的值符合您的預期。

另外,openFileReadRobust()函數對我來說似乎沒有什麼幫助,只要它能夠爲非感性參數值返回非感性值。我非常喜歡我的功能,在這種情況下立即拋出異常。

+0

他確實提到結果與輸入文件的內容相同。原來'source'不是空的,它只是一個文件對象,這段代碼不會意外拋出異常。檢查我的答案。 – dequis 2013-04-07 21:06:23

+0

你說得很對,OP確實提到了這一點。它讓我感到困惑,因爲有什麼東西被讀入程序中。 – Simon 2013-04-07 21:13:09

+0

是的,我也完全困惑,直到我決定將FileUtilities包含在我正在測試的代碼中而不是將其更改爲我自己的open()。read() – dequis 2013-04-07 21:18:41

3
caeser.encrypt(source) 

caeser.encrypt(source.read()) 

source是一個文件對象 - 事實上,這個代碼「工程」(由未加密的任何東西)是有趣的 - 原來你叫list()在源迭代前,將其變成文件中的行列表。 list(string)這是一個字符列表的結果,而不是通常的結果。因此,當它試圖加密每個字符時,它會找到一條與您設置的任何替換項不匹配的整行。

也像其他人指出的,你忘記了在代碼中包含plainset,但這並不重要。

一些有關您的代碼散記(可能是挑剔的你沒問,嘿)

  • 你typo'd「凱撒」
  • 您使用成語這是低效的蟒蛇(通常稱爲「不pythonic」),其中一些可能來自其他語言如C的經驗。
    • 那些while循環可能是for item in string: - 字符串已經像您嘗試轉換的字節列表一樣工作。
    • 寫入到outfile線可能只是outfile.write(self._encoded)
  • 這兩個功能都非常相似,幾乎是複製粘貼代碼。嘗試寫第三個功能共享兩者的功能,但有兩個「模式」,加密和解密。你可以使它通過cipher_list或plain_list工作,具體取決於模式,例如
  • 我知道你在做這個練習,但標準庫包括these functions這種替換。包括電池!

編輯:如果有人想知道這些文件的功能做的,爲什麼他們的工作,他們稱之爲raw_input() while循環中,直到有一個合適的文件返回。 openFileWriteRobust()有一個參數,該參數是用戶不輸入任何內容時的默認值。該代碼鏈接在OP帖子上。

+0

+1:好的斑點錯誤和出色的額外Python建議。 – Simon 2013-04-07 21:11:14

+0

謝謝.read()做到了。你很棒。至於你的其他建議,除了正確的拼寫凱撒之外,我會爲這個項目保持不偏不倚,並稱之爲包裝。再次感謝。 – 2013-04-08 00:57:57

+0

是的,有時甚至是「pythonic」或者不是隻是味道和次要優化的問題。但有時它會改善代碼的可維護性,特別是當我提到避免重複的代碼太相似時。只是將它作爲未來項目的建議 - 我可以理解這對代碼無關緊要。 (順便提一下,請記住接受一個答案!我對網站相當陌生,所以我會很感激它) – dequis 2013-04-09 01:19:53

1

幾點:

  • 使用上下文管理器(with)確保了正在讀或寫的文件後關閉。
  • 由於凱撒密碼是一個替代密碼,其中shift參數是關鍵,因此不需要單獨的成員函數encryptdecrypt:它們是相同的,但「否定」關鍵字。
  • writeEncrypted方法不過是文件寫入方法的包裝。所以班級實際上只有兩種方法,其中之一是__init__
  • 這意味着您可以輕鬆地將其替換爲單一功能。

考慮到這一點,你的代碼可以用這個代替;

import string 

def caesartable(txt, shift): 
    shift = int(shift) 
    if shift > 25 or shift < -25: 
     raise ValueError('illegal shift value') 
    az = string.ascii_lowercase 
    AZ = string.ascii_uppercase 
    eaz = az[-shift:]+az[:-shift] 
    eAZ = AZ[-shift:]+AZ[:-shift] 
    tt = string.maketrans(az + AZ, eaz + eAZ) 
    return tt 

enc = caesartable(3) # for example. decrypt would be caesartable(-3) 
with open('plain.txt') as inf: 
    txt = inf.read() 
with open('encrypted.txt', 'w+') as outf: 
    outf.write(txt.translate(enc)) 

如果您使用的是13的轉變,您可以使用內置的rot13編碼器來代替。