C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

ログ内検索
  • キーワードを複数指定する場合は 半角スペース で区切ってください。
  • 検索条件は、(AND)=[A かつ B] (OR)=[A または B] となっています。
  • [返信]をクリックすると返信ページへ移動します。
キーワード/ 検索条件 /
検索範囲/ 強調表示/ ON (自動リンクOFF)
結果表示件数/ 記事No検索/ ON
大文字と小文字を区別する

全過去ログを検索

<< 0 | 1 >>
■43450  Re[1]: VSのアイコンがおかしい
□投稿者/ nori -(2009/11/10(Tue) 21:26:38)
    一旦プロジェクトから除外して、再登録してみては如何ですか?
記事No.43432 のレス /過去ログ74より / 関連記事表示
削除チェック/

■53821  Re[2]: DataTableの主キー更新
□投稿者/ 逃亡者 -(2010/09/28(Tue) 00:04:36)
    No53819 (すなふきぬ さん) に返信
    > ■No53815 (逃亡者 さん) に返信
    >>C# 3.0開発となります。
    >>
    >>一つ質問させていただいておりますが、別質問としてもう一つさせてください。
    >>
    >>TableAdapterでFillしたものから主キーになるものでWhere句を指定して1レコードをDataTableの中を更新したいんですけど、
    >>どうかいたらいいのでしょうか
    >
    > VS2008の場合は、以下の手順でTableAdapterを作成します。
    >
    > 1.ソリューションエクスプローラーでDataSetを開く
    > 2.ツールボックスからTableAdapterをDataSetデザイナにドラッグする
    > 3.TableAdapter構成ウィザードで、「SQLステートメントを使用する」を選択する
    > 4.Where句を含むSQLを作成し、TableAdapterを完成させる
    >
    > この手順で作成したTableAdapterならWhere句を考慮した更新ができます。
    > 慣れてくるとデザイナを使用せず、手書きとかで作成するのも有りです。

    ご回答ありがとうございます。
    Where句を考慮したというのは、これはどういう風につかえるのでしょうか。
    DataAdapter.Fill(ds)とやるのでしょうか
    Where句の条件はどこでしていすればいいのでしょうか
記事No.53815 のレス /過去ログ90より / 関連記事表示
削除チェック/

■53822  Re[3]: DataTableの主キー更新
□投稿者/ 逃亡者 -(2010/09/28(Tue) 00:06:29)
    No53821 (逃亡者 さん) に返信
    > ■No53819 (すなふきぬ さん) に返信
    >>■No53815 (逃亡者 さん) に返信
    > >>C# 3.0開発となります。
    > >>
    > >>一つ質問させていただいておりますが、別質問としてもう一つさせてください。
    > >>
    > >>TableAdapterでFillしたものから主キーになるものでWhere句を指定して1レコードをDataTableの中を更新したいんですけど、
    > >>どうかいたらいいのでしょうか
    >>
    >>VS2008の場合は、以下の手順でTableAdapterを作成します。
    >>
    >>1.ソリューションエクスプローラーでDataSetを開く
    >>2.ツールボックスからTableAdapterをDataSetデザイナにドラッグする
    >>3.TableAdapter構成ウィザードで、「SQLステートメントを使用する」を選択する
    >>4.Where句を含むSQLを作成し、TableAdapterを完成させる
    >>
    >>この手順で作成したTableAdapterならWhere句を考慮した更新ができます。
    >>慣れてくるとデザイナを使用せず、手書きとかで作成するのも有りです。
    >
    > ご回答ありがとうございます。
    > Where句を考慮したというのは、これはどういう風につかえるのでしょうか。
    > DataAdapter.Fill(ds)とやるのでしょうか
    > Where句の条件はどこでしていすればいいのでしょうか
    >

    なにもしてないFillをみるとWhere句がないのでそこにWhere句を入れるというのは
    わかりましたが、どうやってそれにWhere句の条件をしていするのかがわかりません
    よろしくお願いします
記事No.53815 のレス /過去ログ90より / 関連記事表示
削除チェック/

■68997  フォームをポップアップ時にアクティブにさせない方法
□投稿者/ Kat -(2013/11/28(Thu) 09:51:43)

    分類:[VB.NET/VB2005 以降] 

    VisualStdio2005 使用言語はVBです。

    NotifyIconを使用し、タスクトレイに常駐させるシステムがあります。
    30分毎にとあるデータベースの中を見てデータが存在した場合に
    お知らせフォームをポップアップさせているのですが、
    ポップアップ時にポップアップフォームがアクティブになってしまい
    Word等で日本語入力途中の文字が確定されてしまいます。
    表示処理の中で「Me.Activate()」の記述があり消してみても駄目でした。

    ポップアップフォームを最前面に表示し、アクティブにさせない方法はあるのでしょうか?
    ご存知の方いらっしゃいましたらアドバイス宜しくお願い致します。

    '現在の記述
    Private Sub Form_Load
    Me.Close()
    End Sub

    Private Sub FormClosing
    Me.Visible = False
    Timer1.Enabled = True 'タイマースタート
    End Sub

    Private Sub Timer1_Tick
    Dim iRet As Integer

    iRet = DataChk 'データがあるかチェック(0以外はデータ有り)

    'データがあった場合フォームを表示
    If iRet <> 0 Then
    Timer1.Enabled = False 'タイマーストップ

    Me.Visible = True
    Me.Activate() 'ここを消しても駄目でした
    End If
    End Sub
親記事 /過去ログ117より / 関連記事表示
削除チェック/

■85599  間違いを教えてください。
□投稿者/ 夜叉丸 -(2017/11/09(Thu) 16:57:18)

    分類:[.NET 全般] 


    byte[] valuearray;

    string strvalue = "";
    for (int isnum = 0; isnum < sstream.ToArray().Length; isnum++)
    strvalue += (char)valuearray [isnum];

    ↓↓↓↓↓
    逆変換したのですが

    byte[] valuearray = new byte[strvalue .Length];
    for (int inum = 0; inum < strvalue.Length; inum++)
    valuearray[inum] = (byte)strvalue[inum];

    元のデータと差異が生じています。
    どうしてでしょうか?
    どうすればよいのでしょうか?
親記事 /過去ログ146より / 関連記事表示
削除チェック/

■85600  Re[1]: 間違いを教えてください。
□投稿者/ 本醸造 -(2017/11/09(Thu) 18:11:29)
記事No.85599 のレス /過去ログ146より / 関連記事表示
削除チェック/

■85608  Re[1]: 間違いを教えてください。
□投稿者/ Jitta -(2017/11/09(Thu) 23:10:29)
    No85599 (夜叉丸 さん) に返信
    >
    > byte[] valuearray;
    >
    > string strvalue = "";
    > for (int isnum = 0; isnum < sstream.ToArray().Length; isnum++)
    > strvalue += (char)valuearray [isnum];
    >
    > ↓↓↓↓↓
    > 逆変換したのですが
    >
    > byte[] valuearray = new byte[strvalue .Length];
    > for (int inum = 0; inum < strvalue.Length; inum++)
    > valuearray[inum] = (byte)strvalue[inum];
    >
    > 元のデータと差異が生じています。
    > どうしてでしょうか?
    > どうすればよいのでしょうか?
    >

    ん?
    valuearray が20こ配列として、
    全部の値が0だったら、
    strvalueはどうなるんだ?
記事No.85599 のレス /過去ログ146より / 関連記事表示
削除チェック/

■85609  Re[1]: 間違いを教えてください。
□投稿者/ Azulean -(2017/11/09(Thu) 23:42:38)
    2017/11/09(Thu) 23:45:38 編集(投稿者)

    No85599 (夜叉丸 さん) に返信
    > string strvalue = "";
    > for (int isnum = 0; isnum < sstream.ToArray().Length; isnum++)
    > strvalue += (char)valuearray [isnum];

    なぜ、string に入れるのでしょうか。
    string は文字の集合であり、文字ではない byte 型を無理矢理変換して入れるようなものではありませんよ。
    byte の可変長配列が欲しいのなら、List<byte> の方が良いでしょう。

    // なお、char は 2 バイトです。

    > 逆変換したのですが

    元の strvalue そのままなのか、どこかを経由したのかは明らかにしておいた方が良いと思います。
    byte を無理矢理変換した string なので、経由した内容次第ではデータが化けることもあると予想されるため。

    > 元のデータと差異が生じています。
    > どうしてでしょうか?

    データが化けて、255 を超える値があるとか、0 を下回る値があるとか。
    あるいは、0 が終端文字と誤解されて途切れているとか。

    > どうすればよいのでしょうか?

    個人的に思うのは、string を使うのをやめるべきでしょうね。
    なぜこんな処理を書いているのか、目的・背景・理由を明らかにしてもらった方が良いでしょう。


    No85608 (Jitta さん) に返信
    > valuearray が20こ配列として、
    > 全部の値が0だったら、
    > strvalueはどうなるんだ?

    \0 が 20 個入った string になります。
    .NET の string はヌル文字終端ではなく、長さ管理なので。
記事No.85599 のレス /過去ログ146より / 関連記事表示
削除チェック/

■85610  Re[2]: 間違いを教えてください。
□投稿者/ 夜叉丸 -(2017/11/10(Fri) 08:28:03)
    文字列にして、INI ファイルに Key=Value の
    Value として登録するために
    関数を2つ作りました。
    
    byte[] の状態まではうまく変換できたのですが、
    String にすると変換できずにエラーメッセージが出てきたので
    byte[] → string か、byte[] → dynamic のどちらかで
    何かがおかしいのかと思ったのです。
    現状では Value に DataTable型 のデータを指定しています。
    
    
    private string DynamicToString(dynamic Value)
    {
    	// dynamic → byte[]
    	MemoryStream sstream = new MemoryStream();
    	IFormatter formatter = new BinaryFormatter();
    	formatter.Serialize(sstream, Value);
    
    	// byte[] → string
    	string strvalue = "";
    	for (int isnum = 0; isnum < sstream.ToArray().Length; isnum++) strvalue += (char)sstream.ToArray()[isnum];
    
    	return (strvalue);
    }
    
    private dynamic StringToDynamic(string Value)
    {
    	try
    	{
    		if (Value == "") return (null);
    
    		// string → byte[]
    		byte[] valuearray = new byte[Value.Length];
    		for (int inum = 0; inum < Value.Length; inum++) valuearray[inum] = (byte)Value[inum];
    
    		// byte[] → dynamic
    		MemoryStream dstream = new MemoryStream(valuearray);
    		IFormatter formatter = new BinaryFormatter();
    		return (formatter.Deserialize(dstream));
    	}
    	catch(Exception ex)
    	{
    		MessageBox.Show(ex.Message);
    		return (null);
    	}
    }
    
    
    
記事No.85599 のレス /過去ログ146より / 関連記事表示
削除チェック/

■85611  Re[3]: 間違いを教えてください。
□投稿者/ 夜叉丸 -(2017/11/10(Fri) 08:41:47)
    ちなみに表示されるエラーメッセージは以下のメッセージです。

    「バイナリストリーム'46'に、有効なBinaryHeaderが含まれていません。
    シリアル化と逆シリアル化の途中で、無効なストリームまたは
    オブジェクトのバージョン変更が発生した可能性があります。」

    また、今テスト的に変換しようとしているデータは以下のような文字列になっています。
    DataTable で 列は Start, End で 1行目に それぞれ "A1", "B1" を入れたものです。

    "\0\u0001\0\0\0&yuml;&yuml;&yuml;&yuml;\u0001\0\0\0\0\0\0\0\f\u0002\0\0\0NSystem.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089\u0005\u0001\0\0\0\u0015System.Data.DataTable\u0003\0\0\0\u0019DataTable.RemotingVersion\tXmlSchema\vXmlDiffGram\u0003\u0001\u0001\u000eSystem.Version\u0002\0\0\0\t\u0003\0\0\0\u0006\u0004\0\0\0&Uacute;\u0005<?xml version=\"1.0\" encoding=\"utf-16\"?>\r\n<xs:schema xmlns=\"\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\r\n <xs:element name=\"Table1\">\r\n <xs:complexType>\r\n <xs:sequence>\r\n <xs:element name=\"START\" type=\"xs:string\" msdata:targetNamespace=\"\" minOccurs=\"0\" />\r\n <xs:element name=\"END\" type=\"xs:string\" msdata:targetNamespace=\"\" minOccurs=\"0\" />\r\n </xs:sequence>\r\n </xs:complexType>\r\n </xs:element>\r\n <xs:element name=\"tmpDataSet\" msdata:IsDataSet=\"true\" msdata:MainDataTable=\"Table1\" msdata:UseCurrentLocale=\"true\">\r\n <xs:complexType>\r\n <xs:choice minOccurs=\"0\" maxOccurs=\"unbounded\" />\r\n </xs:complexType>\r\n </xs:element>\r\n</xs:schema>\u0006\u0005\0\0\0&Atilde;\u0002<diffgr:diffgram xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\" xmlns:diffgr=\"urn:schemas-microsoft-com:xml-diffgram-v1\">\r\n <tmpDataSet>\r\n <Table1 diffgr:id=\"Table11\" msdata:rowOrder=\"0\" diffgr:hasChanges=\"inserted\">\r\n <START>A1</START>\r\n <END>B1</END>\r\n </Table1>\r\n </tmpDataSet>\r\n</diffgr:diffgram>\u0004\u0003\0\0\0\u000eSystem.Version\u0004\0\0\0\u0006_Major\u0006_Minor\u0006_Build\t_Revision\0\0\0\0\b\b\b\b\u0002\0\0\0\0\0\0\0&yuml;&yuml;&yuml;&yuml;&yuml;&yuml;&yuml;&yuml;\v"
記事No.85599 のレス /過去ログ146より / 関連記事表示
削除チェック/

■85612  Re[4]: 間違いを教えてください。
□投稿者/ 夜叉丸 -(2017/11/10(Fri) 08:57:20)
    なぜ、byte[] string の相互変換ができないのかがわからないので
    教えてください。

    ひょっとしたらたまたまかもしれませんけど
    List<string> や String などは普通に変換できましたし
    問題は起こりませんでした。
    今のところ DataTable だけがエラー発生します。


    逃げ道としては今のところ対応するために
    byte [A][B][C] → string '414243'
    として16進表示文字列にするしかないかと考えていますが、
    他にもっといい案があれば教えて下さい。
記事No.85599 のレス /過去ログ146より / 関連記事表示
削除チェック/

■85613  Re[5]: 間違いを教えてください。
□投稿者/ 夜叉丸 -(2017/11/10(Fri) 09:40:55)
    以下のように変更するととりあえずは動作するようになりましたが、
    文字サイズが2倍になっちゃいますし、
    入力されているデータの中身は全く分からくなりました。

    byte[] string は何が原因で使えないんでしょうか?


    string strvalue = "";
    for (int isnum = 0; isnum < sstream.ToArray().Length; isnum++) strvalue += ((char)sstream.ToArray()[isnum]).ToString();
    ↓↓↓↓↓
    string strvalue = "";
    for (int isnum = 0; isnum < sstream.ToArray().Length; isnum++) strvalue += (sstream.ToArray()[isnum]).ToString("X2");



    byte[] valuearray = new byte[Value.Length];
    for (int inum = 0; inum < Value.Length; inum++) valuearray[inum] = (byte)Value[inum];
    ↓↓↓↓↓
    int inum = 0;
    byte[] valuearray = new byte[Value.Length / 2];
    for (; inum < valuearray.Length; inum++) valuearray[inum] = (byte)Convert.ToInt32(Value.Substring(inum * 2, 2), 16);
記事No.85599 のレス /過去ログ146より / 関連記事表示
削除チェック/

■85616  Re[5]: 間違いを教えてください。
□投稿者/ 魔界の仮面弁士 -(2017/11/10(Fri) 12:04:11)
    2017/11/10(Fri) 12:06:01 編集(投稿者)

    No85612 (夜叉丸 さん) に返信
    > なぜ、byte[] string の相互変換ができないのかがわからないので
    > 教えてください。

    Azulean さんも書かれていますが、念のために確認。
    char/Char は「16 bit(2 バイト)長」のデータで、
    byte/Byte は「8 bit(1 バイト)長」のデータですが、
    その点の認識に差異はありますか?

    そして
     char a1 = 'a';
     char a1 = '\u0061';
     char a1 = (char)0x61;
     char a1 = (char)97;
    はいずれも同じ意味です。

    -----

    たとえば、まずこんなデータがあったとします。

    char a1 = '\u0061'; // Latin Small Letter A
    char a2 = '\u03B1'; // Greek Small Letter Alpha
    char a3 = '\uff41'; // Fullwidth Latin Small Letter A
    string str = new string(new char[] { a1, a2, a3 });


    データ内容が分かりやすくなるよう、上記は意図的に
    16 進数コードで表記していますが、要するに、
     string str = "aαa";
    を回りくどく書いているだけです。


    さて、上記の 3 文字(str 変数)を byte[] 配列にした場合、
    どのようなバイナリに変換されることを期待しておられますか?



    (1) UCS-2 あるいは UTF-16 バイナリ相当の 6 バイト
      61-00-B1-03-41-FF

    (2) UTF-16BE バイナリ相当の 6 バイト
      00-61-03-B1-FF-41

    (3) UTF-8 バイナリ相当の 6 バイト
      61-CE-B1-EF-BD-81

    (4) CP932 あるいは Shift_JIS バイナリ相当の 5 バイト
      61-83-BF-82-81

    (5) EUC-JP バイナリ相当の 5 バイト
      61-A6-C1-A3-E1

    (6) ISO-2022-JP バイナリ相当の 11 バイト
      61-1B-24-42-26-41-23-61-1B-28-42


    たとえば (1) を望むなら、
     string str = "aαa";
     byte[] bin = System.Text.Encoding.Unicode.GetBytes(str);
    で変換でき、それを復元するために
     string result = System.Text.Encoding.Unicode.GetString(bin);
    と書けます。
記事No.85599 のレス /過去ログ146より / 関連記事表示
削除チェック/

■85617  Re[3]: 間違いを教えてください。
□投稿者/ Azulean -(2017/11/10(Fri) 12:32:27)
    No85610 (夜叉丸 さん) に返信
    > 文字列にして、INI ファイルに Key=Value の
    > Value として登録するために
    > 関数を2つ作りました。

    BinaryFormatter でシリアライズした内容を ini ファイルに書き出すシナリオという理解で問題ないですか?

    BinaryFormatter の出力で得られる byte 配列をそのまま char 配列、そして string に変換すると、表示できない文字になる部分があります。
    たとえば、0 は扱う場所によっては文字列の終端とみなされます。
    ini ファイルを扱う API も 0 を終端とみなしますので途切れるでしょうね。
    その他、文字コードの都合で ini ファイルで扱えないバイトがあるので、ini に書き出すなら char にキャストするのではなく、何らかのエンコード(符号化)が必要です。
    16 進数にするのは1つの手ですし、BASE64 を使うのも選択肢になるかもしれません。(= が大丈夫かは不安ですが)

    なお、符号化によって、中身がパッとみてわからなくなる点は避けられません。ini ファイルを使う以上は仕方ないかと。
記事No.85599 のレス /過去ログ146より / 関連記事表示
削除チェック/

■85618  Re[4]: 間違いを教えてください。
□投稿者/ 魔界の仮面弁士 -(2017/11/10(Fri) 13:29:40)
    No85617 (Azulean さん) に返信
    > BASE64 を使うのも選択肢になるかもしれません。(= が大丈夫かは不安ですが)

    BASE64 の = が現われるのはパディング部だけなので、
    パディングが不要な実装、たとえば base64url が向いているかもしれません。
    https://ja.wikipedia.org/wiki/Base64


    // 保存したいバイナリ
    byte[] inBinary = { 0x96, 0xe9, 0x8d, 0xb3, 0x8a, 0xdb };

    // ini ファイルで保存可能な base64url 文字列に変換
    string iniString = inBinary.ToIniString();

    // 元のバイナリに復元
    byte[] outBinary = iniString.ToIniBinary();
     



    static class Base64Extensions
    {
     public static string ToIniString(this byte[] bin)
     {
      return Convert.ToBase64String(bin).TrimEnd('=')
       .Replace('/', '_').Replace('+', '-');
     }
     
     public static byte[] ToIniBinary(this string str)
     {
      int p = 4 - (str.Length % 4);
      string s = str;
      if (p != 4) { s += new string('=', p); }
      s = s.Replace('_', '/').Replace('-', '+');
      return Convert.FromBase64String(s);
     }
    }

    ini ファイルなら、+ → _ や / → - の置き換えは無くても大丈夫かも。
記事No.85599 のレス /過去ログ146より / 関連記事表示
削除チェック/

■85619  Re[5]: 間違いを教えてください。
□投稿者/ 夜叉丸 -(2017/11/10(Fri) 13:55:14)
    No85618 (魔界の仮面弁士 さん) に返信

    はっきりとは理解できていないのですが、
    char を介してコピーを行うと
    文字列としての特殊な処理がされるということでしょうか?

    何らかの方法にて byte[n] → string[n] のコピーは可能なのでしょうか?

記事No.85599 のレス /過去ログ146より / 関連記事表示
削除チェック/

■85621  Re[6]: 間違いを教えてください。
□投稿者/ furu -(2017/11/10(Fri) 15:10:48)
    No85619 (夜叉丸 さん) に返信
    > ■No85618 (魔界の仮面弁士 さん) に返信
    >
    > 何らかの方法にて byte[n] → string[n] のコピーは可能なのでしょうか?
    >
    byte[n] →stringの間違い?

    byte(符号なし8ビット整数)からchar(16ビット数)へはコピー可能なので
    byte[n]からstringへのコピーは可能です。

    逆(string→byte[n])は
    各文字がU+0000 〜 U+00FFの範囲であるならば可能です。
記事No.85599 のレス /過去ログ146より / 関連記事表示
削除チェック/

■85620  Re[3]: 間違いを教えてください。
□投稿者/ とっちゃん -(2017/11/10(Fri) 15:02:57)
    No85619 (夜叉丸 さん) に返信

    > はっきりとは理解できていないのですが、
    > char を介してコピーを行うと
    > 文字列としての特殊な処理がされるということでしょうか?
    >
    .NET の char は、2バイトのデータ型です。
    C++ の wchar_t と同等で、データサイズは unsigned short と同じです。
    また、格納されているものは文字コードという前提で作られています。

    それと、string や、"..." は文字列型や文字列であって、文字配列ではありません。

    C や C++ は"..."は文字列と表記しますが実際は「\0で終わる文字の配列」という特殊な配列です。
    std::string のように文字列型を用いる場合でも、リテラルなデータは文字の配列であることに変わりはありません。

    ソースコードというテキストデータ上では同じ表現を用いていますが
    コンパイルされ、実行中のメモリの状態は異なる概念であることも注意が必要でしょう。



    > 何らかの方法にて byte[n] → string[n] のコピーは可能なのでしょうか?


    「n個の要素を持つバイトの配列」を 「n個の要素を持つ文字列の配列」にコピーするのですか?
    それとも
    「バイト配列のn番目の要素」を「stringのn番目の要素」としてコピーするのですか?

    どちらとも読めますが、これまでここについて明確にこうであるとは記述されていないように思います。
    (だからプログラムも怪しい)

    INIファイルにDataTableのレコード(あるいはデータブロックそのもの)を格納するのはどうなの?とも思いますが。。。

    自分の過去に携わってきたものとか、ここ30年余りのINIファイルの扱われ方などを考慮すると

    INI形式のファイルの特定のエントリーに、バイナリデータをバイナリチックな文字列として格納しておく
    という可能性が考えられます。

    構造としては... ■No85610 の DynamicToString の文字列化部分は

    // byte[] → string
    string strvalue = "";
    for (int isnum = 0; isnum < sstream.ToArray().Length; isnum++) strvalue += (char)sstream.ToArray()[isnum];

    ではなく、
    foreach( var ch in sstream.ToArray() ) strvalue += ch.ToString( "X2" );
    という感じが本来意図していた変換処理なのではないでしょうか?

    これだと byte[] の2倍になりますが30年くらい前のコードでもよく使われていた形式なので
    テキストデータで維持するのが目的になってるなら使うこともできると思います。

    個人的にはほかの人も書いているように BASE64 などの形式のほうがいいと思いますが
    互換性問題が出る気もするのでとりあえずは言及しないことにします。
記事No.85599 のレス /過去ログ146より / 関連記事表示
削除チェック/

■85623  Re[4]: 間違いを教えてください。
□投稿者/ 夜叉丸 -(2017/11/10(Fri) 16:40:46)
    ありがとうございました。

    逆変換が文字として処理されるためうまくいかないんですね。

    やはり、16進数に変換して文字列にします。
記事No.85599 のレス / END /過去ログ146より / 関連記事表示
削除チェック/

■88731  Re[1]: 文字化けする画像ファイルヘッダー
□投稿者/ 魔界の仮面弁士 -(2018/09/22(Sat) 14:29:16)
    No88724 (ひょっとこ さん) に返信
    > どこのサイトで調べたのかは忘れましたが、
    > 以下のコードでヘッダーからファイル名を取得することができます。
    
    恐らく下記では無いでしょうか。見覚えはありますか?
    http://www.atmarkit.co.jp/fdotnet/dotnettips/618downnoname/downnoname.html
    
    上記には URL$ という名の引数は出てこないので、自前で書き直した記憶が無ければ、
    上記を元に二次加工されたソースだったのかも知れませんが。
    
    
    > Dim req As HttpWebRequest = CType(WebRequest.Create(URL), HttpWebRequest)
    今回のように、ヘッダー情報を読み取ることだけを目的としているのであれば、
    HTTP GET のままリクエストするのではなく、
     req.Method = System.Net.Http.HttpMethod.Head.Method
     'req.Method = "HEAD"
    のように HTTP HEAD メソッドに変更してリクエストするべきかと思います。
    
    
    > DSC_0063 - コピー北國新聞社社長賞.JPG
    > このファイル名はHTMLファイル内には記述していないので
    > 恐らく、ファイルヘッダーから取得したのだと思います。
    
    参照されているのは、ファイルヘッダーではなく、HTTP 応答ヘッダーですね。
    
    http://cms1.ishikawa-c.ed.jp/~shough/NC2/htdocs/?action=common_download_main&upload_id=4537
    の画像では Exif 情報も削除されているため、ファイルヘッダーからは取得できないはず。
    
    
    該当の URL にアクセスすると、Web サーバーから下記の応答が返されることを確認しました。(一部抜粋)
    
    HTTP/1.1 200 OK
    Date: Sat, 22 Sep 2018 01:46:42 GMT
    Server: Apache/2.2.15 (CentOS)
    Content-disposition: inline; filename="DSC_0063 - コピー北國新聞社社長賞.JPG"
    Content-Length: 85599
    Connection: close
    Content-Type: image/jpeg
    
    
    この時、filename= の後続のカナ漢字部分が UTF-8 エンコーディングになっていたので、
    これが文字化けの原因ですね。
    
    そしてこれは、Web サーバー側の処理に問題があるように思います。
    
    HTTP ヘッダでの利用が許可されているのは、現時点では ISO-8859-1 のみですので、
    UTF-8 でエンコードされた文字列が返されるのは、本来は NG のはずです。
    
    2011年6月に RFC 6266 で定められるまでは、ファイル名に使われる非 ASCII 文字を
    Content-Disposition: にどのように組み込むかが明確に定義されておらず、
    各ブラウザーで解釈が異なっていたのですけれど、それは昔の話。
    
    現在では、日本語ファイル名なら RFC 6266 / RFC 5987 に従って、filename= ではなく filename*= を用いた
    Content-disposition: inline; filename*=utf-8'ja-jp'DSC_0063%20-%20%E3%82%B3%E3%83%94%E3%83%BC%E5%8C%97%E5%9C%8B%E6%96%B0%E8%81%9E%E7%A4%BE%E7%A4%BE%E9%95%B7%E8%B3%9E.JPG
    などの応答を Web サーバーが返却するのが正しい手順であろうかと思います。
    (ブラウザーによっては、"%20" の部分が " " にデコードされずに残る事もあるようですが)
    
    
    もしも仮に、上記のヘッダーで返却されていたのだとしたら、受信した文字列を
    下記の Uri.UnescapeDataString などでデコードすることで、正しく取得できるようになる見込みです。
    https://dobon.net/vb/dotnet/internet/urlencode.html
    
    ただしサーバーの実装が正しかったとしても、filename*= で utf-8 以外が指定されていた場合は、
    HttpUtility.UrlDecodeToBytes(String, Encoding) してから
    Encoding.Unicode.GetString( Byte() ) で復元する必要がありますし、
    そもそも No88724 の正規表現のままでは不足なので、いずれにしてももう少し手直しは必要です。
    
    
    
    閑話休題。
    
    話をまとめると、文字化けの原因は、サーバー側がファイル名 UTF-8 で返しているからであり、
    それを取得するための機能は、WebRequest クラスには存在しないという結論になります。
    
    WebRequest クラスには、ContentEncoding ならありますが、
    HeaderEncoding プロパティはありませんので…。
    
    
    代替手段を考えてみたのですが、今のところは、サーバーと会話する処理を
    自前で書くぐらいしか思い当たりませんでした。
    
    以下は、リダイレクトやエラー処理、SSL 対応、プロキシ指定等は考慮せず、
    あくまでも今回の URL に限定させた最低限の手抜き実装ですが、一応参考までに。
    
    
    'Imports System
    'Imports System.IO
    'Imports System.Net
    'Imports System.Net.Sockets
    'Imports System.Text
    'Imports System.Text.RegularExpressions
    
    Function AcquireFileNameFromUTF8Header(url As String) As String
        Dim headers As String()
    
        Dim u As New Uri(url)
        Using client As New TcpClient()
            client.Connect(u.Host, u.Port)
            Using stm As NetworkStream = client.GetStream()
                Dim wrt As New StreamWriter(stm)
                wrt.WriteLine("HEAD " & u.ToString() & " HTTP/1.1")
                wrt.WriteLine("Host: " & u.Host)
                wrt.WriteLine("Connection: close")
                wrt.WriteLine("")
                wrt.WriteLine("")
                wrt.WriteLine("")
                wrt.Flush()
    
                'UTF-8 で喋るサイトのために、無理矢理 UTF-8 でデコードしています。
                Dim rdr As New StreamReader(stm, Encoding.UTF8)
                headers = rdr.ReadToEnd().Split(New String() {vbCrLf}, StringSplitOptions.RemoveEmptyEntries)
            End Using
        End Using
    
        Dim cd = headers.FirstOrDefault(Function(h) h.ToLowerInvariant().StartsWith("content-disposition:"))
        If Not String.IsNullOrWhiteSpace(cd) Then
            'ここの正規表現は、元の正規表現のままで、特に弄っていません。
            Dim re As New Regex( _
                      "filename\s*=\s*           " & _
                      "(?:                       " & _
                      "  ""(?<filename>[^""]*)"" " & _
                      "  |                       " & _
                      "  (?<filename>[^;]*)      " & _
                      ")                         " _
                      , RegexOptions.IgnoreCase _
                  Or RegexOptions.IgnorePatternWhitespace)
    
            Dim m As Match = re.Match(cd)
            If m.Success Then
                Return m.Groups("filename").Value
            End If
        End If
        Return String.Empty
    End Function
記事No.88724 のレス /過去ログ152より / 関連記事表示
削除チェック/

次の20件>

<< 0 | 1 >>

パスワード/

- Child Tree -