2012-01-11 167 views
15

我們有一個數據錄入人員,他在Windows上以UTF-16編碼,並想要使用utf-8並刪除物料清單。 utf-8轉換工作,但BOM仍然存在。我將如何刪除這個?這是我目前有:轉換utf-16 - > utf-8並刪除物料清單

batch_3={'src':'/Users/jt/src','dest':'/Users/jt/dest/'} 
batches=[batch_3] 

for b in batches: 
    s_files=os.listdir(b['src']) 
    for file_name in s_files: 
    ff_name = os.path.join(b['src'], file_name) 
    if (os.path.isfile(ff_name) and ff_name.endswith('.json')): 
     print ff_name 
     target_file_name=os.path.join(b['dest'], file_name) 
     BLOCKSIZE = 1048576 
     with codecs.open(ff_name, "r", "utf-16-le") as source_file: 
     with codecs.open(target_file_name, "w+", "utf-8") as target_file: 
      while True: 
      contents = source_file.read(BLOCKSIZE) 
      if not contents: 
       break 
      target_file.write(contents) 

如果我進制打印-C我看到:

Wed Jan 11$ hexdump -C svy-m-317.json 
00000000 ef bb bf 7b 0d 0a 20 20 20 20 22 6e 61 6d 65 22 |...{.. "name"| 
00000010 3a 22 53 61 76 6f 72 79 20 4d 61 6c 69 62 75 2d |:"Savory Malibu-| 
生成的文件中

。我如何刪除BOM?

THX

回答

19

只需使用str.decodestr.encode

with open(ff_name, 'rb') as source_file: 
    with open(target_file_name, 'w+b') as dest_file: 
    contents = source_file.read() 
    dest_file.write(contents.decode('utf-16').encode('utf-8')) 

str.decode會得到你擺脫BOM的(和推斷的存儲方式)。

+0

酷 - 效果很好,你知道如何添加CRLF - > LF轉換閱讀中的設施? thx如果可以幫助 – timpone 2012-01-11 22:45:31

+0

如果您正在處理大型文件,那麼這種方法(將整個文件存儲在內存中兩次)效率不高。 – 2015-01-07 04:35:03

28

這是UTF-16LEUTF-16

  • UTF-16LE之間的差別是小端沒有一個BOM
  • UTF-16是大或小尾數一個BOM

所以,當你使用UTF-16LE,BOM只是文本的一部分。改爲使用UTF-16,以便BOM自動刪除。 UTF-16LEUTF-16BE之所以存在,是因爲人們可以在沒有BOM的情況下攜帶「正確編碼」文本,這不適用於您。

請注意當您使用一種編碼進行編碼並使用另一種編碼進行解碼時會發生什麼情況。 (UTF-16自動檢測UTF-16LE有時,並非總是如此。)

>>> u'Hello, world'.encode('UTF-16LE') 
'H\x00e\x00l\x00l\x00o\x00,\x00 \x00w\x00o\x00r\x00l\x00d\x00' 
>>> u'Hello, world'.encode('UTF-16') 
'\xff\xfeH\x00e\x00l\x00l\x00o\x00,\x00 \x00w\x00o\x00r\x00l\x00d\x00' 
^^^^^^^^ (BOM) 

>>> u'Hello, world'.encode('UTF-16LE').decode('UTF-16') 
u'Hello, world' 
>>> u'Hello, world'.encode('UTF-16').decode('UTF-16LE') 
u'\ufeffHello, world' 
    ^^^^ (BOM) 

或者你也可以在Shell做到這一點:

for x in * ; do iconv -f UTF-16 -t UTF-8 <"$x" | dos2unix >"$x.tmp" && mv "$x.tmp" "$x"; done