4

ディレクトリにファイルのリストを作成する PHP スクリプトがありますが、PHP は英語のファイル名しか認識できず、ロシア語やアジア言語などの他の言語のファイル名を完全に無視します。

多くの努力の後、私は自分のために働くことができる唯一の解決策を見つけました-ファイルの名前をUTF8に変更するPythonスクリプトを使用して、その後PHPスクリプトがそれらを処理できるようにします。

(PHP がファイルの処理を終了した後、ファイルの名前を英語に変更します。UTF8 では保持しません)。

次の python スクリプトを使用しました。これは正常に動作します。

import sys
import os
import glob
import ntpath
from random import randint

for infile in glob.glob( os.path.join('C:\\MyFiles', u'*') ):
    if os.path.isfile(infile):
      infile_utf8 = infile.encode('utf8')
      os.rename(infile, infile_utf8)

問題は、すでに UTF8 になっているファイル名も変換することです。ファイル名が既に UTF8 である場合に備えて、変換をスキップする方法が必要です。

私はこのpythonスクリプトを試していました:

for infile in glob.glob( os.path.join('C:\\MyFiles', u'*') ):
    if os.path.isfile(infile):
      try:
        infile.decode('UTF-8', 'strict')
      except UnicodeDecodeError:
        infile_utf8 = infile.encode('utf8')
        os.rename(infile, infile_utf8)    

ただし、ファイル名が既に utf8 の場合、致命的なエラーが発生します。

UnicodeDecodeError: 'ascii' codec can't decode characters in position 18-20
ordinal not in range(128)

別の方法も試しましたが、うまくいきませんでした:

for infile in glob.glob( os.path.join('C:\\MyFiles', u'*') ):
    if os.path.isfile(infile):
      try:
        tmpstr = str(infile)
      except UnicodeDecodeError:
        infile_utf8 = infile.encode('utf8')
        os.rename(infile, infile_utf8)      

以前とまったく同じエラーが発生しました。

何か案は?

Python は私にとって非常に新しいものであり、単純なスクリプトでさえデバッグするのは大変な作業です。そのため、明示的な回答 (つまりコード) を書いてください。私には、うまくいくかどうかわからない一般的なアイデアをテストする能力がありません。ありがとう。

ファイル名の例:

 hello.txt
 你好.txt
 안녕하세요.html
 chào.doc
4

2 に答える 2

3

Python のすべての UTF-8 の問題について、PyCon 2012 でNed Batchelder ( http://nedbatchelder.com/text/unipain.html ) による"Pragmatic Unicode"を 36 分間視聴することを強くお勧めします。このプレゼンテーションの多くは、実際には Python 固有のものではありませんが、 Unicode 文字列UTF-8 でエンコードされたバイトの違いなど、重要なことを理解するのに役立ちます...

私がこのビデオをあなたに勧める理由は (私が多くの友人に勧めたように)、あなたのコードには、デコードを試みて失敗しdecodeencode場合などの矛盾が含まれているためです。そのようなメソッドは同じオブジェクトには適用できません! Python2 では構文的には可能ですが、意味がありません。Python 3 では、 と の区別によりbytesstr物事がより明確になります。

オブジェクトは次の形式でエンコードstrできます。bytes

>>> a = 'a'
>>> type(a)
<class 'str'>
>>> a.encode
<built-in method encode of str object at 0x7f1f6b842c00>
>>> a.decode
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'str' object has no attribute 'decode'

...bytesオブジェクトは次のようにデコードstrできます:

>>> b = b'b'
>>> type(b)
<class 'bytes'>
>>> b.decode
<built-in method decode of bytes object at 0x7f1f6b79ddc8>
>>> b.encode
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'bytes' object has no attribute 'encode'

ファイル名の操作に関する質問に戻ると、答える必要があるトリッキーな質問は、「ファイル名のエンコードは何ですか」です。言語は関係ありません。エンコーディングだけです。

于 2013-10-03T07:32:38.307 に答える
3

用語を混乱させ、間違った仮定をしていると思います。私の知る限り、PHP は任意のエンコーディング タイプのファイル名を開くことができます。PHP はエンコーディング タイプについて非常に無知です。

UTF-8 != 英語として実現したいことを正確に明確にしておらず、例の外部ファイル名はさまざまな方法でエンコードできますが、ASCII 英語では決してエンコードできません! 既存の UTF-8 ファイルがどのように見えるか、および非 UTF-8 ファイルとは何かを説明できますか?

さらに混乱を招くことに、Windows では、ファイル名は透過的に UTF-16 として保存されます。したがって、ファイル名を UTF-8 にエンコードしようとしないでください。代わりに、Unicode 文字列を使用して、Python が適切な変換を行えるようにする必要があります。(UTF-16 でエンコードしないでください!)

質問をさらに明確にしてください。

更新

PHPに関する問題を理解しました。http://evertpot.com/filesystem-encoding-and-php/は、非ラテン文字が PHP+Windows で問題になることを示しています。Windows 1252 文字セットの文字で作成されたファイルのみを表示して開くことができるようです。

あなたの課題は、ファイル名を Windows 1252 互換に変換することです。質問で述べたように、既に互換性のあるファイルの名前を変更しないことが理想的です。私はあなたの試みを次のように作り直しました:

import os
from glob import glob
import shutil
import urllib

files = glob(u'*.txt')
for my_file in files:
    try:
        print "File %s" % my_file
    except UnicodeEncodeError:
        print "File (escaped): %s" % my_file.encode("unicode_escape")
    new_name = my_file
    try:
        my_file.encode("cp1252" , "strict")
        print "    Name unchanged. Copying anyway"
    except UnicodeEncodeError:
        print "    Can not convert to cp1252"
        utf_8_name = my_file.encode("UTF-8")
        new_name = urllib.quote(utf_8_name )
        print "    New name: (%% encoded): %s" % new_name
    
    shutil.copy2(my_file, os.path.join("fixed", new_name))

壊す:

  1. ファイル名を印刷します。デフォルトでは、Windows シェルはローカル DOS コード ページでのみ結果を表示します。たとえば、私のシェルは表示できますü.txtが、€.txtとして表示され?.txtます。したがって、正しく印刷できないため、Python が例外をスローすることに注意する必要があります。このコードは、Unicode バージョンを出力しようとしますが、代わりに Unicode コード ポイント エスケープを出力することに頼っています。

  2. 文字列を Windows-1252 としてエンコードしてみてください。これが機能する場合、ファイル名は問題ありません

  3. それ以外の場合: ファイル名を UTF-8 に変換してから、パーセント エンコードします。このように、ファイル名は一意のままであり、PHP でこの手順を逆にすることができます。

  4. ファイルを新しい/検証済みファイルにコピーします。

たとえば、你好.txt は %E4%BD%A0%E5%A5%BD.txt になります。

于 2013-10-07T20:45:43.787 に答える