4

FileUpload サーバー コントロールを使用して、以前に保存された (Web ページとして、フィルター処理された) HTML ドキュメントを MS Word からアップロードしています。文字セットは windows-1252 です。ドキュメントには、通常の引用符だけでなくスマート引用符 (curly) も含まれています。また、よく見ると通常の TAB や SPACE 以外の文字である (どうやら) いくつかの空白スペースがあります。

StreamReader でファイルの内容をキャプチャすると、これらの特殊文字は疑問符に変換されます。デフォルトのエンコードがUTF-8で、ファイルがUnicodeであるためだと思います。

私は先に進み、Unicode エンコーディングを使用して StreamReader を作成し、不要な文字をすべて正しい文字 (stackoverflow で実際に見つけたコード) に置き換えました。これはうまくいくようです....文字列をUTF-8に変換してasp:literalに表示することはできません。コードはそこにあり、動作するはずです....しかし、出力(ConvertToASCII)は判読できません。

以下をご覧ください。

    protected void btnUpload_Click(object sender, EventArgs e)
    {
        StreamReader sreader;
        if (uplSOWDoc.HasFile)
        {
            try
            {
                if (uplSOWDoc.PostedFile.ContentType == "text/html" || uplSOWDoc.PostedFile.ContentType == "text/plain")
                {
                    sreader = new StreamReader(uplSOWDoc.FileContent, Encoding.Unicode);
                    string sowText = sreader.ReadToEnd();
                    sowLiteral.Text = ConvertToASCII(sowText);
                    lblUploadResults.Text = "File loaded successfully.";
                }
                else
                    lblUploadResults.Text = "Upload failed. Just text or html files are allowed.";
            }
            catch(Exception ex)
            {
                lblUploadResults.Text = ex.Message;
            }
        }
    }

    private string ConvertToASCII(string source)
    {
        if (source.IndexOf('\u2013') > -1) source = source.Replace('\u2013', '-');
        if (source.IndexOf('\u2014') > -1) source = source.Replace('\u2014', '-');
        if (source.IndexOf('\u2015') > -1) source = source.Replace('\u2015', '-');
        if (source.IndexOf('\u2017') > -1) source = source.Replace('\u2017', '_');
        if (source.IndexOf('\u2018') > -1) source = source.Replace('\u2018', '\'');
        if (source.IndexOf('\u2019') > -1) source = source.Replace('\u2019', '\'');
        if (source.IndexOf('\u201a') > -1) source = source.Replace('\u201a', ',');
        if (source.IndexOf('\u201b') > -1) source = source.Replace('\u201b', '\'');
        if (source.IndexOf('\u201c') > -1) source = source.Replace('\u201c', '\"');
        if (source.IndexOf('\u201d') > -1) source = source.Replace('\u201d', '\"');
        if (source.IndexOf('\u201e') > -1) source = source.Replace('\u201e', '\"');
        if (source.IndexOf('\u2026') > -1) source = source.Replace("\u2026", "...");
        if (source.IndexOf('\u2032') > -1) source = source.Replace('\u2032', '\'');
        if (source.IndexOf('\u2033') > -1) source = source.Replace('\u2033', '\"');


        byte[] sourceBytes = Encoding.Unicode.GetBytes(source);
        byte[] targetBytes = Encoding.Convert(Encoding.Unicode, Encoding.ASCII, sourceBytes);
        char[] asciiChars = new char[Encoding.ASCII.GetCharCount(targetBytes, 0, targetBytes.Length)];
        Encoding.ASCII.GetChars(targetBytes, 0, targetBytes.Length, asciiChars, 0);

        string result = new string(asciiChars);

        return result;

    }

また、前に言ったように、単語 doc に番号付けされたインデントがある場所に対応しているように見える「透明な」文字がいくつかあります。それらのユニコード値をキャプチャしてそれらを置き換える方法がわかりません....ヒント、教えてください。

よろしくお願いします!

4

2 に答える 2

6
sreader = new StreamReader(uplSOWDoc.FileContent, Encoding.Unicode);

おめでとう、あなたは「Encoding.Unicode」に噛まれた 100 万人目のコーダーです。

「Unicode エンコーディング」のようなものはありません。Unicode は文字セットであり、さまざまなエンコーディングがあります。

Encoding.Unicode は、実際には特定のエンコーディング UTF-16LE であり、文字は UTF-16 の「コード単位」としてエンコードされ、次に各 16 ビット コード単位がリトル エンディアン順にバイトに書き込まれます。これは、Windows NT のネイティブなインメモリ Unicode 文字列形式ですが、ファイルの読み取りまたは書き込みに使用することはほとんどありません。1 ユニットあたり 2 バイトのエンコーディングであるため、ASCII と互換性がなく、ストレージやネットワーク上ではあまり効率的ではありません。

最近では、UTF-8 が Unicode テキストに使用されるより一般的なエンコーディングです。しかし、Microsoft による UTF-16LE の「Unicode」という誤った命名は、「Unicode をサポート」したいだけのユーザーを混乱させ、騙し続けています。Encoding.Unicode は非 ASCII 互換エンコーディングであるため、ASCII スーパーセット エンコーディング (UTF-8 や 1252 西ヨーロッパ言語のような Windows デフォルト コード ページなど) でファイルを読み込もうとすると、すべてが非常に読みにくくなります。非ASCII文字のみ。

この場合、ファイルが保存されているエンコーディングは Windows コード ページ 1252 です。

sreader= new StreamReader(uplSOWDoc.FileContent, Encoding.GetEncoding(1252));

私はそれを残しておきます。わざわざ「ASCII に変換」しようとする必要はありません。これらのスマート クォートは完全に適切な文字であり、他の Unicode 文字と同様にサポートする必要があります。スマート クォートの表示に問題がある場合は、おそらく他のすべての非 ASCII 文字も壊している可能性があります。いくつかの一般的なケースで問題を回避しようとするのではなく、その原因となっている問題を修正することをお勧めします。

于 2011-03-17T01:23:35.810 に答える
6

MSDN の StreamReader によると:

StreamReader オブジェクトは、ストリームの最初の 3 バイトを調べてエンコードを検出しようとします。ファイルが適切なバイト オーダー マークで始まる場合、UTF-8、リトル エンディアン Unicode、およびビッグ エンディアン Unicode テキストを自動的に認識します。それ以外の場合は、ユーザー提供のエンコーディングが使用されます。

したがって、アップロードしたファイルの文字セットがwindows-1252の場合、次の行:

sreader = new StreamReader(uplSOWDoc.FileContent, Encoding.Unicode);

ファイルの内容は Unicode でエンコードされていないため、正しくありません。代わりに、次を使用します。

sreader = new StreamReader(uplSOWDoc.FileContent, 
                  Encoding.GetEncoding("Windows-1252"), true);

ここで、最後のブール値パラメーターは BOM を検出するためのものです。

于 2011-03-15T22:21:12.937 に答える