web-dev-qa-db-ja.com

FTPを使用すると、ファイルエンコーディングを変更できますか?

PHP curlを使用して多数のWebページをダウンロードするWebアプリケーションを開発しています。次に、diffを使用して、ファイルが毎日変化するときにファイルを比較します。

数週間前に、一見同一のファイルがdiffによって異なるものとしてフラグ付けされている問題を報告しました。 https://stackoverflow.com/questions/42552239/different-versions-of-diff-giving -mixed-results-when-comparing-2-identical-fil

上記に対する答えは、diff-wフラグと共に使用された場合、空白を無視するというものでした。

しかし、私は別の問題に気づきました。比較しているファイルの1つをダウンロードし、FTPクライアントを介して再アップロード(上書き)すると、出力が変わります。

例:file1.htmlfile2.htmldiff file1.html file2.htmlと比較すると、次のような出力が得られます。

12159,12161c12159,12161
<   
< 
< 
---
>   
> 
> 
12163,12172c12163,12172
< 
< 
< 
< 
< 
< 
< 
< 
< 
< 
---

ただし、file2.htmlをデスクトップにダウンロードし、FTP経由で再アップロードすると、diff -wフラグなし まったく違いがない、つまり、ファイルが同一であると言っています。

file -bi file2.htmlを使用してファイルのエンコードを確認しようとしましたが、FTPを介したアップロードの前後で同じことが報告されています。エンコードはtext/html; charset=us-asciiです

エンコーディングに違いがなく、ファイルの内容が変更されていない場合、FTPを介してファイルを再アップロードするとどうなりますか? FileZillaとNetbeansを使用して試しました。

MacOS Sierraをローカルで使用しており、リモートサーバーはApache 2/PHP 7/centOSです。

4
Andy

おそらく行末に違いが見られます。 (「バイナリモード」ではなく)ASCII /テキストモードでファイルを転送する場合、ほとんどのFTPクライアントは、転送先のOSに行末を変換/正規化します。

クラシックMac OS(9.x以前)では、行末文字は単に\r(ASCII 13)ですが、Mac OS Xではこれは\n(ASCII 10)に変更され、Linuxでは\n(ASCII 10)です。 Windowsは\r\nまたはASCII 13 + 10です。 (Macの修正について@ 8bittreeに感謝します。)

そのため、1つのOSから別のOSにダウンロードするとき、すべての行末は静かに変換されます。アップロード時に変換は元に戻されます。 (ただし、 @ Joshua's answer に記載されているように、ファイルの文字エンコーディングとファイルに含まれる特定の文字によっては、破損する可能性があります。)行末のミッシュマッシュがある場合は、 FTPソフトウェアは、行末を正規化/修正しています。これは、ファイルをダウンロードしてからアップロードすると、元々サーバー上にあったものとは「異なる」ファイルになる理由を説明します(つまり、「修正済み」です)。または、以前にミス変換されたファイルを元に戻していますか?ただし、EOL変換はそれほどインテリジェントではない可能性があり、二重に区切られた行または行方不明の改行(つまり、わずかに破損している)で終わる可能性があります。

デフォルトでは、ほとんどのFTPクライアントは「自動」転送モードに設定されており、ASCII /テキストモードで転送する既知のファイルタイプのリストがあります。他の種類のファイルは、「バイナリ」モードで転送されます。同じOS間で転送する場合、または変換せずに転送する場合は、「バイナリ」モードのみを使用する必要があります。

通常、ソース/ターゲットオペレーティングシステムがテキストファイルの表現に非常に異なる文字エンコーディングを使用しない限り、FTPソフトウェアは転送されたファイルの文字エンコーディングを変更しません。 @KeithDaviesがコメントで指摘したように、そのような例の1つは、 EBCDIC を使用するメインフレームからローカルWindowsマシンにダウンロードする場合です。 EBCDICはWindowsでネイティブにサポートされていないため、これをASCIIに変換するには変換が必要です。繰り返しますが、「バイナリモード」で転送すると、このような変換が回避されます。 (文字エンコーディングに関する注記については@KeithDaviesに感謝します。)

上記に対する答えは、diffが-wフラグとともに使用された場合、空白を無視するというものでした。

はい、行末(空白)は比較で無視されます。

比較しているファイルの1つをダウンロードし、FTPクライアントを介して再アップロード(上書き)すると、出力が変わります。

元のファイルに行末が混在している場合、ASCIIモードでダウンロードして再アップロードすると、一貫性のない行末を「修正」できます。したがって、ファイルは「同じ」になりました。

6
MrWhite

はい。 ASCIIモードでUTF-16ファイルを転送しないでください。ここでデータの破損を避けるためにバイナリモードを使用します。

FTPが\ r\nを\ nに変換すると、単一の文字characterまたはシーケンスㄍਰまたは同じクラスの他の多くの文字が含まれている場合、ファイルの残りの部分が破損します。

これはインテリジェントな変換ではなく、逆変換も存在し、さらに多くのケースをカバーしていることに注意してください。

3
Joshua

はい、ftpはエンコーディングの変更を行います。データは、送信側ホストのストレージデバイスから受信側ホストのストレージデバイスに転送されます。 2つのシステムのデータストレージ表現は異なるため、多くの場合、データに対して特定の変換を実行する必要があります。たとえば、NVT-ASCIIには、システムごとに異なるデータストレージ表現があります。 PDP-10は通常、NVT-ASCIIを5つの7ビットASCII文字として保存し、36ビットWordで左寄せします。 360はNVT-ASCIIを8ビットEBCDICコードとして保存します。 Multicsは、NVT-ASCIIを36ビットWordの4つの9ビット文字として保存します。異なるシステム間でテキストを送信するときは、文字を標準のNVT-ASCII表現に変換することが望ましい場合があります。送信サイトと受信サイトは、標準表現とその内部表現の間で必要な変換を実行する必要があります(詳細については、 RFC 765 のデータ表現とストレージセクションを参照してください)。

2
Pramod_Para

これについて私が受け入れた答えは正しいですが、私はこの情報を使用して何が起こっているかを解決する方法についていくつかのメモを追加しています。

質問では、簡単にするためにfile1.htmlfile2.htmlを使用しています。実際、file1.htmlは、過去にダウンロードしたWebページの「マスター」コピーを表します。 file2.htmlは、Webページコンテンツの最新のダウンロードです。アプリケーションの目的は、ファイルのマスターコピーを最新バージョン(diff file1.html file2.html)と比較することです。

実際のアプリケーションにはこれらのファイルが数百あります。

マスターファイルを作成するときに行ったのは、file1.html--同等のすべてのセットをデスクトップにダウンロードすることでした。次に、FileZillaを介してサーバーの「マスター」ディレクトリに再アップロードしました。これはしばらく前(3月1日頃)に行われたもので、何が起こったのかがわかるまでは考えもしませんでした。

MacからFileZillaを介してアップロードすると、受け入れられた回答に記載されているように、改行文字に変更が加えられました。。具体的には\rを使用していますが、Linux(centOS)Webサーバーでは\nを使用しています。

だから今私がdiff file1.html file2.htmlしたとき、それはファイルが異なると言っていた。これは、この時点でファイル間に2つの異なる改行文字があるためです:\r in file1.htmlおよび\n in file2.html

その後、私はfile2.htmlをダウンロードし、FileZillaを使用してデスクトップからサーバーに再アップロード(上書き)していました。 これが元の質問を投稿したポイントです。

答えが示唆するように、file2.htmlがアップロードされるまで、文字エンコードの違いがあります。この時点で、ファイルは両方とも同じプロセスを経ているため同じになります。私の観点からは、単にfile2.htmlをアップロードするだけで問題が「修正」されたかのようでしたが、理由を理解できませんでした。

https://stackoverflow.com/questions/3569997/view-line-endings-in-a-text-file を使用して、どのファイルがどの改行文字を使用しているかを判断できました

問題全体に対する私の解決策は、FTPを介して何もダウンロードしないことです(これは単にファイルを調べるために使用されていたためです)。ファイルの「マスター」ディレクトリを作成するときにサーバーでcpを使用します。これはすべてLinux上で行われるため、改行文字に違いはありません。各ファイルのコピーは、常に\nを使用していることを意味します

基本的にこの問題の解決策は、ファイル間で改行文字を同じにする必要があることです。そうしないと、diffは異なるものとしてフラグを立てますが、それが出力することはあなたを示すのに役立ちませんwhatその違いは、これらの文字はファイルが表示されたときに「見えない」ためです(上記のリンクのようなものを使用してエディターで表示しない限り)。

2
Andy