Python write模式導致的bug

今天遇到一個因爲寫文件模式不正確導致的一個bug。因爲這個bug很難被發現,所以我覺得有必要將這一個bug記錄下來,往後再有使用write()函數的時候,就得小心,究竟是模式爲"w",還是"wb"呢。

簡單說一下問題。有一個文件有很多行,我需要讀取每一行,然後將每一行的內容寫到一個文本文件中,然後再通過hex_to_blob.py將文本文件的內容轉爲二進制文件。最後對這個二進制文件再進行處理。需求看似不復雜,一眼就能看明白。但是最後的結果證明自己給自己挖了一個大坑。

我們首先看一下這個最初的文件,文件內容如下:

17844620002270008040FF010081DF02010381F40207FBE8040E03F0081FE7E01038007C207BCFD840E07DF081FEFBE100
17844620002270008040FF010081DF02010381F40207FBE8040E03F0081FE7E01038007C207C10D840E07DF081FEFBE100
17844620002270008040FF010081DF02010381F40207FBE8040E03F0081FE7E01038007C207F80F840E07DF081FEFBE100
17844620002270008040FF010081DF02010381F40207FBE8040E03F0081FE7E01038007C207F80F840E369D081F3D3A100
17844620002270008040FF010081DF02010381F40207FBE8040E03F0081FE7E01038007C207F80F840E3EBD081F4D7A100
178446249007389C0020103FC0402077C08040E07D0081FEFA010380FC0207F9F8040E001E081FB03C10381CF8207EB9F040
文件有兩萬多行,這個只是最初的6行,總之這個文件的每一行都是一些十六進制數的組合。

最後的結果是兩萬個文件中有23個文件的結果是錯誤的。究竟是哪個地方導致這23個文件,也就是這兩萬多行中的某23行文件不對呢?這裏先給出結果,錯誤原因就是在將每一行文件轉爲二進制後,將其寫入文件時用的是'w',而不是‘wb’。可能你會問,爲什麼別的行沒有問題,就這23行會有問題呢。問題就在於這23行文件有回車字符(carriage return CR)。

我們看一下出問題的一行,十六進制內容如下:

178447A4100513821C0207F408040EF010081C0FA0103F7F4020701E8040FEBF0081CA4B6103FC07C2070AAD840FF7DF0800

然後再看一下轉換爲二進制後的文件,這裏爲了直觀,用了notepad++的hex-editor插件。

atgqa@atgqa-5:~/fengxi$ od -t x1 input.oamd
0000000 17 84 47 a4 10 05 13 82 1c 02 07 f4 08 04 0e f0
0000020 10 08 1c 0f a0 10 3f 7f 40 20 70 1e 80 40 fe bf
0000040 00 81 ca 4b 61 03 fc 07 c2 07 0d 0a ad 84 0f f7
0000060 df 08 00
0000062
然後再看直接用hex_to_blob.py將十六進制文件轉換並直接重定向到另一個文件,而不是通過write函數將其寫入。再用beyond compare軟件對兩個文件進行比較,以下是比較的結果。

我們可以發現,通過write()函數寫進來的比通過重定向">"寫進去的多了一個"0D"符合。而"0D"在十六進制中表示回車,即CR,'\r'符號。爲什麼會多出這麼一個"0D"符號來呢?後來證明是因爲通過write()函數寫入時,mode爲'w',因爲是Windows的換行符爲"\r\n",在以文本形式寫入的時候,它默認將"\n"前添加了一個"\r"符號。恰恰就是這多出來的一個'r'文件導致最後的十六進制數多了一,從而導致了錯誤。如果在用write()函數寫入時將mode設爲‘wb’就能避免這樣的錯誤。





發佈了83 篇原創文章 · 獲贊 38 · 訪問量 31萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章